mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-15 17:35:45 +00:00
331 lines
12 KiB
Nim
331 lines
12 KiB
Nim
# nim-metrics
|
|
# Copyright (c) 2019 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT
|
|
# * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
import net, os, unittest,
|
|
../metrics
|
|
|
|
when defined(metrics):
|
|
addExportBackend(
|
|
metricProtocol = STATSD,
|
|
netProtocol = UDP,
|
|
address = "127.0.0.1",
|
|
port = Port(8125)
|
|
)
|
|
addExportBackend(
|
|
metricProtocol = CARBON,
|
|
netProtocol = TCP,
|
|
address = "127.0.0.1",
|
|
port = Port(2003)
|
|
)
|
|
|
|
declareCounter globalCounter, "help"
|
|
declarePublicCounter globalPublicCounter, "help"
|
|
declareGauge globalGauge, "help"
|
|
declarePublicGauge globalPublicGauge, "help"
|
|
|
|
proc gcSafetyTest* {.gcsafe.} = # The test is successful if this proc compiles
|
|
globalCounter.inc 2
|
|
globalPublicCounter.inc(2)
|
|
globalGauge.set 10.0
|
|
globalGauge.inc
|
|
globalGauge.dec
|
|
globalPublicGauge.set(1)
|
|
|
|
suite "counter":
|
|
setup:
|
|
var registry = newRegistry()
|
|
declareCounter myCounter, "help", registry = registry
|
|
|
|
test "basic":
|
|
check myCounter.value == 0
|
|
myCounter.inc()
|
|
check myCounter.value == 1
|
|
myCounter.inc(7)
|
|
check myCounter.value == 8
|
|
myCounter.inc(0.5)
|
|
check myCounter.value == 8.5
|
|
myCounter.inc(-1) # you shouldn't be doing this - but we don't want metrics to crash the app
|
|
check myCounter.value == 8.5
|
|
# name validation (have to use the internal API to get past Nim's identifier validation)
|
|
when defined(metrics):
|
|
expect ValueError:
|
|
var tmp = newCounter("1337", "invalid name")
|
|
|
|
test "alternative API":
|
|
counter("one_off_counter").inc()
|
|
check counter("one_off_counter").value == 1
|
|
counter("one_off_counter").inc(0.5)
|
|
check counter("one_off_counter").value == 1.5
|
|
|
|
# confusing, but allowed
|
|
check gauge("one_off_counter").value == 0
|
|
|
|
# colons in name
|
|
counter("one:off:counter:colons").inc()
|
|
check counter("one:off:counter:colons").value == 1
|
|
|
|
test "exceptions":
|
|
proc f(switch: bool) =
|
|
if switch:
|
|
raise newException(ValueError, "exc1")
|
|
else:
|
|
raise newException(IndexError, "exc2")
|
|
|
|
expect IndexError:
|
|
myCounter.countExceptions(ValueError):
|
|
f(false)
|
|
check myCounter.value == 0
|
|
|
|
expect ValueError:
|
|
myCounter.countExceptions(ValueError):
|
|
f(true)
|
|
check myCounter.value == 1
|
|
|
|
expect IndexError:
|
|
myCounter.countExceptions:
|
|
f(false)
|
|
check myCounter.value == 2
|
|
|
|
myCounter.countExceptions:
|
|
discard
|
|
check myCounter.value == 2
|
|
|
|
test "labels":
|
|
declareCounter lCounter, "l help", @["foo", "bar"], registry
|
|
expect KeyError:
|
|
discard lCounter.value
|
|
|
|
# you can't access a labelled value before it was initialised
|
|
expect KeyError:
|
|
discard lCounter.value(@["a", "x"])
|
|
|
|
let labelValues = @["a", "x \"y\" \n\\z"]
|
|
lCounter.inc(labelValues = labelValues)
|
|
check lCounter.value(labelValues) == 1
|
|
# echo registry
|
|
|
|
# label validation
|
|
expect ValueError:
|
|
declareCounter invalid1, "invalid", @["123", "foo"]
|
|
expect ValueError:
|
|
declareCounter invalid2, "invalid", @["foo", "123"]
|
|
expect ValueError:
|
|
declareCounter invalid3, "invalid", @["foo", "__bar"]
|
|
|
|
# label names: array instead of sequence
|
|
declareCounter lCounter2, "l2 help", ["foo", "bar"], registry
|
|
let labelValues2 = ["a", "x \"y\" \n\\z"]
|
|
lCounter2.inc(labelValues = labelValues2)
|
|
check lCounter2.value(labelValues2) == 1
|
|
|
|
test "sample rate":
|
|
declareCounter sCounter, "counter with a sample rate set", registry = registry, sampleRate = 0.5
|
|
sCounter.inc()
|
|
# No sampling done on our side, just in sending the increments to a StatsD server
|
|
check sCounter.value == 1
|
|
|
|
test "names with colons":
|
|
declareCounter cCounter, "counter with colons in name", registry = registry, name = "foo:bar:baz"
|
|
cCounter.inc()
|
|
check cCounter.value == 1
|
|
check cCounter.valueByName("foo:bar:baz_total") == 1
|
|
# echo cCounter
|
|
|
|
var myName = "bla:bla"
|
|
declareCounter cCounter2, "another counter with colon in name", registry = registry, name = myName
|
|
cCounter2.inc()
|
|
check cCounter2.value == 1
|
|
check cCounter2.valueByName("bla:bla_total") == 1
|
|
# echo cCounter2
|
|
|
|
suite "gauge":
|
|
setup:
|
|
var registry = newRegistry()
|
|
declareGauge myGauge, "help", registry = registry
|
|
|
|
test "basic":
|
|
check myGauge.value == 0
|
|
myGauge.inc()
|
|
check myGauge.value == 1
|
|
myGauge.dec(3)
|
|
check myGauge.value == -2.0 # weird Nim bug if it's "-2"
|
|
myGauge.dec(0.1)
|
|
check myGauge.value == -2.1
|
|
myGauge.set(9.5)
|
|
check myGauge.value == 9.5
|
|
myGauge.set(1)
|
|
check myGauge.value == 1
|
|
|
|
test "alternative API":
|
|
gauge("one_off_gauge").set(1)
|
|
check gauge("one_off_gauge").value == 1
|
|
gauge("one_off_gauge").inc(0.5)
|
|
check gauge("one_off_gauge").value == 1.5
|
|
|
|
test "in progress":
|
|
myGauge.trackInProgress:
|
|
check myGauge.value == 1
|
|
check myGauge.value == 0
|
|
|
|
declareGauge lgauge, "help", @["foobar"], registry = registry
|
|
let labelValues = @["b"]
|
|
lgauge.trackInProgress(labelValues):
|
|
check lgauge.value(labelValues) == 1
|
|
check lgauge.value(labelValues) == 0
|
|
# echo registry
|
|
|
|
test "timing":
|
|
myGauge.time:
|
|
sleep(1000)
|
|
check myGauge.value == 0
|
|
check myGauge.value >= 1 # may be 2 inside a macOS Travis job
|
|
# echo registry
|
|
|
|
test "timing with labels":
|
|
declareGauge lgauge, "help", @["foobar"], registry = registry
|
|
let labelValues = @["b"]
|
|
lgauge.time(labelValues):
|
|
sleep(1000)
|
|
check lgauge.value(labelValues) >= 1
|
|
|
|
test "names with colons":
|
|
declareGauge cGauge, "gauge with colons in name", registry = registry, name = "foo:bar:baz"
|
|
cGauge.inc()
|
|
check cGauge.value == 1
|
|
check cGauge.valueByName("foo:bar:baz") == 1
|
|
# echo cGauge
|
|
|
|
suite "summary":
|
|
setup:
|
|
var registry = newRegistry()
|
|
declareSummary mySummary, "help", registry = registry
|
|
|
|
test "basic":
|
|
check mySummary.valueByName("mySummary_count") == 0
|
|
check mySummary.valueByName("mySummary_sum") == 0
|
|
mySummary.observe(10)
|
|
check mySummary.valueByName("mySummary_count") == 1
|
|
check mySummary.valueByName("mySummary_sum") == 10
|
|
mySummary.observe(0.5)
|
|
check mySummary.valueByName("mySummary_count") == 2
|
|
check mySummary.valueByName("mySummary_sum") == 10.5
|
|
|
|
test "alternative API":
|
|
summary("one_off_summary").observe(10)
|
|
check summary("one_off_summary").valueByName("one_off_summary_count") == 1
|
|
check summary("one_off_summary").valueByName("one_off_summary_sum") == 10
|
|
|
|
test "timing":
|
|
mySummary.time:
|
|
sleep(1000)
|
|
check mySummary.valueByName("mySummary_sum") == 0
|
|
check mySummary.valueByName("mySummary_sum") >= 1
|
|
|
|
test "timing with labels":
|
|
declareSummary lsummary, "help", ["foobar"], registry = registry
|
|
let labelValues = ["b"]
|
|
lsummary.time(labelValues):
|
|
sleep(1000)
|
|
check lsummary.valueByName("lsummary_sum", labelValues) >= 1
|
|
|
|
test "names with colons":
|
|
declareSummary cSummary, "summary with colons in name", registry = registry, name = "foo:bar:baz"
|
|
cSummary.observe(10)
|
|
check cSummary.valueByName("foo:bar:baz_count") == 1
|
|
check cSummary.valueByName("foo:bar:baz_sum") == 10
|
|
# echo cSummary
|
|
|
|
suite "histogram":
|
|
setup:
|
|
var registry = newRegistry()
|
|
declareHistogram myHistogram, "help", registry = registry
|
|
|
|
test "basic":
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["1.0"]) == 0
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["2.5"]) == 0
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["5.0"]) == 0
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["+Inf"]) == 0
|
|
check myHistogram.valueByName("myHistogram_count") == 0
|
|
check myHistogram.valueByName("myHistogram_sum") == 0
|
|
|
|
myHistogram.observe(2)
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["1.0"]) == 0
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["2.5"]) == 1
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["5.0"]) == 1
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["+Inf"]) == 1
|
|
check myHistogram.valueByName("myHistogram_count") == 1
|
|
check myHistogram.valueByName("myHistogram_sum") == 2
|
|
|
|
myHistogram.observe(2.5)
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["1.0"]) == 0
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["2.5"]) == 2
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["5.0"]) == 2
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["+Inf"]) == 2
|
|
check myHistogram.valueByName("myHistogram_count") == 2
|
|
check myHistogram.valueByName("myHistogram_sum") == 4.5
|
|
|
|
myHistogram.observe(Inf)
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["1.0"]) == 0
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["2.5"]) == 2
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["5.0"]) == 2
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["+Inf"]) == 3
|
|
check myHistogram.valueByName("myHistogram_count") == 3
|
|
check myHistogram.valueByName("myHistogram_sum") == Inf
|
|
|
|
declareHistogram h1, "help", registry = registry, buckets = [0.0, 1.0, 2.0]
|
|
check h1.valueByName("h1_bucket", [], ["0.0"]) == 0
|
|
check h1.valueByName("h1_bucket", [], ["1.0"]) == 0
|
|
check h1.valueByName("h1_bucket", [], ["2.0"]) == 0
|
|
check h1.valueByName("h1_bucket", [], ["+Inf"]) == 0
|
|
|
|
declareHistogram h2, "help", registry = registry, buckets = [0.0, 1.0, 2.0, Inf]
|
|
check h2.valueByName("h2_bucket", [], ["0.0"]) == 0
|
|
check h2.valueByName("h2_bucket", [], ["1.0"]) == 0
|
|
check h2.valueByName("h2_bucket", [], ["2.0"]) == 0
|
|
check h2.valueByName("h2_bucket", [], ["+Inf"]) == 0
|
|
|
|
expect ValueError:
|
|
declareHistogram h3, "help", registry = registry, buckets = []
|
|
expect ValueError:
|
|
declareHistogram h3, "help", registry = registry, buckets = [Inf]
|
|
expect ValueError:
|
|
declareHistogram h3, "help", registry = registry, buckets = [3.0, 1.0]
|
|
|
|
test "alternative API":
|
|
histogram("one_off_histogram").observe(2)
|
|
check histogram("one_off_histogram").valueByName("one_off_histogram_bucket", [], ["1.0"]) == 0
|
|
check histogram("one_off_histogram").valueByName("one_off_histogram_bucket", [], ["2.5"]) == 1
|
|
check histogram("one_off_histogram").valueByName("one_off_histogram_bucket", [], ["5.0"]) == 1
|
|
check histogram("one_off_histogram").valueByName("one_off_histogram_bucket", [], ["+Inf"]) == 1
|
|
check histogram("one_off_histogram").valueByName("one_off_histogram_count") == 1
|
|
check histogram("one_off_histogram").valueByName("one_off_histogram_sum") == 2
|
|
|
|
test "timing":
|
|
myHistogram.time:
|
|
sleep(1000)
|
|
check myHistogram.valueByName("myHistogram_sum") == 0
|
|
check myHistogram.valueByName("myHistogram_sum") >= 1
|
|
check myHistogram.valueByName("myHistogram_count") == 1
|
|
check myHistogram.valueByName("myHistogram_bucket", [], ["+Inf"]) == 1
|
|
|
|
test "timing with labels":
|
|
declareHistogram lhistogram, "help", ["foobar"], registry = registry
|
|
let labelValues = ["b"]
|
|
lhistogram.time(labelValues):
|
|
sleep(1000)
|
|
check lhistogram.valueByName("lhistogram_sum", labelValues) >= 1
|
|
check lhistogram.valueByName("lhistogram_count", labelValues) == 1
|
|
check lhistogram.valueByName("lhistogram_bucket", labelValues, ["+Inf"]) == 1
|
|
|
|
test "names with colons":
|
|
declareHistogram cHistogram, "histogram with colons in name", registry = registry, name = "foo:bar:baz"
|
|
cHistogram.observe(10)
|
|
check cHistogram.valueByName("foo:bar:baz_count") == 1
|
|
check cHistogram.valueByName("foo:bar:baz_sum") == 10
|
|
# echo cHistogram
|
|
|