Browse Source

Family{C}: consistent variable naming (NFC).

pull/6/head
Fredrik Ekre 2 years ago
parent
commit
8d933d3dd3
  1. 63
      src/Prometheus.jl
  2. 12
      test/runtests.jl

63
src/Prometheus.jl

@ -418,7 +418,7 @@ function verify_label_name(label_name::String)
end end
struct LabelNames{N} struct LabelNames{N}
labelnames::NTuple{N, String} label_names::NTuple{N, String}
function LabelNames(label_names::NTuple{N, String}) where N function LabelNames(label_names::NTuple{N, String}) where N
for label_name in label_names for label_name in label_names
verify_label_name(label_name) verify_label_name(label_name)
@ -428,36 +428,36 @@ struct LabelNames{N}
end end
struct LabelValues{N} struct LabelValues{N}
labelvalues::NTuple{N, String} label_values::NTuple{N, String}
end end
function Base.hash(l::LabelValues, h::UInt) function Base.hash(l::LabelValues, h::UInt)
h = hash(0x94a2d04ee9e5a55b, h) # hash("Prometheus.LabelValues") on Julia 1.9.3 h = hash(0x94a2d04ee9e5a55b, h) # hash("Prometheus.LabelValues") on Julia 1.9.3
for v in l.labelvalues for v in l.label_values
h = hash(v, h) h = hash(v, h)
end end
return h return h
end end
function Base.:(==)(l1::LabelValues, l2::LabelValues) function Base.:(==)(l1::LabelValues, l2::LabelValues)
return l1.labelvalues == l2.labelvalues return l1.label_values == l2.label_values
end end
struct Family{C, N} <: Collector struct Family{C, N} <: Collector
metric_name::String metric_name::String
help::String help::String
labelnames::LabelNames{N} label_names::LabelNames{N}
children::Dict{LabelValues{N}, C} children::Dict{LabelValues{N}, C}
lock::ReentrantLock lock::ReentrantLock
function Family{C}( function Family{C}(
metric_name::String, help::String, labelnames::NTuple{N, String}; metric_name::String, help::String, label_names::NTuple{N, String};
registry::Union{CollectorRegistry, Nothing}=DEFAULT_REGISTRY, registry::Union{CollectorRegistry, Nothing}=DEFAULT_REGISTRY,
) where {C, N} ) where {C, N}
children = Dict{LabelValues{N}, C}() children = Dict{LabelValues{N}, C}()
lock = ReentrantLock() lock = ReentrantLock()
family = new{C, N}( family = new{C, N}(
verify_metric_name(metric_name), help, LabelNames(labelnames), children, lock, verify_metric_name(metric_name), help, LabelNames(label_names), children, lock,
) )
if registry !== nothing if registry !== nothing
register(registry, family) register(registry, family)
@ -467,15 +467,15 @@ struct Family{C, N} <: Collector
end end
""" """
Prometheus.Family{C}(name, help, labelnames; registry=DEFAULT_REGISTRY) Prometheus.Family{C}(name, help, label_names; registry=DEFAULT_REGISTRY)
Create a labeled collector family with labels given by `labelnames`. For every new set of Create a labeled collector family with labels given by `label_names`. For every new set of
label values encountered a new collector of type `C <: Collector` will be created. label values encountered a new collector of type `C <: Collector` will be created.
**Arguments** **Arguments**
- `name :: String`: the name of the family metric. - `name :: String`: the name of the family metric.
- `help :: String`: the documentation for the family metric. - `help :: String`: the documentation for the family metric.
- `labelnames :: Tuple{String, ...}`: the label names. - `label_names :: Tuple{String, ...}`: the label names.
**Keyword arguments** **Keyword arguments**
- `registry :: Prometheus.CollectorRegistry`: the registry in which to register the - `registry :: Prometheus.CollectorRegistry`: the registry in which to register the
@ -505,10 +505,10 @@ function metric_names(family::Family)
end end
""" """
Prometheus.labels(family::Family{C}, labelvalues::Tuple{String, ...}) where C Prometheus.labels(family::Family{C}, label_values::Tuple{String, ...}) where C
Return the collector of type `C` from the family corresponding to the labels given by Return the collector of type `C` from the family corresponding to the labels given by
`labelvalues`. `label_values`.
!!! note !!! note
This method does an acquire/release of a lock, and a dictionary lookup, to find the This method does an acquire/release of a lock, and a dictionary lookup, to find the
@ -516,8 +516,8 @@ Return the collector of type `C` from the family corresponding to the labels giv
matter (below 100ns for some basic benchmarks) but it is safe to cache the returned matter (below 100ns for some basic benchmarks) but it is safe to cache the returned
collector if required. collector if required.
""" """
function labels(family::Family{C, N}, labelvalues::NTuple{N, String}) where {C, N} function labels(family::Family{C, N}, label_values::NTuple{N, String}) where {C, N}
collector = @lock family.lock get!(family.children, LabelValues(labelvalues)) do collector = @lock family.lock get!(family.children, LabelValues(label_values)) do
# TODO: Avoid the re-verification of the metric name? # 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
@ -525,17 +525,17 @@ function labels(family::Family{C, N}, labelvalues::NTuple{N, String}) where {C,
end end
""" """
Prometheus.remove(family::Family, labelvalues::Tuple{String, ...}) Prometheus.remove(family::Family, label_values::Tuple{String, ...})
Remove the collector corresponding to `labelvalues`. Effectively this resets the collector Remove the collector corresponding to `label_values`. Effectively this resets the collector
since [`Prometheus.labels`](@ref) will recreate the collector when called with the same since [`Prometheus.labels`](@ref) will recreate the collector when called with the same
label names. label names.
!!! note !!! note
This method invalidates cached collectors for the label names. This method invalidates cached collectors for the label names.
""" """
function remove(family::Family{<:Any, N}, labelvalues::NTuple{N, String}) where N function remove(family::Family{<:Any, N}, label_values::NTuple{N, String}) where N
@lock family.lock delete!(family.children, LabelValues(labelvalues)) @lock family.lock delete!(family.children, LabelValues(label_values))
return return
end end
@ -576,7 +576,7 @@ function collect!(metrics::Vector, family::Family{C}) where C
else else
@assert(child_samples isa Vector{Sample}) @assert(child_samples isa Vector{Sample})
for child_sample in child_samples for child_sample in child_samples
@assert(child_sample.labels === nothing) @assert(child_sample.label_values === nothing)
push!(samples, Sample(child_sample.suffix, labels, child_sample.value)) push!(samples, Sample(child_sample.suffix, labels, child_sample.value))
end end
end end
@ -584,11 +584,14 @@ function collect!(metrics::Vector, family::Family{C}) where C
end end
# Sort samples lexicographically by the labels # Sort samples lexicographically by the labels
sort!(samples; by = function(x) sort!(samples; by = function(x)
labels = x.labels labels = x.label_values
@assert(labels !== nothing) @assert(labels !== nothing)
return labels.labelvalues return labels.label_values
end) end)
push!(metrics, Metric(type, family.metric_name, family.help, family.labelnames, samples)) push!(
metrics,
Metric(type, family.metric_name, family.help, family.label_names, samples),
)
return metrics return metrics
end end
@ -599,7 +602,7 @@ end
struct Sample struct Sample
suffix::Union{String, Nothing} # e.g. _count or _sum suffix::Union{String, Nothing} # e.g. _count or _sum
labels::Union{LabelValues, Nothing} label_values::Union{LabelValues, Nothing}
value::Float64 value::Float64
end end
@ -607,7 +610,7 @@ struct Metric
type::String type::String
metric_name::String metric_name::String
help::String help::String
labelnames::Union{LabelNames, Nothing} label_names::Union{LabelNames, Nothing}
# TODO: Union{Tuple{Sample}, Vector{Sample}} would always make this iterable. # TODO: Union{Tuple{Sample}, Vector{Sample}} would always make this iterable.
samples::Union{Sample, Vector{Sample}} samples::Union{Sample, Vector{Sample}}
end end
@ -628,12 +631,12 @@ function expose_metric(io::IO, metric::Metric)
print_escaped(io, metric.help, ('\\', '\n')) print_escaped(io, metric.help, ('\\', '\n'))
println(io) println(io)
println(io, "# TYPE ", metric.metric_name, " ", metric.type) println(io, "# TYPE ", metric.metric_name, " ", metric.type)
labelnames = metric.labelnames label_names = metric.label_names
samples = metric.samples samples = metric.samples
if samples isa Sample if samples isa Sample
# Single sample, no labels # Single sample, no labels
@assert(labelnames === nothing) @assert(label_names === nothing)
@assert(samples.labels === nothing) @assert(samples.label_values === nothing)
@assert(samples.suffix === nothing) @assert(samples.suffix === nothing)
val = samples.value val = samples.value
println(io, metric.metric_name, " ", isinteger(val) ? Int(val) : val) println(io, metric.metric_name, " ", isinteger(val) ? Int(val) : val)
@ -648,11 +651,11 @@ function expose_metric(io::IO, metric::Metric)
print(io, sample.suffix) print(io, sample.suffix)
end end
# Print potential labels # Print potential labels
labels = sample.labels labels = sample.label_values
if labelnames !== nothing && labels !== nothing if label_names !== nothing && labels !== nothing
first = true first = true
print(io, "{") print(io, "{")
for (name, value) in zip(labelnames.labelnames, labels.labelvalues) for (name, value) in zip(label_names.label_names, labels.label_values)
first || print(io, ",") first || print(io, ",")
print(io, name, "=\"") print(io, name, "=\"")
print_escaped(io, value, ('\\', '\"', '\n')) print_escaped(io, value, ('\\', '\"', '\n'))

12
test/runtests.jl

@ -152,8 +152,8 @@ end
s1, s2 = metric.samples[1], metric.samples[2] s1, s2 = metric.samples[1], metric.samples[2]
@test s1.suffix == "_count" @test s1.suffix == "_count"
@test s2.suffix == "_sum" @test s2.suffix == "_sum"
@test s1.labels === nothing @test s1.label_values === nothing
@test s2.labels === nothing @test s2.label_values === nothing
@test s1.value == 2 @test s1.value == 2
@test s2.value == 11 @test s2.value == 11
# Prometheus.expose_metric(...) # Prometheus.expose_metric(...)
@ -237,8 +237,8 @@ end
@test metric.help == c.help @test metric.help == c.help
@test length(metric.samples) == 2 @test length(metric.samples) == 2
s1, s2 = metric.samples[1], metric.samples[2] s1, s2 = metric.samples[1], metric.samples[2]
@test s1.labels.labelvalues == ("/bar/", "404") @test s1.label_values.label_values == ("/bar/", "404")
@test s2.labels.labelvalues == ("/foo/", "200") @test s2.label_values.label_values == ("/foo/", "200")
@test s1.value == 3 @test s1.value == 3
@test s2.value == 3 @test s2.value == 3
# Prometheus.expose_metric(...) # Prometheus.expose_metric(...)
@ -292,8 +292,8 @@ end
@test metric.help == c.help @test metric.help == c.help
@test length(metric.samples) == 4 @test length(metric.samples) == 4
s1, s2, s3, s4 = metric.samples s1, s2, s3, s4 = metric.samples
@test s1.labels.labelvalues == s2.labels.labelvalues == ("/bar/", "404") @test s1.label_values.label_values == s2.label_values.label_values == ("/bar/", "404")
@test s3.labels.labelvalues == s4.labels.labelvalues == ("/foo/", "200") @test s3.label_values.label_values == s4.label_values.label_values == ("/foo/", "200")
@test s1.value == 2 # _count @test s1.value == 2 # _count
@test s2.value == 6.4 # _sum @test s2.value == 6.4 # _sum
@test s3.value == 2 # _count @test s3.value == 2 # _count

Loading…
Cancel
Save