diff --git a/src/Prometheus.jl b/src/Prometheus.jl index 916cdc3..4dc3346 100644 --- a/src/Prometheus.jl +++ b/src/Prometheus.jl @@ -202,7 +202,7 @@ function collect!(metrics::Vector, counter::Counter) push!(metrics, Metric( "counter", counter.metric_name, counter.help, - nothing, Sample(nothing, nothing, @atomic(counter.value)), + Sample(nothing, nothing, nothing, @atomic(counter.value)), ), ) return metrics @@ -310,7 +310,7 @@ function collect!(metrics::Vector, gauge::Gauge) push!(metrics, Metric( "gauge", gauge.metric_name, gauge.help, - nothing, Sample(nothing, nothing, @atomic(gauge.value)), + Sample(nothing, nothing, nothing, @atomic(gauge.value)), ), ) return metrics @@ -381,10 +381,10 @@ end function collect!(metrics::Vector, summary::Summary) push!(metrics, Metric( - "summary", summary.metric_name, summary.help, nothing, + "summary", summary.metric_name, summary.help, [ - Sample("_count", nothing, @atomic(summary._count)), - Sample("_sum", nothing, @atomic(summary._sum)), + Sample("_count", nothing, nothing, @atomic(summary._count)), + Sample("_sum", nothing, nothing, @atomic(summary._sum)), ] ), ) @@ -748,8 +748,9 @@ function collect!(metrics::Vector, family::Family{C}) where C type = prometheus_type(C) samples = Sample[] buf = Metric[] + label_names = family.label_names @lock family.lock begin - for (labels, child) in family.children + for (label_values, child) in family.children # collect!(...) the child, throw away the metric, but keep the samples child_metrics = collect!(resize!(buf, 0), child) length(child_metrics) != 1 && unreachable() # TODO: maybe this should be supported? @@ -758,12 +759,12 @@ function collect!(metrics::Vector, family::Family{C}) where C # Unwrap and rewrap samples with the labels child_samples = child_metric.samples if child_samples isa Sample - push!(samples, Sample(child_samples.suffix, labels, child_samples.value)) + push!(samples, Sample(child_samples.suffix, label_names, label_values, child_samples.value)) else @assert(child_samples isa Vector{Sample}) for child_sample in child_samples @assert(child_sample.label_values === nothing) - push!(samples, Sample(child_sample.suffix, labels, child_sample.value)) + push!(samples, Sample(child_sample.suffix, label_names, label_values, child_sample.value)) end end end @@ -776,7 +777,7 @@ function collect!(metrics::Vector, family::Family{C}) where C end) push!( metrics, - Metric(type, family.metric_name, family.help, family.label_names, samples), + Metric(type, family.metric_name, family.help, samples), ) return metrics end @@ -788,6 +789,7 @@ end struct Sample suffix::Union{String, Nothing} # e.g. _count or _sum + label_names::Union{LabelNames, Nothing} label_values::Union{LabelValues, Nothing} value::Float64 end @@ -796,7 +798,6 @@ struct Metric type::String metric_name::String help::String - label_names::Union{LabelNames, Nothing} # TODO: Union{Tuple{Sample}, Vector{Sample}} would always make this iterable. samples::Union{Sample, Vector{Sample}} end @@ -817,11 +818,10 @@ function expose_metric(io::IO, metric::Metric) print_escaped(io, metric.help, ('\\', '\n')) println(io) println(io, "# TYPE ", metric.metric_name, " ", metric.type) - label_names = metric.label_names samples = metric.samples if samples isa Sample # Single sample, no labels - @assert(label_names === nothing) + @assert(samples.label_names === nothing) @assert(samples.label_values === nothing) @assert(samples.suffix === nothing) val = samples.value @@ -837,11 +837,13 @@ function expose_metric(io::IO, metric::Metric) print(io, sample.suffix) end # Print potential labels - labels = sample.label_values - if label_names !== nothing && labels !== nothing + label_names = sample.label_names + label_values = sample.label_values + @assert((label_names === nothing) === (label_values === nothing)) + if label_names !== nothing && label_values !== nothing first = true print(io, "{") - for (name, value) in zip(label_names.label_names, labels.label_values) + for (name, value) in zip(label_names.label_names, label_values.label_values) first || print(io, ",") print(io, name, "=\"") print_escaped(io, value, ('\\', '\"', '\n')) diff --git a/src/gc_collector.jl b/src/gc_collector.jl index bb95e74..e5a15ab 100644 --- a/src/gc_collector.jl +++ b/src/gc_collector.jl @@ -44,40 +44,42 @@ function collect!(metrics::Vector, ::GCCollector) gc_live_bytes = Base.gc_live_bytes() # Push all the metrics push!(metrics, - Metric( - "counter", "julia_gc_alloc_total", "Total number of allocations (calls to malloc, realloc, etc)", - LabelNames(("type",)), - [ - Sample(nothing, LabelValues(("bigalloc",)), gc_num.bigalloc), - Sample(nothing, LabelValues(("malloc",)), gc_num.malloc), - Sample(nothing, LabelValues(("poolalloc",)), gc_num.poolalloc), - Sample(nothing, LabelValues(("realloc",)), gc_num.realloc), - ], - ), + let label_names = LabelNames(("type",)) + Metric( + "counter", "julia_gc_alloc_total", "Total number of allocations (calls to malloc, realloc, etc)", + [ + Sample(nothing, label_names, LabelValues(("bigalloc",)), gc_num.bigalloc), + Sample(nothing, label_names, LabelValues(("malloc",)), gc_num.malloc), + Sample(nothing, label_names, LabelValues(("poolalloc",)), gc_num.poolalloc), + Sample(nothing, label_names, LabelValues(("realloc",)), gc_num.realloc), + ], + ) + end, Metric( "counter", "julia_gc_free_total", "Total number of calls to free()", - nothing, Sample(nothing, nothing, gc_num.freecall), - ), - Metric( - "counter", "julia_gc_alloc_bytes_total", "Total number of allocated bytes", nothing, - Sample(nothing, nothing, Base.gc_total_bytes(gc_num)), + Sample(nothing, nothing, nothing, gc_num.freecall), ), Metric( - "gauge", "julia_gc_live_bytes", "Current number of live bytes", nothing, - Sample(nothing, nothing, gc_live_bytes), + "counter", "julia_gc_alloc_bytes_total", "Total number of allocated bytes", + Sample(nothing, nothing, nothing, Base.gc_total_bytes(gc_num)), ), Metric( - "counter", "julia_gc_seconds_total", "Total time spent in garbage collection", nothing, - Sample(nothing, nothing, gc_num.total_time / 10^9), # [ns] to [s] + "gauge", "julia_gc_live_bytes", "Current number of live bytes", + Sample(nothing, nothing, nothing, gc_live_bytes), ), Metric( - "counter", "julia_gc_collections_total", "Total number of calls to garbage collection", - LabelNames(("type",)), - [ - Sample(nothing, LabelValues(("full",)), gc_num.full_sweep), - Sample(nothing, LabelValues(("minor",)), gc_num.pause - gc_num.full_sweep), - ], + "counter", "julia_gc_seconds_total", "Total time spent in garbage collection", + Sample(nothing, nothing, nothing, gc_num.total_time / 10^9), # [ns] to [s] ), + let label_names = LabelNames(("type",)) + Metric( + "counter", "julia_gc_collections_total", "Total number of calls to garbage collection", + [ + Sample(nothing, label_names, LabelValues(("full",)), gc_num.full_sweep), + Sample(nothing, label_names, LabelValues(("minor",)), gc_num.pause - gc_num.full_sweep), + ], + ) + end, ) return metrics end diff --git a/src/process_collector.jl b/src/process_collector.jl index 2717651..8bb19b5 100644 --- a/src/process_collector.jl +++ b/src/process_collector.jl @@ -118,13 +118,13 @@ function collect!(metrics::Vector, procc::ProcessCollector) if procc.clock_ticks_per_second > 0 utime = parse(Int, fields[14 - 2]) / procc.clock_ticks_per_second stime = parse(Int, fields[15 - 2]) / procc.clock_ticks_per_second + label_names = LabelNames(("mode",)) proc_cpu_seconds = Metric( "counter", "process_cpu_seconds_total", "Total CPU time (user and system mode) in seconds.", - LabelNames(("mode",)), [ - Sample(nothing, LabelValues(("system",)), stime), - Sample(nothing, LabelValues(("user",)), utime), + Sample(nothing, label_names, LabelValues(("system",)), stime), + Sample(nothing, label_names, LabelValues(("user",)), utime), ], ) push!(metrics, proc_cpu_seconds) @@ -132,16 +132,16 @@ function collect!(metrics::Vector, procc::ProcessCollector) starttime = parse(Int, fields[22 - 2]) / procc.clock_ticks_per_second proc_start_time = Metric( "gauge", "process_start_time_seconds", - "Start time since unix epoch in seconds.", nothing, - Sample(nothing, nothing, starttime + procc.system_boot_time), + "Start time since unix epoch in seconds.", + Sample(nothing, nothing, nothing, starttime + procc.system_boot_time), ) push!(metrics, proc_start_time) end # Virtual memory vsize = parse(Int, fields[23 - 2]) proc_virtual_memory = Metric( - "gauge", "process_virtual_memory_bytes", "Virtual memory size in bytes.", nothing, - Sample(nothing, nothing, vsize), + "gauge", "process_virtual_memory_bytes", "Virtual memory size in bytes.", + Sample(nothing, nothing, nothing, vsize), ) push!(metrics, proc_virtual_memory) if procc.pagesize > 0 @@ -149,8 +149,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) rss = parse(Int, fields[24 - 2]) proc_resident_memory = Metric( "gauge", "process_resident_memory_bytes", - "Resident memory size (RSS) in bytes.", nothing, - Sample(nothing, nothing, rss * procc.pagesize), + "Resident memory size (RSS) in bytes.", + Sample(nothing, nothing, nothing, rss * procc.pagesize), ) push!(metrics, proc_resident_memory) end @@ -166,8 +166,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) # Open file descriptors proc_open_fds = Metric( "gauge", "process_open_fds", - "Number of open file descriptors.", nothing, - Sample(nothing, nothing, proc_fd), + "Number of open file descriptors.", + Sample(nothing, nothing, nothing, proc_fd), ) push!(metrics, proc_open_fds) # TODO: Maybe add maximum open fds from /proc/$(pid)/limits like the Python client @@ -184,8 +184,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) if rchar !== nothing proc_io_rchar = Metric( "counter", "process_io_rchar_bytes_total", - "Total number of bytes read in bytes (rchar from /proc/[pid]/io).", nothing, - Sample(nothing, nothing, parse(Int, rchar.captures[1]::AbstractString)), + "Total number of bytes read in bytes (rchar from /proc/[pid]/io).", + Sample(nothing, nothing, nothing, parse(Int, rchar.captures[1]::AbstractString)), ) push!(metrics, proc_io_rchar) end @@ -193,8 +193,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) if wchar !== nothing proc_io_wchar = Metric( "counter", "process_io_wchar_bytes_total", - "Total number of bytes written in bytes (wchar from /proc/[pid]/io).", nothing, - Sample(nothing, nothing, parse(Int, wchar.captures[1]::AbstractString)), + "Total number of bytes written in bytes (wchar from /proc/[pid]/io).", + Sample(nothing, nothing, nothing, parse(Int, wchar.captures[1]::AbstractString)), ) push!(metrics, proc_io_wchar) end @@ -202,8 +202,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) if syscr !== nothing proc_io_syscr = Metric( "counter", "process_io_syscr_total", - "Total number of read I/O operations (syscalls) (syscr from /proc/[pid]/io).", nothing, - Sample(nothing, nothing, parse(Int, syscr.captures[1]::AbstractString)), + "Total number of read I/O operations (syscalls) (syscr from /proc/[pid]/io).", + Sample(nothing, nothing, nothing, parse(Int, syscr.captures[1]::AbstractString)), ) push!(metrics, proc_io_syscr) end @@ -211,8 +211,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) if syscw !== nothing proc_io_syscw = Metric( "counter", "process_io_syscw_total", - "Total number of write I/O operations (syscalls) (syscw from /proc/[pid]/io).", nothing, - Sample(nothing, nothing, parse(Int, syscw.captures[1]::AbstractString)), + "Total number of write I/O operations (syscalls) (syscw from /proc/[pid]/io).", + Sample(nothing, nothing, nothing, parse(Int, syscw.captures[1]::AbstractString)), ) push!(metrics, proc_io_syscw) end @@ -220,8 +220,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) if read_bytes !== nothing proc_io_read_bytes = Metric( "counter", "process_io_read_bytes_total", - "Total number of bytes read from the file system (read_bytes from /proc/[pid]/io).", nothing, - Sample(nothing, nothing, parse(Int, read_bytes.captures[1]::AbstractString)), + "Total number of bytes read from the file system (read_bytes from /proc/[pid]/io).", + Sample(nothing, nothing, nothing, parse(Int, read_bytes.captures[1]::AbstractString)), ) push!(metrics, proc_io_read_bytes) end @@ -229,8 +229,8 @@ function collect!(metrics::Vector, procc::ProcessCollector) if write_bytes !== nothing proc_io_write_bytes = Metric( "counter", "process_io_write_bytes_total", - "Total number of bytes written to the file system (write_bytes from /proc/[pid]/io).", nothing, - Sample(nothing, nothing, parse(Int, write_bytes.captures[1]::AbstractString)), + "Total number of bytes written to the file system (write_bytes from /proc/[pid]/io).", + Sample(nothing, nothing, nothing, parse(Int, write_bytes.captures[1]::AbstractString)), ) push!(metrics, proc_io_write_bytes) end