Created
September 7, 2016 13:26
Revisions
-
thinkbeforecoding created this gist
Sep 7, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,86 @@ open Hopac open Hopac.Infixes open NodaTime open Logary open Logary.Metrics.Reservoirs open Logary.Configuration open Logary.Targets open Metric module PointName = let append suffix (PointName name) = Array.append name [| suffix |] |> PointName.ofArray type Timing = { source: (Value*Units) Stream.Src } [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] module Timing = let create() = { source = Stream.Src.create() } let update timing v = Stream.Src.value timing.source v let report timing (x,v) = update timing v >>-. x let reportAsync timing result = async.Bind(result, Job.toAsync << report timing) let metric timing name = let minName = name |> PointName.append "min" let maxName = name |> PointName.append "max" let medianName = name |> PointName.append "median" let countName = name |> PointName.append "count" let upper95 = name |> PointName.append "upper_95" let reduce state = function | Float v, Seconds -> int64 (v * 1000.) :: state | _ -> state let tick state = let snap = Metrics.Reservoirs.Snapshot.create (Array.ofList state) [], [ snap |> Snapshot.size |> int64 |> Int64 |> Message.gauge countName snap |> Snapshot.median |> int64 |> Int64 |> Message.gauge medianName snap |> Snapshot.min |> Int64 |> Message.gauge minName snap |> Snapshot.max |> Int64 |> Message.gauge maxName snap |> Snapshot.percentile95th |> int64 |> Int64|> Message.gauge upper95 ] job { let! metric = Metric.create reduce [] tick do! metric |> Metric.consume (Stream.Src.tap timing.source) return metric } let time f = let sw = System.Diagnostics.Stopwatch.StartNew() f(), (Float sw.Elapsed.TotalSeconds, Units.Seconds) let timeAsync f = async { let sw = System.Diagnostics.Stopwatch.StartNew() let! result = f return result, (Float sw.Elapsed.TotalSeconds, Units.Seconds) } // usage sample let sampleTiming = Timing.create() // this defines a timing stream source let doSomething() = printfn "Do something" let logary = withLogaryManager "SampleApp" ( withTargets [ Console.create (Console.empty) "console" Graphite.create { Graphite.GraphiteConf.hostname = "graphite-server"; port = 2003us} "graphite" ] >> withMetrics [ MetricConf.create (Duration.FromSeconds 10L) "test.logary.timing" (Timing.metric sampleTiming) ] >> withRules [ Rule.createForTarget "console" Rule.createForTarget "graphite" ] ) |> run doSomething |> time |> Timing.report sampleTiming |> run