diff --git a/project.clj b/project.clj index 0d92f58..ac1034a 100644 --- a/project.clj +++ b/project.clj @@ -4,6 +4,7 @@ :license {:name "The MIT License (MIT)" :url "http://opensource.org/licenses/MIT" :comments "Copyright (c) 2018 Unbounce Marketing Solutions Inc."} + :profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]]}} :dependencies [[org.clojure/clojure "1.9.0"] [com.datadoghq/java-dogstatsd-client "2.5"]] :global-vars {*warn-on-reflection* true}) diff --git a/src/com/unbounce/dogstatsd/core.clj b/src/com/unbounce/dogstatsd/core.clj index 381f9b7..50a7cc4 100644 --- a/src/com/unbounce/dogstatsd/core.clj +++ b/src/com/unbounce/dogstatsd/core.clj @@ -2,10 +2,11 @@ (:import [com.timgroup.statsd StatsDClient NonBlockingStatsDClient ServiceCheck NoOpStatsDClient])) ;; In case setup! is not called, this prevents nullpointer exceptions i.e. Unit tests -(defonce ^:private ^StatsDClient client - (NoOpStatsDClient.)) +(defonce ^:private ^StatsDClient client (NoOpStatsDClient.)) -(defn str-array [tags] +(def ^:private ^"[Ljava.lang.String;" -empty-array (into-array String [])) + +(defn ^"[Ljava.lang.String;" str-array [tags] (into-array String tags)) (defn setup! @@ -32,46 +33,58 @@ tags))))) (defn increment - [metric & {:keys [tags sample-rate]}] - (let [tags (str-array tags)] - (if sample-rate - (.incrementCounter client metric sample-rate tags) - (.incrementCounter client metric tags)))) + ([metric] + (.incrementCounter client metric -empty-array)) + ([metric {:keys [tags sample-rate]}] + (let [tags (str-array tags)] + (if sample-rate + (.incrementCounter client metric sample-rate tags) + (.incrementCounter client metric tags))))) (defn decrement - [metric & {:keys [tags sample-rate]}] - (let [tags (str-array tags)] - (if sample-rate - (.decrementCounter client metric sample-rate tags) - (.decrementCounter client metric tags)))) + ([metric] + (.decrementCounter client metric -empty-array)) + ([metric {:keys [tags sample-rate]}] + (let [tags (str-array tags)] + (if sample-rate + (.decrementCounter client metric sample-rate tags) + (.decrementCounter client metric tags))))) (defn gauge - [metric value {:keys [sample-rate tags]}] - (let [value (double value) - tags (str-array tags) - sample-rate (when sample-rate (double sample-rate)) - f (fn [^String metric ^double value {:keys [^double sample-rate #^"[Ljava.lang.String;" tags]}] - (if sample-rate - (.recordGaugeValue client metric value sample-rate tags) - (.recordGaugeValue client metric value tags)))] - (f metric value {:sample-rate sample-rate - :tags tags}))) + ([^String metric ^Double value] + (.recordGaugeValue client metric value -empty-array)) + ([^String metric ^Double value {:keys [sample-rate tags]}] + (let [tags (str-array tags) + sample-rate ^Double sample-rate] + (if sample-rate + (.recordGaugeValue client metric value sample-rate tags) + (.recordGaugeValue client metric value tags))))) (defn histogram - [metric value {:keys [sample-rate tags]}] - (let [value (double value) - tags (str-array tags) - sample-rate (when sample-rate (double sample-rate)) - f (fn [^String metric ^double value {:keys [^double sample-rate #^"[Ljava.lang.String;" tags]}] - (if sample-rate - (.recordHistogramValue client metric value sample-rate tags) - (.recordHistogramValue client metric value tags)))] - (f metric value {:sample-rate sample-rate - :tags tags}))) + ([^String metric ^Double value] + (.recordHistogramValue client metric value -empty-array)) + ([^String metric ^Double value {:keys [sample-rate tags]}] + (let [tags (str-array tags) + sample-rate ^Double sample-rate] + (if sample-rate + (.recordHistogramValue client metric value sample-rate tags) + (.recordHistogramValue client metric value tags))))) (defmacro time! - "Times the body and submits the execution time to metric" - [metric opts & body] + "Times the body and records the execution time (in msecs) as a histogram. + + Takes opts is a map of :sample-rate and :tags to apply to the histogram + + Examples: + + (statsd/time! [\"my.metric\"] + (Thread/sleep 1000)) + + (statsd/time! [\"my.metric.with.tags\" {:tags #{\"foo\" :sample-rate 0.3}}] + (Thread/sleep 1000)) + + " + [[metric opts] & body] `(let [t0# (System/currentTimeMillis) res# (do ~@body)] (histogram ~metric (- (System/currentTimeMillis) t0#) ~opts) diff --git a/test/com/unbounce/dogstatsd/core_test.clj b/test/com/unbounce/dogstatsd/core_test.clj index 8958759..3b0635d 100644 --- a/test/com/unbounce/dogstatsd/core_test.clj +++ b/test/com/unbounce/dogstatsd/core_test.clj @@ -6,7 +6,7 @@ (s/def ::sample-rate number?) (s/def ::tags (s/coll-of string?)) -(s/def ::opts (s/keys :req-un [::tags ::sample-rate])) +(s/def ::opts (s/keys :opt-un [::tags ::sample-rate])) (s/fdef sut/str-array :args (s/cat :tags ::tags) @@ -14,32 +14,26 @@ (s/fdef sut/increment :args (s/cat :metric string? - :opts (s/* (s/alt :_ (s/cat :_ (partial = :tags) - :_ ::tags) - :_ (s/cat :_ (partial = :sample-rate) - :_ ::sample-rate)))) + :opts (s/? ::opts)) :ret nil?) (s/fdef sut/decrement :args (s/cat :metric string? - :opts (s/* (s/alt :_ (s/cat :_ (partial = :tags) - :_ ::tags) - :_ (s/cat :_ (partial = :sample-rate) - :_ ::sample-rate)))) + :opts (s/? ::opts)) :ret nil?) (s/fdef sut/gauge :args (s/cat :metric string? :value number? - :opts ::opts) + :opts (s/? ::opts)) :ret nil?) (s/fdef sut/histogram :args (s/cat :metric string? :value number? - :opts ::opts) + :opts (s/? ::opts)) :ret nil?) (t/deftest datadog-statsd-metrics @@ -50,8 +44,6 @@ (stest/instrument `sut/gauge) (stest/instrument `sut/histogram) - (sut/setup!) - (stest/check `sut/str-array) (stest/check `sut/increment) (stest/check `sut/decrement) @@ -59,7 +51,14 @@ (stest/check `sut/histogram) (t/are [x y] (= x y) - nil (sut/increment "asdf" :tags ["asdf"] :sample-rate 1) - nil (sut/decrement "asdf" :tags ["asdf"] :sample-rate 1) + nil (sut/increment "asdf") + nil (sut/increment "asdf" {:tags ["asdf"] :sample-rate 1}) + + nil (sut/decrement "asdf") + nil (sut/decrement "asdf" {:tags ["asdf"] :sample-rate 1}) + + nil (sut/gauge "asdf" 20) nil (sut/gauge "asdf" 20 {:tags ["asdf" "asdf"] :sample-rate 1}) + + nil (sut/histogram "asdf" 20) nil (sut/histogram "asdf" 20 {:tags ["asdf" "asdf"] :sample-rate 1}))))