Steve Losh avatar Steve Losh committed 26d62ce

Move the ring repo into this one.

Comments (0)

Files changed (35)

metrics-clojure-core/project.clj

+(defproject metrics-clojure "0.7.1-SNAPSHOT"
+  :description "A Clojure façade for Coda Hale's metrics library."
+  :dependencies [[org.clojure/clojure "[1.2.1,1.3.0]"]
+                 [com.yammer.metrics/metrics-core "2.0.1"]]
+  :repositories {"repo.codahale.com" "http://repo.codahale.com"}
+  :warn-on-reflection true)

metrics-clojure-core/src/metrics/core.clj

+(ns metrics.core
+  (:use [metrics.utils :only (metric-name)])
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.reporting ConsoleReporter))
+  (:import (java.util.concurrent TimeUnit)))
+
+
+(defn remove-metric
+  "Remove the metric with the given title."
+  [title]
+  (.removeMetric (Metrics/defaultRegistry) (metric-name title)))
+
+
+(defn report-to-console
+  "Report all metrics to standard out every few seconds."
+  [seconds]
+  (ConsoleReporter/enable seconds TimeUnit/SECONDS))
+
+

metrics-clojure-core/src/metrics/counters.clj

+(ns metrics.counters
+  (:use [metrics.utils :only (metric-name)])
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.core Counter)))
+
+
+; Create ----------------------------------------------------------------------
+(defn counter
+  "Create and return a new Counter metric with the given title.
+
+  Title can be a plain string like \"foo\" or a vector of three strings like:
+
+      [\"myapp\" \"webserver\" \"connections\"]
+
+  "
+  [title]
+  (Metrics/newCounter (metric-name title)))
+
+
+; Read ------------------------------------------------------------------------
+(defn value
+  "Return the current value of the counter."
+  [^Counter c]
+  (.count c))
+
+
+; Write -----------------------------------------------------------------------
+(defn inc!
+  "Increment the counter by the given amount (or 1 if not specified)."
+  ([^Counter c] (inc! c 1))
+  ([^Counter c n]
+   (.inc c n)
+   c))
+
+(defn dec!
+  "Decrement the counter by the given amount (or 1 if not specified)."
+  ([^Counter c] (dec! c 1))
+  ([^Counter c n]
+   (.dec c n)
+   c))
+
+(defn clear!
+  "Clear the given counter, resetting its value to zero."
+  [^Counter c]
+  (.clear c)
+  c)
+

metrics-clojure-core/src/metrics/gauges.clj

+(ns metrics.gauges
+  (:use [metrics.utils :only (metric-name)])
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.core Gauge)))
+
+
+; Create ----------------------------------------------------------------------
+(defmacro gauge
+  "Create a new Gauge metric with the given title.
+
+  The body exprs will be used to retrieve the value of the Gauge when requested."
+  [title & body]
+  `(Metrics/newGauge (metric-name ~title)
+                     (proxy [Gauge] []
+                       (value [] (do ~@body)))))
+
+
+; Read ------------------------------------------------------------------------
+(defn gauge-fn
+  "Create a new Gauge metric with the given title.
+
+  The given function will be called (with no arguments) to retrieve the value of
+  the Gauge when requested."
+  [title f]
+  (Metrics/newGauge (metric-name title)
+                    (proxy [Gauge] []
+                      (value [] (f)))))
+
+
+; Read ------------------------------------------------------------------------
+(defn value
+  "Return the value of the given Gauge."
+  [^Gauge g]
+  (.value g))
+

metrics-clojure-core/src/metrics/histograms.clj

+(ns metrics.histograms
+  (:use [metrics.utils :only (metric-name get-percentiles)])
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.core Histogram MetricName)))
+
+
+; Create ----------------------------------------------------------------------
+(defn histogram
+  "Create and return a Histogram metric with the given title.
+
+  By default a biased Histogram is created.  This is probably what you want, but
+  if you know what you're doing you can pass false to create a uniform one
+  instead."
+  ([title] (histogram title true))
+  ([title biased]
+   (Metrics/newHistogram
+     ^MetricName (metric-name title)
+     (boolean biased))))
+
+
+; Read ------------------------------------------------------------------------
+(defn mean
+  "Return the mean value of the given Histogram."
+  [^Histogram h]
+  (.mean h))
+
+(defn std-dev
+  "Return the standard deviation of the given Histogram."
+  [^Histogram h]
+  (.stdDev h))
+
+(defn percentiles
+  "Return a mapping of percentiles to their values for the given Histogram.
+
+  For example:
+
+    (percentiles myhistogram [0.5 0.9 1.0])
+    ;=> {0.5 200, 0.9 240, 1.0 500}
+
+  This means that:
+
+  * 50% of the values recorded by this Histogram were less than or equal to 200
+  * 90% were less than or equal to 240
+  * 100% were less than or equal to 500
+
+  If you don't pass a list of desired percentiles, the default will be
+  [0.75 0.95 0.99 0.999 1.0]."
+  ([^Histogram h]
+   (percentiles h [0.75 0.95 0.99 0.999 1.0]))
+  ([^Histogram h ps]
+   (get-percentiles h ps)))
+
+
+(defn number-recorded
+  "Return the number of values recorded by the given Histogram."
+  [^Histogram h]
+  (.count h))
+
+(defn largest
+  "Return the largest value recorded by the given Histogram."
+  [^Histogram h]
+  (.max h))
+
+(defn smallest
+  "Return the smallest value recorded by the given Histogram."
+  [^Histogram h]
+  (.min h))
+
+(defn sample
+  "Return the values in the given Histogram's current sampling.
+
+  This is almost certainly NOT what you want.  Read up on how these histograms
+  work and make sure you understand it before using this function."
+  [^Histogram h]
+  (.getValues (.getSnapshot h)))
+
+
+; Write -----------------------------------------------------------------------
+(defn update!
+  "Record a value in the given Histogram."
+  [^Histogram h n]
+  (.update h (long n))
+  h)
+
+(defn clear!
+  "Clear all data from the given Histogram."
+  [^Histogram h]
+  (.clear h)
+  h)
+

metrics-clojure-core/src/metrics/meters.clj

+(ns metrics.meters
+  (:use [metrics.utils :only (metric-name)])
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.core Meter))
+  (:import (java.util.concurrent TimeUnit)))
+
+
+; Create ----------------------------------------------------------------------
+(defn meter [title event-type]
+  (Metrics/newMeter (metric-name title)
+                    event-type
+                    TimeUnit/SECONDS))
+
+
+; Read ------------------------------------------------------------------------
+(defn rates [^Meter m]
+  {1 (.oneMinuteRate m)
+   5 (.fiveMinuteRate m)
+   15 (.fifteenMinuteRate m)})
+
+(defn rate-one [^Meter m]
+  (.oneMinuteRate m))
+
+(defn rate-five [^Meter m]
+  (.fiveMinuteRate m))
+
+(defn rate-fifteen [^Meter m]
+  (.fifteenMinuteRate m))
+
+(defn rate-mean [^Meter m]
+  (.meanRate m))
+
+
+; Write -----------------------------------------------------------------------
+(defn mark!
+  ([^Meter m]
+   (mark! m 1))
+  ([^Meter m n]
+   (.mark m (long n))
+   m))
+

metrics-clojure-core/src/metrics/timers.clj

+(ns metrics.timers
+  (:use [metrics.utils :only (metric-name get-percentiles)])
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.core Timer MetricName))
+  (:import (java.util.concurrent TimeUnit)))
+
+
+; Create ----------------------------------------------------------------------
+(defn timer [title]
+  (Metrics/newTimer ^MetricName (metric-name title)
+                    TimeUnit/MILLISECONDS
+                    TimeUnit/SECONDS))
+
+
+; Read ------------------------------------------------------------------------
+(defn rates [^Timer m]
+  {1 (.oneMinuteRate m)
+   5 (.fiveMinuteRate m)
+   15 (.fifteenMinuteRate m)})
+
+(defn rate-one [^Timer m]
+  (.oneMinuteRate m))
+
+(defn rate-five [^Timer m]
+  (.fiveMinuteRate m))
+
+(defn rate-fifteen [^Timer m]
+  (.fifteenMinuteRate m))
+
+(defn rate-mean [^Timer m]
+  (.meanRate m))
+
+
+(defn mean [^Timer t]
+  (.mean t))
+
+(defn std-dev [^Timer t]
+  (.stdDev t))
+
+(defn percentiles
+  ([^Timer t]
+   (percentiles t [0.75 0.95 0.99 0.999 1.0]))
+  ([^Timer t ps]
+   (get-percentiles t ps)))
+
+
+(defn number-recorded [^Timer t]
+  (.count t))
+
+(defn largest [^Timer t]
+  (.max t))
+
+(defn smallest [^Timer t]
+  (.min t))
+
+(defn sample [^Timer t]
+  (.getValues (.getSnapshot t)))
+
+
+; Write -----------------------------------------------------------------------
+(defmacro time! [^Timer t & body]
+  `(.time ~(vary-meta t assoc :tag `Timer)
+         (proxy [Callable] []
+           (call [] (do ~@body)))))
+
+(defn time-fn! [^Timer t f]
+  (.time t
+         (proxy [Callable] []
+           (call [] (f)))))
+
+(defn clear! [^Timer t]
+  (.clear t))
+

metrics-clojure-core/src/metrics/utils.clj

+(ns metrics.utils
+  (:import (com.yammer.metrics Metrics))
+  (:import (com.yammer.metrics.core Sampling MetricName)))
+
+
+(defn get-percentile [^Sampling metric ^double percentile]
+  (-> metric
+    .getSnapshot
+    (.getValue percentile)))
+
+(defn get-percentiles [metric percentiles]
+  (zipmap percentiles
+           (map (partial get-percentile metric)
+                percentiles)))
+
+(defn metric-name ^MetricName [title]
+  (if (string? title)
+    (new MetricName "default" "default" ^String title)
+    (new MetricName
+         ^String (first title)
+         ^String (second title)
+         ^String (last title))))
+
+(defn all-metrics []
+  (letfn [(parse-name [metric-name]
+            (str (.getGroup metric-name)
+                 "." (.getType metric-name)
+                 "." (.getName metric-name)))
+          (parse-entry [[metric-name metric]]
+            [(parse-name metric-name)
+             metric])]
+    (into {} (map parse-entry (.allMetrics (Metrics/defaultRegistry))))))

metrics-clojure-core/test/metrics/test/core.clj

+(ns metrics.test.core
+  (:use [metrics.core])
+  (:use [clojure.test]))
+

metrics-clojure-core/test/metrics/test/counters.clj

+(ns metrics.test.counters
+  (:require [metrics.counters :as counters])
+  (:use [clojure.test]))
+
+
+(deftest test-inc
+  (let [c (counters/counter ["test" "counters" "test-inc"])]
+    (is (= (counters/value c) 0))
+    (counters/inc! c)
+    (is (= (counters/value c) 1))
+    (counters/inc! c 2)
+    (is (= (counters/value c) 3))))
+
+(deftest test-dec
+  (let [c (counters/counter ["test" "counters" "test-dec"])]
+    (is (= (counters/value c) 0))
+    (counters/dec! c)
+    (is (= (counters/value c) -1))
+    (counters/dec! c 2)
+    (is (= (counters/value c) -3))))
+
+(deftest test-clear
+  (let [c (counters/counter ["test" "counters" "test-clear"])]
+    (is (= (counters/value c) 0))
+    (counters/inc! c 100)
+    (is (= (counters/value c) 100))
+    (counters/clear! c)
+    (is (= (counters/value c) 0))))

metrics-clojure-core/test/metrics/test/gauges.clj

+(ns metrics.test.gauges
+  (:require [metrics.gauges :as gauges])
+  (:use [clojure.test]))
+
+
+(deftest test-gauge
+  (let [g (gauges/gauge ["test" "gauges" "test-gauge"]
+                        (+ 100 1))]
+    (is (= (gauges/value g) 101))))
+
+(deftest test-gauge-fn
+  (let [g (gauges/gauge-fn ["test" "gauges" "test-gauge-fn"]
+                           #(+ 100 2))]
+    (is (= (gauges/value g) 102))))

metrics-clojure-core/test/metrics/test/histograms.clj

+(ns metrics.test.histograms
+  (:require [metrics.histograms :as histograms])
+  (:use [metrics.test.utils])
+  (:use [clojure.test]))
+
+
+(deftest test-mean
+  (let [h (histograms/histogram ["test" "histograms" "test-mean"])]
+    (is (= (histograms/mean h) 0.0))
+    (histograms/update! h 5)
+    (is (= (histograms/mean h) 5.0))
+    (histograms/update! h 15)
+    (is (= (histograms/mean h) 10.0))))
+
+(deftest test-number-recorded
+  (let [h (histograms/histogram ["test" "histograms" "test-number-recorded"])]
+    (is (= (histograms/number-recorded h) 0))
+    (histograms/update! h 0)
+    (is (= (histograms/number-recorded h) 1))
+    (histograms/update! h 0)
+    (is (= (histograms/number-recorded h) 2))))
+
+(deftest test-std-dev
+  (let [h (histograms/histogram ["test" "histograms" "test-std-dev"])]
+    (is (= (histograms/std-dev h) 0.0))
+    (histograms/update! h 2)
+    (histograms/update! h 4)
+    (histograms/update! h 6)
+    (is (= (histograms/std-dev h) 2.0))))
+
+(deftest test-smallest
+  (let [h (histograms/histogram ["test" "histograms" "test-smallest"])]
+    (is (= (histograms/smallest h) 0.0))
+    (histograms/update! h 1)
+    (histograms/update! h 9)
+    (histograms/update! h 3)
+    (is (= (histograms/smallest h) 1.0))))
+
+(deftest test-largest
+  (let [h (histograms/histogram ["test" "histograms" "test-largest"])]
+    (is (= (histograms/largest h) 0.0))
+    (histograms/update! h 1)
+    (histograms/update! h 9)
+    (histograms/update! h 3)
+    (is (= (histograms/largest h) 9.0))))
+
+(deftest test-percentiles
+  (let [h (histograms/histogram ["test" "histograms" "test-percentiles"])]
+    (is (maps-within-one (histograms/percentiles h)
+                    {0.75 0, 0.95 0, 0.99 0, 0.999 0, 1.00 0}))
+
+    (dorun (map (partial histograms/update! h) (range 1 101)))
+
+    (is (maps-within-one (histograms/percentiles h)
+                    {0.75 75, 0.95 95, 0.99 99, 0.999 100, 1.00 100}))
+
+    (is (maps-within-one (histograms/percentiles h [0.10 0.50])
+                    {0.10 10, 0.50 50}))))
+
+(deftest test-clear
+  (let [h (histograms/histogram ["test" "histograms" "test-clear"])]
+    (is (= (histograms/mean h) 0.0))
+    (histograms/update! h 5)
+    (is (= (histograms/mean h) 5.0))
+    (histograms/clear! h)
+    (is (= (histograms/mean h) 0.0))))
+

metrics-clojure-core/test/metrics/test/meters.clj

+(ns metrics.test.meters
+  (:require [metrics.meters :as meters])
+  (:use [metrics.test.utils])
+  (:use [clojure.test]))
+
+
+(deftest test-rate-mean
+  (let [m (meters/meter ["test" "meters" "test-rate-mean"] "test-events")]
+    (is (= (meters/rate-mean m) 0.0))
+    (meters/mark! m)
+    (is (> (meters/rate-mean m) 0.0))))
+
+(deftest test-rate-mean-update-multiple
+  (let [m (meters/meter ["test" "meters" "test-rate-mean-update-multiple"] "test-events")]
+    (is (= (meters/rate-mean m) 0.0))
+    (meters/mark! m 10)
+    (is (> (meters/rate-mean m) 0.0))))
+
+(deftest test-rate-one
+  (let [m (meters/meter ["test" "meters" "test-rate-one"] "test-events")]
+    (is (= (meters/rate-one m) 0.0))
+    (meters/mark! m 20000)
+    (Thread/sleep 8000)
+    (is (> (meters/rate-one m) 0.0))))
+
+(deftest test-rate-five
+  (let [m (meters/meter ["test" "meters" "test-rate-five"] "test-events")]
+    (is (= (meters/rate-five m) 0.0))
+    (meters/mark! m 20000)
+    (Thread/sleep 8000)
+    (is (> (meters/rate-five m) 0.0))))
+
+(deftest test-rate-fifteen
+  (let [m (meters/meter ["test" "meters" "test-rate-fifteen"] "test-events")]
+    (is (= (meters/rate-fifteen m) 0.0))
+    (meters/mark! m 20000)
+    (Thread/sleep 8000)
+    (is (> (meters/rate-fifteen m) 0.0))))
+
+(deftest test-rates
+  (let [m (meters/meter ["test" "meters" "test-rates"] "test-events")]
+    (is (every? zero? (vals (meters/rates m))))
+    (meters/mark! m 20000)
+    (Thread/sleep 8000)
+    (is (every? #(> % 0.0) (vals (meters/rates m))))))

metrics-clojure-core/test/metrics/test/timers.clj

+(ns metrics.test.timers
+  (:require [metrics.timers :as timers])
+  (:use [metrics.test.utils])
+  (:use [clojure.test]))
+
+
+(defn- sleep-100 []
+  (Thread/sleep 100)
+  100)
+
+(defn- sleep-200 []
+  (Thread/sleep 200)
+  200)
+
+
+(deftest test-rate-mean
+  (let [t (timers/timer ["test" "timers" "test-rate-mean"])]
+    (is (= (timers/rate-mean t) 0.0))
+    (is (= (timers/time! t (sleep-100)) 100))
+    (is (> (timers/rate-mean t) 0.0))))
+
+(deftest test-rate-mean-fn
+  (let [t (timers/timer ["test" "timers" "test-rate-mean-fn"])]
+    (is (= (timers/rate-mean t) 0.0))
+    (is (= (timers/time-fn! t sleep-100) 100))
+    (is (> (timers/rate-mean t) 0.0))))
+
+(deftest test-rate-one
+  (let [t (timers/timer ["test" "timers" "test-rate-one"])]
+    (is (= (timers/rate-one t) 0.0))
+    (is (= (timers/time! t (sleep-100)) 100))
+    (Thread/sleep 8000)
+    (is (> (timers/rate-one t) 0.0))))
+
+(deftest test-rate-five
+  (let [t (timers/timer ["test" "timers" "test-rate-five"])]
+    (is (= (timers/rate-five t) 0.0))
+    (is (= (timers/time! t (sleep-100)) 100))
+    (Thread/sleep 8000)
+    (is (> (timers/rate-five t) 0.0))))
+
+(deftest test-rate-fifteen
+  (let [t (timers/timer ["test" "timers" "test-rate-fifteen"])]
+    (is (= (timers/rate-fifteen t) 0.0))
+    (is (= (timers/time! t (sleep-100)) 100))
+    (Thread/sleep 8000)
+    (is (> (timers/rate-fifteen t) 0.0))))
+
+
+(deftest test-largest
+  (let [t (timers/timer ["test" "timers" "test-largest"])]
+    (is (= (timers/largest t) 0.0))
+    (is (= (timers/time! t (sleep-100)) 100))
+    (is (within-ten (timers/largest t) 100.0))
+    (is (= (timers/time! t (sleep-200)) 200))
+    (is (within-ten (timers/largest t) 200.0))))
+
+(deftest test-smallest
+  (let [t (timers/timer ["test" "timers" "test-smallest"])]
+    (is (= (timers/smallest t) 0.0))
+    (is (= (timers/time! t (sleep-100)) 100))
+    (is (within-ten (timers/smallest t) 100.0))
+    (is (= (timers/time! t (sleep-200)) 200))
+    (is (within-ten (timers/smallest t) 100.0))))

metrics-clojure-core/test/metrics/test/utils.clj

+(ns metrics.test.utils)
+
+(defn abs [n]
+  (if (> n 0) n (* -1 n)))
+
+(defn within-one [a b]
+  (<= (abs (- a b))
+      1))
+
+(defn within-ten [a b]
+  (<= (abs (- a b))
+      10))
+
+(defn maps-within-one [a b]
+  (when (= (set (keys a)) (set (keys b)))
+    (every? identity
+            (map #(within-one (a %) (b %))
+                 (keys a)))))
+

metrics-clojure-ring/project.clj

+(defproject metrics-clojure-ring "0.7.1-SNAPSHOT"
+  :description "Various things gluing together metrics-clojure and ring."
+  :dependencies [[cheshire "2.2.2"]
+                 [metrics-clojure "0.7.0"]])

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])
+  (:require [metrics.meters :as meters])
+  (:require [metrics.histograms :as histograms])
+  (:require [metrics.counters :as counters])
+  (:require [metrics.timers :as timers])
+  (:use [ring.util.response :only [header response]])
+  (:use [metrics.utils :only [all-metrics]])
+  (:use [cheshire.core :only [generate-string]]))
+
+
+(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)}))
+
+(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)])
+
+(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]
+   (let [uri (sanitize-uri uri)]
+     (fn [request]
+       (if (.startsWith (:uri request) uri)
+         (metrics-json request)
+         (handler request))))))
+

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

+(ns metrics.ring.instrument
+  (:use [metrics.counters :only (counter inc! dec!)]
+        [metrics.meters :only (meter mark!)]
+        [metrics.timers :only (timer time!)]))
+
+(defn- mark-in! [metric-map k]
+  (when-let [metric (metric-map k)]
+    (mark! metric)))
+
+(defn instrument
+  "Instrument a ring handler.
+
+  This middleware should be added as late as possible for maximum effect."
+  ([handler]
+   (let [active-requests (counter ["ring" "requests" "active"])
+         requests (meter ["ring" "requests" "rate"] "requests")
+         responses (meter ["ring" "responses" "rate"] "responses")
+         statuses {2 (meter ["ring" "responses" "rate.2xx"] "responses")
+                   3 (meter ["ring" "responses" "rate.3xx"] "responses")
+                   4 (meter ["ring" "responses" "rate.4xx"] "responses")
+                   5 (meter ["ring" "responses" "rate.5xx"] "responses")}
+         times {:get     (timer ["ring" "handling-time" "GET"])
+                :put     (timer ["ring" "handling-time" "PUT"])
+                :post    (timer ["ring" "handling-time" "POST"])
+                :head    (timer ["ring" "handling-time" "HEAD"])
+                :delete  (timer ["ring" "handling-time" "DELETE"])
+                :options (timer ["ring" "handling-time" "OPTIONS"])}
+         request-methods {:get     (meter ["ring" "requests" "rate.GET"] "requests")
+                          :put     (meter ["ring" "requests" "rate.PUT"] "requests")
+                          :post    (meter ["ring" "requests" "rate.POST"] "requests")
+                          :head    (meter ["ring" "requests" "rate.HEAD"] "requests")
+                          :delete  (meter ["ring" "requests" "rate.DELETE"] "requests")
+                          :options (meter ["ring" "requests" "rate.OPTIONS"] "requests")}]
+     (fn [request]
+       (inc! active-requests)
+       (try
+         (let [request-method (:request-method request)]
+           (mark! requests)
+           (mark-in! request-methods request-method)
+           (let [resp (time! (times request-method)
+                             (handler request))
+                 status-code (or (:status resp) 404)]
+             (mark! responses)
+             (mark-in! statuses (int (/ status-code 100)))
+             resp))
+         (finally (dec! active-requests)))))))

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

+(ns metrics.rendering)
+
+
+(defprotocol RenderableMetric
+  (render-to-basic [metric] "Turn a metric into a basic Clojure datastructure."))
+
+(defn render-metric)
+

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

+(ns metrics-clojure-ring.test.core
+  (:use [metrics-clojure-ring.core])
+  (:use [clojure.test]))
+
+(deftest replace-me ;; FIXME: write
+  (is false "No tests have been written."))

project.clj

-(defproject metrics-clojure "0.7.1-SNAPSHOT"
-  :description "A Clojure façade for Coda Hale's metrics library."
-  :dependencies [[org.clojure/clojure "[1.2.1,1.3.0]"]
-                 [com.yammer.metrics/metrics-core "2.0.1"]]
-  :repositories {"repo.codahale.com" "http://repo.codahale.com"}
-  :warn-on-reflection true)

src/metrics/core.clj

-(ns metrics.core
-  (:use [metrics.utils :only (metric-name)])
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.reporting ConsoleReporter))
-  (:import (java.util.concurrent TimeUnit)))
-
-
-(defn remove-metric
-  "Remove the metric with the given title."
-  [title]
-  (.removeMetric (Metrics/defaultRegistry) (metric-name title)))
-
-
-(defn report-to-console
-  "Report all metrics to standard out every few seconds."
-  [seconds]
-  (ConsoleReporter/enable seconds TimeUnit/SECONDS))
-
-

src/metrics/counters.clj

-(ns metrics.counters
-  (:use [metrics.utils :only (metric-name)])
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.core Counter)))
-
-
-; Create ----------------------------------------------------------------------
-(defn counter
-  "Create and return a new Counter metric with the given title.
-
-  Title can be a plain string like \"foo\" or a vector of three strings like:
-
-      [\"myapp\" \"webserver\" \"connections\"]
-
-  "
-  [title]
-  (Metrics/newCounter (metric-name title)))
-
-
-; Read ------------------------------------------------------------------------
-(defn value
-  "Return the current value of the counter."
-  [^Counter c]
-  (.count c))
-
-
-; Write -----------------------------------------------------------------------
-(defn inc!
-  "Increment the counter by the given amount (or 1 if not specified)."
-  ([^Counter c] (inc! c 1))
-  ([^Counter c n]
-   (.inc c n)
-   c))
-
-(defn dec!
-  "Decrement the counter by the given amount (or 1 if not specified)."
-  ([^Counter c] (dec! c 1))
-  ([^Counter c n]
-   (.dec c n)
-   c))
-
-(defn clear!
-  "Clear the given counter, resetting its value to zero."
-  [^Counter c]
-  (.clear c)
-  c)
-

src/metrics/gauges.clj

-(ns metrics.gauges
-  (:use [metrics.utils :only (metric-name)])
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.core Gauge)))
-
-
-; Create ----------------------------------------------------------------------
-(defmacro gauge
-  "Create a new Gauge metric with the given title.
-
-  The body exprs will be used to retrieve the value of the Gauge when requested."
-  [title & body]
-  `(Metrics/newGauge (metric-name ~title)
-                     (proxy [Gauge] []
-                       (value [] (do ~@body)))))
-
-
-; Read ------------------------------------------------------------------------
-(defn gauge-fn
-  "Create a new Gauge metric with the given title.
-
-  The given function will be called (with no arguments) to retrieve the value of
-  the Gauge when requested."
-  [title f]
-  (Metrics/newGauge (metric-name title)
-                    (proxy [Gauge] []
-                      (value [] (f)))))
-
-
-; Read ------------------------------------------------------------------------
-(defn value
-  "Return the value of the given Gauge."
-  [^Gauge g]
-  (.value g))
-

src/metrics/histograms.clj

-(ns metrics.histograms
-  (:use [metrics.utils :only (metric-name get-percentiles)])
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.core Histogram MetricName)))
-
-
-; Create ----------------------------------------------------------------------
-(defn histogram
-  "Create and return a Histogram metric with the given title.
-
-  By default a biased Histogram is created.  This is probably what you want, but
-  if you know what you're doing you can pass false to create a uniform one
-  instead."
-  ([title] (histogram title true))
-  ([title biased]
-   (Metrics/newHistogram
-     ^MetricName (metric-name title)
-     (boolean biased))))
-
-
-; Read ------------------------------------------------------------------------
-(defn mean
-  "Return the mean value of the given Histogram."
-  [^Histogram h]
-  (.mean h))
-
-(defn std-dev
-  "Return the standard deviation of the given Histogram."
-  [^Histogram h]
-  (.stdDev h))
-
-(defn percentiles
-  "Return a mapping of percentiles to their values for the given Histogram.
-
-  For example:
-
-    (percentiles myhistogram [0.5 0.9 1.0])
-    ;=> {0.5 200, 0.9 240, 1.0 500}
-
-  This means that:
-
-  * 50% of the values recorded by this Histogram were less than or equal to 200
-  * 90% were less than or equal to 240
-  * 100% were less than or equal to 500
-
-  If you don't pass a list of desired percentiles, the default will be
-  [0.75 0.95 0.99 0.999 1.0]."
-  ([^Histogram h]
-   (percentiles h [0.75 0.95 0.99 0.999 1.0]))
-  ([^Histogram h ps]
-   (get-percentiles h ps)))
-
-
-(defn number-recorded
-  "Return the number of values recorded by the given Histogram."
-  [^Histogram h]
-  (.count h))
-
-(defn largest
-  "Return the largest value recorded by the given Histogram."
-  [^Histogram h]
-  (.max h))
-
-(defn smallest
-  "Return the smallest value recorded by the given Histogram."
-  [^Histogram h]
-  (.min h))
-
-(defn sample
-  "Return the values in the given Histogram's current sampling.
-
-  This is almost certainly NOT what you want.  Read up on how these histograms
-  work and make sure you understand it before using this function."
-  [^Histogram h]
-  (.getValues (.getSnapshot h)))
-
-
-; Write -----------------------------------------------------------------------
-(defn update!
-  "Record a value in the given Histogram."
-  [^Histogram h n]
-  (.update h (long n))
-  h)
-
-(defn clear!
-  "Clear all data from the given Histogram."
-  [^Histogram h]
-  (.clear h)
-  h)
-

