   "generate a map of the usage stats for this instance"
   []
   (merge (instance-settings)
-           {:uuid anonymous-id :timestamp (new java.util.Date)}
-            {:stats {:user (user-metrics)
-                     :question (question-metrics)
-                     :dashboard (dashboard-metrics)
-                     :database (database-metrics)
-                     :table (table-metrics)
-                     :field (field-metrics)
-                     :pulse (pulse-metrics)
-                     :segment (segment-metrics)
-                     :metric (metric-metrics)
-                     :group (group-metrics)
-                     :label (label-metrics)
-                     :collection (collection-metrics)
-                     :execution (execution-metrics)}}))
+         {:uuid anonymous-id, :timestamp (java.util.Date.)}
+         {:stats {:user       (user-metrics)
+                  :question   (question-metrics)
+                  :dashboard  (dashboard-metrics)
+                  :database   (database-metrics)
+                  :table      (table-metrics)
+                  :field      (field-metrics)
+                  :pulse      (pulse-metrics)
+                  :segment    (segment-metrics)
+                  :metric     (metric-metrics)
+                  :group      (group-metrics)
+                  :label      (label-metrics)
+                  :collection (collection-metrics)
+                  :execution  (execution-metrics)}}))
 
 
 (defn- send-stats!



(defn- bin-small-number
  "Return small bin number. Assumes positive inputs"
  [x]
  (cond
    (= 0 x) "0"
    (<= 1 x 5) "1-5"
    (<= 6 x 10) "6-10"
    (<= 11 x 25) "11-25"
    (> x 25) "25+"))

(defn- bin-medium-number
  "Return medium bin number. Assumes positive inputs"
  [x]
  (cond
    (= 0 x) "0"
    (<= 1 x 5) "1-5"
    (<= 6 x 10) "6-10"
    (<= 11 x 25) "11-25"
    (<= 26 x 50) "26-50"
    (<= 51 x 100) "51-100"
    (<= 101 x 250) "101-250"
    (> x 250) "250+"))


(defn- bin-large-number
  "Return large bin number. Assumes positive inputs"
  [x]
  (cond
    (= 0 x) "0"
    (< x 1) "< 1"
    (<= 1 x 10) "1-10"
    (<= 11 x 50) "11-50"
    (<= 51 x 250) "51-250"
    (<= 251 x 1000) "251-1000"
    (<= 1001 x 10000) "1001-10000"
    (> x 10000) "10000+"))

(defn- value-frequencies
  "go through a bunch of maps and count the frequency a given key's values"
  [many-maps k]
  (frequencies (map k many-maps)))

(defn- histogram
  "Bin some frequencies using a passed in binning function"
  [binning-fn many-maps k]
  (frequencies (map binning-fn (vals (value-frequencies many-maps k)))))

(def micro-histogram
  "Return a histogram for micro numbers"
  (partial histogram bin-micro-number))

(def small-histogram
  "Return a histogram for small numbers"
  (partial histogram bin-small-number))

(def medium-histogram
  "Return a histogram for medium numbers"
  (partial histogram bin-medium-number))

(def large-histogram
  "Return a histogram for large numbers"
  (partial histogram bin-large-number))

(defn- instance-start-date
  "Pull up the first user account and use that date"
  []
  (db/select-one-field :date_joined 'User {:order-by [[:date_joined :desc]]}))

(defn- environment-type
  "Figure out what we're running under"
  []
  (cond
    (= (config/config-str :mb-client) "OSX") :osx
    (config/config-str :rds-hostname) :elastic-beanstalk
    (config/config-str :database-url) :heroku ;; Putting this last as 'database-url' seems least specific
    :default :unknown))

(defn- instance-settings
  "Figure out global info about his instance"
  []
  {:version               (config/mb-version-info :tag)
   :running_on            (environment-type)
   :application_database  (config/config-str :mb-db-type)
   :check_for_updates     (setting/get :check-for-updates)
   :site_name             (not= (public-settings/site-name) "Metabase")
   :report_timezone       (setting/get :report-timezone)
   :friendly_names        (humanization/enable-advanced-humanization)
   :email_configured      ((resolve 'metabase.email/email-configured?))
   :slack_configured      ((resolve 'metabase.integrations.slack/slack-configured?))
   :sso_configured        (boolean ((resolve 'metabase.api.session/google-auth-client-id)))
   :instance_started      (instance-start-date)
   :has_sample_data       (db/exists? 'Database, :is_sample true)})

;; util function
(def add-summaries
  "add up some dictionaries"
  (partial merge-with +))

;; User metrics
(defn- user-dims
  "characterize a user record"
  [user]
  {:total 1
   :active (if (:is_active user) 1 0) ;; HOW DO I GET THE LIST OF ALL USERS INCLUDING INACTIVES?
   :admin (if (:is_superuser user) 1 0)
   :logged_in (if (nil? (:last_login user)) 0 1)
   :sso (if (nil? (:google_auth user)) 0 1)})


(defn- user-metrics
  "Get metrics based on user records
  TODO: get activity in terms of created questions, pulses and dashboards"
  []
  (let [users (db/select ['User :is_active :is_superuser :last_login :google_auth])]
    {:users (apply add-summaries (map user-dims users))}))



  "Get mes based on pulses
  TODO: characterize by non-user account emails, # emails"
  []
  (let [pulses         (db/select [Pulse :id :creator_id])
        pulse-cards    (db/select [PulseCard :id :card_id :pulse_id])
        pulse-channels (db/select [PulseChannel :channel_type :schedule_type])]
    {:pulses               (count pulses)
     :pulse_types          (frequencies (map :channel_type pulse-channels))
     :pulse_schedules      (frequencies (map :schedule_type pulse-channels))
     :num_pulses_per_user  (medium-histogram pulses :creator_id)
     :num_pulses_per_card  (medium-histogram pulse-cards :card_id)
     :num_cards_per_pulses (medium-histogram pulse-cards :pulse_id)}))


(defn- label-metrics
  "Get metrics based on labels"
  []
  (let [card-labels (db/select [CardLabel :card_id :label_id])]
    {:labels              (db/count Label)
     :num_labels_per_card (micro-histogram card-labels :card_id)
     :num_cards_per_label (medium-histogram card-labels :label_id)}))


(defn- collection-metrics
  "Get metrics on collection usage"
  []
  (let [collections (db/select Collection)
        cards       (db/select [Card :collection_id])]
    {:collections              (count collections)
     :cards_in_collections     (count (filter (comp nil?) (map :collection_id cards)))
     :cards_not_in_collections (count (filter nil? (map :collection_id cards)))
     :num_cards_per_collection (medium-histogram cards :collection_id)}))

;; Metadata Metrics
(defn- database-dims
  "characterize a database record"
  [database]
  {:total    1
   :analyzed (one-if (:is_full_sync database))})

(defn- database-metrics
  "Get metrics based on databases"
  []
  (let [databases (db/select [Database :id :is_full_sync])]
    {:databases (apply add-summaries (map database-dims databases))}))


(defn- table-metrics
  "Get metrics based on tables"
  []
  (let [tables (db/select [Table :id :db_id :schema])]
    {:tables           (count tables)
     :num_per_database (medium-histogram tables :db_id)
     :num_per_schema   (medium-histogram tables :schema)}))


(defn- field-metrics
  "Get metrics based on fields"
  []
  (let [fields (db/select [Field :table_id])]
    {:fields        (count fields)
     :num_per_table (medium-histogram fields :table_id)}))

(defn- segment-metrics
  "Get metrics based on segments."
  []
  {:segments (db/count Segment)})


(defn- metric-metrics
  "Get metrics based on metrics"
  []
  {:metrics (db/count Metric)})


(defn- bin-latencies
