Browse Source

Collectors: verify that metric names are valid.

pull/6/head
Fredrik Ekre 2 years ago
parent
commit
3e6d9c81be
  1. 24
      src/Prometheus.jl
  2. 16
      test/runtests.jl

24
src/Prometheus.jl

@ -39,6 +39,19 @@ function Base.showerror(io::IO, err::Union{AssertionError, UnreachableError})
) )
end end
# https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
# Metric names may contain ASCII letters, digits, underscores, and colons.
# It must match the regex [a-zA-Z_:][a-zA-Z0-9_:]*.
# Note: The colons are reserved for user defined recording rules. They should
# not be used by exporters or direct instrumentation.
function verify_metric_name(metric_name::String)
metric_name_regex = r"^[a-zA-Z_:][a-zA-Z0-9_:]*$"
if !occursin(metric_name_regex, metric_name)
throw(ArgumentError("metric name \"$(metric_name)\" is invalid"))
end
return metric_name
end
########################################### ###########################################
# Compat for const fields, @lock, @atomic # # Compat for const fields, @lock, @atomic #
########################################### ###########################################
@ -137,7 +150,7 @@ mutable struct Counter <: Collector
registry::Union{CollectorRegistry, Nothing}=DEFAULT_REGISTRY, registry::Union{CollectorRegistry, Nothing}=DEFAULT_REGISTRY,
) )
initial_value = 0.0 initial_value = 0.0
counter = new(metric_name, help, initial_value) counter = new(verify_metric_name(metric_name), help, initial_value)
if registry !== nothing if registry !== nothing
register(registry, counter) register(registry, counter)
end end
@ -219,7 +232,7 @@ mutable struct Gauge <: Collector
registry::Union{CollectorRegistry, Nothing}=DEFAULT_REGISTRY, registry::Union{CollectorRegistry, Nothing}=DEFAULT_REGISTRY,
) )
initial_value = 0.0 initial_value = 0.0
gauge = new(metric_name, help, initial_value) gauge = new(verify_metric_name(metric_name), help, initial_value)
if registry !== nothing if registry !== nothing
register(registry, gauge) register(registry, gauge)
end end
@ -331,7 +344,7 @@ mutable struct Summary <: Collector
) )
initial_count = 0 initial_count = 0
initial_sum = 0.0 initial_sum = 0.0
summary = new(metric_name, help, initial_count, initial_sum) summary = new(verify_metric_name(metric_name), help, initial_count, initial_sum)
if registry !== nothing if registry !== nothing
register(registry, summary) register(registry, summary)
end end
@ -423,7 +436,9 @@ struct Family{C, N} <: Collector
) where {C, N} ) where {C, N}
children = Dict{LabelValues{N}, C}() children = Dict{LabelValues{N}, C}()
lock = ReentrantLock() lock = ReentrantLock()
family = new{C, N}(metric_name, help, LabelNames(labelnames), children, lock) family = new{C, N}(
verify_metric_name(metric_name), help, LabelNames(labelnames), children, lock,
)
if registry !== nothing if registry !== nothing
register(registry, family) register(registry, family)
end end
@ -483,6 +498,7 @@ Return the collector of type `C` from the family corresponding to the labels giv
""" """
function labels(family::Family{C, N}, labelvalues::NTuple{N, String}) where {C, N} function labels(family::Family{C, N}, labelvalues::NTuple{N, String}) where {C, N}
collector = @lock family.lock get!(family.children, LabelValues(labelvalues)) do collector = @lock family.lock get!(family.children, LabelValues(labelvalues)) do
# TODO: Avoid the re-verification of the metric name?
C(family.metric_name, family.help; registry=nothing) C(family.metric_name, family.help; registry=nothing)
end end
return collector return collector

16
test/runtests.jl

@ -41,6 +41,10 @@ end
c = Prometheus.Counter("metric_name_counter", "A counter."; registry=r) c = Prometheus.Counter("metric_name_counter", "A counter."; registry=r)
@test c in r.collectors @test c in r.collectors
@test c.value == 0 @test c.value == 0
@test_throws(
Prometheus.ArgumentError("metric name \"invalid-name\" is invalid"),
Prometheus.Counter("invalid-name", "help"),
)
# Prometheus.inc(...) # Prometheus.inc(...)
Prometheus.inc(c) Prometheus.inc(c)
@test c.value == 1 @test c.value == 1
@ -75,6 +79,10 @@ end
c = Prometheus.Gauge("metric_name_gauge", "A gauge."; registry=r) c = Prometheus.Gauge("metric_name_gauge", "A gauge."; registry=r)
@test c in r.collectors @test c in r.collectors
@test c.value == 0 @test c.value == 0
@test_throws(
Prometheus.ArgumentError("metric name \"invalid-name\" is invalid"),
Prometheus.Gauge("invalid-name", "help"),
)
# Prometheus.inc(...) # Prometheus.inc(...)
Prometheus.inc(c) Prometheus.inc(c)
@test c.value == 1 @test c.value == 1
@ -123,6 +131,10 @@ end
@test c in r.collectors @test c in r.collectors
@test c._count == 0 @test c._count == 0
@test c._sum == 0 @test c._sum == 0
@test_throws(
Prometheus.ArgumentError("metric name \"invalid-name\" is invalid"),
Prometheus.Summary("invalid-name", "help"),
)
# Prometheus.observe(...) # Prometheus.observe(...)
Prometheus.observe(c, 1) Prometheus.observe(c, 1)
@test c._count == 1 @test c._count == 1
@ -184,6 +196,10 @@ end
) )
@test c in r.collectors @test c in r.collectors
@test length(c.children) == 0 @test length(c.children) == 0
@test_throws(
Prometheus.ArgumentError("metric name \"invalid-name\" is invalid"),
Prometheus.Family{Collector}("invalid-name", "help", ("label",)),
)
# Prometheus.labels(...), Prometheus.remove(...), Prometheus.clear() # Prometheus.labels(...), Prometheus.remove(...), Prometheus.clear()
l1 = ("/foo/", "200") l1 = ("/foo/", "200")
l2 = ("/bar/", "404") l2 = ("/bar/", "404")

Loading…
Cancel
Save