src/metrics/meters.clj

-(ns metrics.meters
-  (:use [metrics.utils :only (metric-name)])
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.core Meter))
-  (:import (java.util.concurrent TimeUnit)))
-
-
-; Create ----------------------------------------------------------------------
-(defn meter [title event-type]
-  (Metrics/newMeter (metric-name title)
-                    event-type
-                    TimeUnit/SECONDS))
-
-
-; Read ------------------------------------------------------------------------
-(defn rates [^Meter m]
-  {1 (.oneMinuteRate m)
-   5 (.fiveMinuteRate m)
-   15 (.fifteenMinuteRate m)})
-
-(defn rate-one [^Meter m]
-  (.oneMinuteRate m))
-
-(defn rate-five [^Meter m]
-  (.fiveMinuteRate m))
-
-(defn rate-fifteen [^Meter m]
-  (.fifteenMinuteRate m))
-
-(defn rate-mean [^Meter m]
-  (.meanRate m))
-
-
-; Write -----------------------------------------------------------------------
-(defn mark!
-  ([^Meter m]
-   (mark! m 1))
-  ([^Meter m n]
-   (.mark m (long n))
-   m))
-

src/metrics/timers.clj

-(ns metrics.timers
-  (:use [metrics.utils :only (metric-name get-percentiles)])
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.core Timer MetricName))
-  (:import (java.util.concurrent TimeUnit)))
-
-
-; Create ----------------------------------------------------------------------
-(defn timer [title]
-  (Metrics/newTimer ^MetricName (metric-name title)
-                    TimeUnit/MILLISECONDS
-                    TimeUnit/SECONDS))
-
-
-; Read ------------------------------------------------------------------------
-(defn rates [^Timer m]
-  {1 (.oneMinuteRate m)
-   5 (.fiveMinuteRate m)
-   15 (.fifteenMinuteRate m)})
-
-(defn rate-one [^Timer m]
-  (.oneMinuteRate m))
-
-(defn rate-five [^Timer m]
-  (.fiveMinuteRate m))
-
-(defn rate-fifteen [^Timer m]
-  (.fifteenMinuteRate m))
-
-(defn rate-mean [^Timer m]
-  (.meanRate m))
-
-
-(defn mean [^Timer t]
-  (.mean t))
-
-(defn std-dev [^Timer t]
-  (.stdDev t))
-
-(defn percentiles
-  ([^Timer t]
-   (percentiles t [0.75 0.95 0.99 0.999 1.0]))
-  ([^Timer t ps]
-   (get-percentiles t ps)))
-
-
-(defn number-recorded [^Timer t]
-  (.count t))
-
-(defn largest [^Timer t]
-  (.max t))
-
-(defn smallest [^Timer t]
-  (.min t))
-
-(defn sample [^Timer t]
-  (.getValues (.getSnapshot t)))
-
-
-; Write -----------------------------------------------------------------------
-(defmacro time! [^Timer t & body]
-  `(.time ~(vary-meta t assoc :tag `Timer)
-         (proxy [Callable] []
-           (call [] (do ~@body)))))
-
-(defn time-fn! [^Timer t f]
-  (.time t
-         (proxy [Callable] []
-           (call [] (f)))))
-
-(defn clear! [^Timer t]
-  (.clear t))
-

