Source

metrics-clojure / metrics-clojure-ring / src / metrics / ring / expose.clj

(ns metrics.ring.expose
  (:import (com.yammer.metrics.core Gauge Timer Counter Histogram Meter))
  (:require [metrics.gauges :as gauges]
            [metrics.meters :as meters]
            [metrics.histograms :as histograms]
            [metrics.counters :as counters]
            [metrics.timers :as timers])
  (:use [ring.util.response :only [header response]]
        [metrics.utils :only [all-metrics]]
        [cheshire.core :only [generate-string]]))


; Define rendering protocol ---------------------------------------------------
(defprotocol RenderableMetric
  (render-to-basic [metric] "Turn a metric into a basic Clojure datastructure."))

(extend-type Gauge
  RenderableMetric
  (render-to-basic [g]
    {:type :gauge
     :value (gauges/value g)}))

(extend-type Timer
  RenderableMetric
  (render-to-basic [t]
    {:type :timer
     :rates (timers/rates t)
     :percentiles (timers/percentiles t)
     :max (timers/largest t)
     :min (timers/smallest t)
     :mean (timers/mean t)
     :standard-deviation (timers/std-dev t)}))

(extend-type Meter
  RenderableMetric
  (render-to-basic [m]
    {:type :meter
     :rates (meters/rates m)}))

(extend-type Histogram
  RenderableMetric
  (render-to-basic [h]
    {:type :histogram
     :max (histograms/largest h)
     :min (histograms/smallest h)
     :mean (histograms/mean h)
     :standard-deviation (histograms/std-dev h)
     :percentiles (histograms/percentiles h)}))

(extend-type Counter
  RenderableMetric
  (render-to-basic [c]
    {:type :counter
     :value (counters/value c)}))


; Utils -----------------------------------------------------------------------
(defn- ensure-leading-slash [s]
  (if (not= \/ (first s))
    (str \/ s)
    s))

(defn- strip-trailing-slash [s]
  (if (= \/ (last s))
    (apply str (butlast s))
    s))

(defn- sanitize-uri [uri]
  (str (-> uri
         ensure-leading-slash
         strip-trailing-slash)
       \/))

(defn- render-metric [[metric-name metric]]
  [metric-name (render-to-basic metric)])


; Exposing --------------------------------------------------------------------
(defn- metrics-json [request]
  (let [metrics-map (into {} (map render-metric (all-metrics)))
        json (generate-string metrics-map)]
    (-> (response json)
      (header "Content-Type" "application/json"))))

(defn expose-metrics-as-json
  ([handler]
     (expose-metrics-as-json handler "/metrics"))
  ([handler uri]
   (fn [request]
     (let [request-uri (:uri request)]
       (if (or (.startsWith request-uri (sanitize-uri uri))
               (= request-uri uri))
         (metrics-json request)
         (handler request))))))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.