Created
September 7, 2016 13:26
-
-
Save thinkbeforecoding/f2f4c7ba8f2a717058c50011192870c8 to your computer and use it in GitHub Desktop.
Sample to report timing metrics
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 characters
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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've added this sample as a progressive enhancement to Logary's metrics here https://github.com/logary/logary/blob/master/examples/Logary.ConsoleApp/Program.fs