src/metrics/utils.clj

-(ns metrics.utils
-  (:import (com.yammer.metrics Metrics))
-  (:import (com.yammer.metrics.core Sampling MetricName)))
-
-
-(defn get-percentile [^Sampling metric ^double percentile]
-  (-> metric
-    .getSnapshot
-    (.getValue percentile)))
-
-(defn get-percentiles [metric percentiles]
-  (zipmap percentiles
-           (map (partial get-percentile metric)
-                percentiles)))
-
-(defn metric-name ^MetricName [title]
-  (if (string? title)
-    (new MetricName "default" "default" ^String title)
-    (new MetricName
-         ^String (first title)
-         ^String (second title)
-         ^String (last title))))
-
-(defn all-metrics []
-  (letfn [(parse-name [metric-name]
-            (str (.getGroup metric-name)
-                 "." (.getType metric-name)
-                 "." (.getName metric-name)))
-          (parse-entry [[metric-name metric]]
-            [(parse-name metric-name)
-             metric])]
-    (into {} (map parse-entry (.allMetrics (Metrics/defaultRegistry))))))

test/metrics/test/core.clj

-(ns metrics.test.core
-  (:use [metrics.core])
-  (:use [clojure.test]))
-

test/metrics/test/counters.clj

-(ns metrics.test.counters
-  (:require [metrics.counters :as counters])
-  (:use [clojure.test]))
-
-
-(deftest test-inc
-  (let [c (counters/counter ["test" "counters" "test-inc"])]
-    (is (= (counters/value c) 0))
-    (counters/inc! c)
-    (is (= (counters/value c) 1))
-    (counters/inc! c 2)
-    (is (= (counters/value c) 3))))
-
-(deftest test-dec
-  (let [c (counters/counter ["test" "counters" "test-dec"])]
-    (is (= (counters/value c) 0))
-    (counters/dec! c)
-    (is (= (counters/value c) -1))
-    (counters/dec! c 2)
-    (is (= (counters/value c) -3))))
-
-(deftest test-clear
-  (let [c (counters/counter ["test" "counters" "test-clear"])]
-    (is (= (counters/value c) 0))
-    (counters/inc! c 100)
-    (is (= (counters/value c) 100))
-    (counters/clear! c)
-    (is (= (counters/value c) 0))))

