Skip to content

Instantly share code, notes, and snippets.

@thinkbeforecoding
Created September 7, 2016 13:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thinkbeforecoding/f2f4c7ba8f2a717058c50011192870c8 to your computer and use it in GitHub Desktop.
Save thinkbeforecoding/f2f4c7ba8f2a717058c50011192870c8 to your computer and use it in GitHub Desktop.
Sample to report timing metrics
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
@haf
Copy link

haf commented Sep 21, 2016

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment