add basic prometheus profiling metrics tracker

This commit is contained in:
gmega 2023-11-03 19:04:37 -03:00
parent aa6d8d7b56
commit 613e4c4038
No known key found for this signature in database
GPG Key ID: FFD8DAF00660270F
3 changed files with 123 additions and 1 deletions

View File

@ -3,4 +3,6 @@ import ../conf
when chronosFuturesInstrumentation: when chronosFuturesInstrumentation:
import ./asyncprofiler/asyncprofiler import ./asyncprofiler/asyncprofiler
import ./asyncprofiler/serialization import ./asyncprofiler/serialization
export asyncprofiler, serialization import ./asyncprofiler/metricscollector
export asyncprofiler, serialization, metricscollector

View File

@ -0,0 +1,54 @@
import std/times
import asyncprofiler
import metrics
when defined(metrics):
type
ProfilingCollector* = ref object of Gauge
perfSampler: PerfSampler
PerfSampler = proc (): MetricsSummary {.raises: [].}
proc newCollector*(
ProfilingCollector: typedesc,
name: string,
help: string,
perfSampler: PerfSampler,
registry: Registry = defaultRegistry,
): ProfilingCollector =
result = ProfilingCollector.newCollector(
name=name, help=help, registry=registry)
result.perfSampler = perfSampler
method collect*(self: ProfilingCollector): Metrics =
let now = times.getTime().toMilliseconds()
var largestExecTime = low(timer.Duration)
var largestMaxExecTime = low(timer.Duration)
for (locationPtr, metric) in self.perfSampler().pairs:
if metric.maxSingleTime > largestMaxExecTime:
largestMaxExecTime = metric.maxSingleTime
if metric.totalExecTime > largestExecTime:
largestExecTime = metric.totalExecTime
result[newSeq[string]()] = @[
Metric(
name: "largest_total_exec_time",
value: largestExecTime.nanoseconds.float64,
timestamp: now,
),
Metric(
name: "largest_max_exec_time",
value: largestMaxExecTime.nanoseconds.float64,
timestamp: now,
)
]
var profilingCollector = ProfilingCollector.newCollector(
name = "profiling",
help = "Profiling metrics",
perfSampler = getFutureSummaryMetrics
)

View File

@ -0,0 +1,66 @@
import std/unittest
import pkg/metrics
import codex/utils/asyncprofiler
import ../../helpers
checksuite "asyncprofiler metrics collector":
var locations = @[
SrcLoc(procedure: "start", file: "discovery.nim", line: 174),
SrcLoc(procedure: "start", file: "discovery.nim", line: 192),
SrcLoc(procedure: "query", file: "manager.nim", line: 323),
SrcLoc(procedure: "update", file: "sqliteds.nim", line: 107),
]
let sample = {
(addr locations[0]): OverallMetrics(
totalExecTime: 90062.nanoseconds,
totalRunTime: 113553.nanoseconds,
totalWallTime: 174567.nanoseconds,
minSingleTime: 80062.nanoseconds,
maxSingleTime: 80062.nanoseconds,
count: 1
),
(addr locations[1]): OverallMetrics(
totalExecTime: 91660.nanoseconds,
totalRunTime: 71660.nanoseconds,
totalWallTime: 72941.nanoseconds,
minSingleTime: 71660.nanoseconds,
maxSingleTime: 81660.nanoseconds,
count: 1
),
(addr locations[2]): OverallMetrics(
totalExecTime: 60529.nanoseconds,
totalRunTime: 60529.nanoseconds,
totalWallTime: 60784.nanoseconds,
minSingleTime: 60529.nanoseconds,
maxSingleTime: 60529.nanoseconds,
count: 1
),
(addr locations[3]): OverallMetrics(
totalExecTime: 60145.nanoseconds,
totalRunTime: 156214.nanoseconds,
totalWallTime: 60813.nanoseconds,
minSingleTime: 5333.nanoseconds,
maxSingleTime: 41257.nanoseconds,
count: 3
),
}.toTable
test "should keep track of basic worst-case exec time stats":
var registry = newRegistry()
var collector = ProfilingCollector.newCollector(
name = "profiling_metrics",
help = "Metrics from the profiler",
registry = registry, perfSampler = proc (): MetricsSummary = sample
)
check collector.valueByName("largest_total_exec_time") == 91660
check collector.valueByName("largest_max_exec_time") == 81660