test/metrics/test/gauges.clj

-(ns metrics.test.gauges
-  (:require [metrics.gauges :as gauges])
-  (:use [clojure.test]))
-
-
-(deftest test-gauge
-  (let [g (gauges/gauge ["test" "gauges" "test-gauge"]
-                        (+ 100 1))]
-    (is (= (gauges/value g) 101))))
-
-(deftest test-gauge-fn
-  (let [g (gauges/gauge-fn ["test" "gauges" "test-gauge-fn"]
-                           #(+ 100 2))]
-    (is (= (gauges/value g) 102))))

test/metrics/test/histograms.clj

-(ns metrics.test.histograms
-  (:require [metrics.histograms :as histograms])
-  (:use [metrics.test.utils])
-  (:use [clojure.test]))
-
-
-(deftest test-mean
-  (let [h (histograms/histogram ["test" "histograms" "test-mean"])]
-    (is (= (histograms/mean h) 0.0))
-    (histograms/update! h 5)
-    (is (= (histograms/mean h) 5.0))
-    (histograms/update! h 15)
-    (is (= (histograms/mean h) 10.0))))
-
-(deftest test-number-recorded
-  (let [h (histograms/histogram ["test" "histograms" "test-number-recorded"])]
-    (is (= (histograms/number-recorded h) 0))
-    (histograms/update! h 0)
-    (is (= (histograms/number-recorded h) 1))
-    (histograms/update! h 0)
-    (is (= (histograms/number-recorded h) 2))))
-
-(deftest test-std-dev
-  (let [h (histograms/histogram ["test" "histograms" "test-std-dev"])]
-    (is (= (histograms/std-dev h) 0.0))
-    (histograms/update! h 2)
-    (histograms/update! h 4)
-    (histograms/update! h 6)
-    (is (= (histograms/std-dev h) 2.0))))
-
-(deftest test-smallest
-  (let [h (histograms/histogram ["test" "histograms" "test-smallest"])]
-    (is (= (histograms/smallest h) 0.0))
-    (histograms/update! h 1)
-    (histograms/update! h 9)
-    (histograms/update! h 3)
-    (is (= (histograms/smallest h) 1.0))))
-
-(deftest test-largest
-  (let [h (histograms/histogram ["test" "histograms" "test-largest"])]
-    (is (= (histograms/largest h) 0.0))
-    (histograms/update! h 1)
-    (histograms/update! h 9)
-    (histograms/update! h 3)
-    (is (= (histograms/largest h) 9.0))))
-
-(deftest test-percentiles
-  (let [h (histograms/histogram ["test" "histograms" "test-percentiles"])]
-    (is (maps-within-one (histograms/percentiles h)
-                    {0.75 0, 0.95 0, 0.99 0, 0.999 0, 1.00 0}))
-
-    (dorun (map (partial histograms/update! h) (range 1 101)))
-
-    (is (maps-within-one (histograms/percentiles h)
-                    {0.75 75, 0.95 95, 0.99 99, 0.999 100, 1.00 100}))
-
-    (is (maps-within-one (histograms/percentiles h [0.10 0.50])
-                    {0.10 10, 0.50 50}))))
-
-(deftest test-clear
-  (let [h (histograms/histogram ["test" "histograms" "test-clear"])]
-    (is (= (histograms/mean h) 0.0))
-    (histograms/update! h 5)
-    (is (= (histograms/mean h) 5.0))
-    (histograms/clear! h)
-    (is (= (histograms/mean h) 0.0))))
-

test/metrics/test/meters.clj

-(ns metrics.test.meters
-  (:require [metrics.meters :as meters])
-  (:use [metrics.test.utils])
-  (:use [clojure.test]))
-
-
-(deftest test-rate-mean
-  (let [m (meters/meter ["test" "meters" "test-rate-mean"] "test-events")]
-    (is (= (meters/rate-mean m) 0.0))
-    (meters/mark! m)
-    (is (> (meters/rate-mean m) 0.0))))
-
-(deftest test-rate-mean-update-multiple
-  (let [m (meters/meter ["test" "meters" "test-rate-mean-update-multiple"] "test-events")]
-    (is (= (meters/rate-mean m) 0.0))
-    (meters/mark! m 10)
-    (is (> (meters/rate-mean m) 0.0))))
-
-(deftest test-rate-one
-  (let [m (meters/meter ["test" "meters" "test-rate-one"] "test-events")]
-    (is (= (meters/rate-one m) 0.0))
-    (meters/mark! m 20000)
-    (Thread/sleep 8000)
-    (is (> (meters/rate-one m) 0.0))))
-
-(deftest test-rate-five
-  (let [m (meters/meter ["test" "meters" "test-rate-five"] "test-events")]
-    (is (= (meters/rate-five m) 0.0))
-    (meters/mark! m 20000)
-    (Thread/sleep 8000)
-    (is (> (meters/rate-five m) 0.0))))
-
-(deftest test-rate-fifteen
-  (let [m (meters/meter ["test" "meters" "test-rate-fifteen"] "test-events")]
-    (is (= (meters/rate-fifteen m) 0.0))
-    (meters/mark! m 20000)
-    (Thread/sleep 8000)
-    (is (> (meters/rate-fifteen m) 0.0))))
-
-(deftest test-rates
-  (let [m (meters/meter ["test" "meters" "test-rates"] "test-events")]
-    (is (every? zero? (vals (meters/rates m))))
-    (meters/mark! m 20000)
-    (Thread/sleep 8000)
-    (is (every? #(> % 0.0) (vals (meters/rates m))))))

test/metrics/test/timers.clj

-(ns metrics.test.timers
-  (:require [metrics.timers :as timers])
-  (:use [metrics.test.utils])
-  (:use [clojure.test]))
-
-
-(defn- sleep-100 []
-  (Thread/sleep 100)
-  100)
-
-(defn- sleep-200 []
-  (Thread/sleep 200)
-  200)
-
-
-(deftest test-rate-mean
-  (let [t (timers/timer ["test" "timers" "test-rate-mean"])]
-    (is (= (timers/rate-mean t) 0.0))
-    (is (= (timers/time! t (sleep-100)) 100))
-    (is (> (timers/rate-mean t) 0.0))))
-
-(deftest test-rate-mean-fn
-  (let [t (timers/timer ["test" "timers" "test-rate-mean-fn"])]
-    (is (= (timers/rate-mean t) 0.0))
-    (is (= (timers/time-fn! t sleep-100) 100))
-    (is (> (timers/rate-mean t) 0.0))))
-
-(deftest test-rate-one
-  (let [t (timers/timer ["test" "timers" "test-rate-one"])]
-    (is (= (timers/rate-one t) 0.0))
-    (is (= (timers/time! t (sleep-100)) 100))
-    (Thread/sleep 8000)
-    (is (> (timers/rate-one t) 0.0))))
-
-(deftest test-rate-five
-  (let [t (timers/timer ["test" "timers" "test-rate-five"])]
-    (is (= (timers/rate-five t) 0.0))
-    (is (= (timers/time! t (sleep-100)) 100))
-    (Thread/sleep 8000)
-    (is (> (timers/rate-five t) 0.0))))
-
-(deftest test-rate-fifteen
-  (let [t (timers/timer ["test" "timers" "test-rate-fifteen"])]
-    (is (= (timers/rate-fifteen t) 0.0))
-    (is (= (timers/time! t (sleep-100)) 100))
-    (Thread/sleep 8000)
-    (is (> (timers/rate-fifteen t) 0.0))))
-
-
-(deftest test-largest
-  (let [t (timers/timer ["test" "timers" "test-largest"])]
-    (is (= (timers/largest t) 0.0))
-    (is (= (timers/time! t (sleep-100)) 100))
-    (is (within-ten (timers/largest t) 100.0))
-    (is (= (timers/time! t (sleep-200)) 200))
-    (is (within-ten (timers/largest t) 200.0))))
-
-(deftest test-smallest
-  (let [t (timers/timer ["test" "timers" "test-smallest"])]
-    (is (= (timers/smallest t) 0.0))
-    (is (= (timers/time! t (sleep-100)) 100))
-    (is (within-ten (timers/smallest t) 100.0))
-    (is (= (timers/time! t (sleep-200)) 200))
-    (is (within-ten (timers/smallest t) 100.0))))

test/metrics/test/utils.clj

-(ns metrics.test.utils)
-
-(defn abs [n]
-  (if (> n 0) n (* -1 n)))
-
-(defn within-one [a b]
-  (<= (abs (- a b))
-      1))
-
-(defn within-ten [a b]
-  (<= (abs (- a b))
-      10))
-
-(defn maps-within-one [a b]
-  (when (= (set (keys a)) (set (keys b)))
-    (every? identity
-            (map #(within-one (a %) (b %))
-                 (keys a)))))
-
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.