diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index d414b20667..e2c3276c7d 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -259,6 +259,32 @@ static bool compare_histograms(const std::optional& a, const std::optional return comparer(a, b, metric_record_type); } +static VectorValPtr build_label_values_vector(const std::vector& prom_labels, + const VectorValPtr& record_label_names) { + static auto string_vec_type = zeek::id::find_type("string_vec"); + auto label_values_vec = make_intrusive(string_vec_type); + + // This feels really bad, since it's an O(m*n) search to bulld the vector, + // but prometheus-cpp returns us a vector of labels and so we just have to + // search through it. + int i = 0; + for ( const auto& name : record_label_names->RawVec() ) { + auto n = name->AsString()->ToStdStringView(); + auto it = std::find_if(prom_labels.begin(), prom_labels.end(), + [n](const prometheus::ClientMetric::Label& l) { return l.name == n; }); + if ( it != prom_labels.end() ) + label_values_vec->Assign(i, make_intrusive(it->value)); + + // See the comment in GetMetricOptsRecord about how labels from non-Zeek + // metrics within the same family can have different labels from each + // other. In this case we might leave some fields null in the output. + + ++i; + } + + return label_values_vec; +} + ValPtr Manager::CollectMetrics(std::string_view prefix_pattern, std::string_view name_pattern) { static auto metrics_vector_type = zeek::id::find_type("Telemetry::MetricVector"); static auto string_vec_type = zeek::id::find_type("string_vec"); @@ -287,17 +313,11 @@ ValPtr Manager::CollectMetrics(std::string_view prefix_pattern, std::string_view continue; RecordValPtr opts_record = GetMetricOptsRecord(fam); + const auto& label_names = opts_record->GetField("labels"); for ( const auto& inst : fam.metric ) { - auto label_values_vec = make_intrusive(string_vec_type); - for ( const auto& label : inst.label ) { - // We don't include the endpoint key/value unless it's a prometheus request - if ( label.name != "endpoint" ) - label_values_vec->Append(make_intrusive(label.value)); - } - auto r = make_intrusive(metric_record_type); - r->Assign(labels_idx, label_values_vec); + r->Assign(labels_idx, build_label_values_vector(inst.label, label_names)); r->Assign(opts_idx, opts_record); if ( fam.type == prometheus::MetricType::Counter ) @@ -360,17 +380,11 @@ ValPtr Manager::CollectHistogramMetrics(std::string_view prefix_pattern, std::st continue; RecordValPtr opts_record = GetMetricOptsRecord(fam); + const auto& label_names = opts_record->GetField("labels"); for ( const auto& inst : fam.metric ) { - auto label_values_vec = make_intrusive(string_vec_type); - for ( const auto& label : inst.label ) { - // We don't include the endpoint key/value unless it's a prometheus request - if ( label.name != "endpoint" ) - label_values_vec->Append(make_intrusive(label.value)); - } - auto r = make_intrusive(histogram_metric_type); - r->Assign(labels_idx, label_values_vec); + r->Assign(labels_idx, build_label_values_vector(inst.label, label_names)); r->Assign(opts_idx, opts_record); auto double_values_vec = make_intrusive(double_vec_type); diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.telemetry/telemetry.log b/testing/btest/Baseline/scripts.base.frameworks.logging.telemetry/telemetry.log index a84c0f505c..e06856304b 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.telemetry/telemetry.log +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.telemetry/telemetry.log @@ -10,7 +10,7 @@ XXXXXXXXXX.XXXXXX zeek counter zeek_log_stream_writes_total module,stream Conn,Conn::LOG 34.0 XXXXXXXXXX.XXXXXX zeek counter zeek_log_stream_writes_total module,stream DNS,DNS::LOG 34.0 XXXXXXXXXX.XXXXXX zeek counter zeek_log_stream_writes_total module,stream HTTP,HTTP::LOG 14.0 -XXXXXXXXXX.XXXXXX zeek counter zeek_log_writer_writes_total writer,module,stream,filter-name,path default,Conn,conn,Conn::LOG,Log::WRITER_ASCII 30.0 -XXXXXXXXXX.XXXXXX zeek counter zeek_log_writer_writes_total writer,module,stream,filter-name,path default,DNS,dns,DNS::LOG,Log::WRITER_ASCII 23.0 -XXXXXXXXXX.XXXXXX zeek counter zeek_log_writer_writes_total writer,module,stream,filter-name,path default,HTTP,http,HTTP::LOG,Log::WRITER_ASCII 10.0 +XXXXXXXXXX.XXXXXX zeek counter zeek_log_writer_writes_total writer,module,stream,filter-name,path Log::WRITER_ASCII,Conn,Conn::LOG,-,conn 30.0 +XXXXXXXXXX.XXXXXX zeek counter zeek_log_writer_writes_total writer,module,stream,filter-name,path Log::WRITER_ASCII,DNS,DNS::LOG,-,dns 23.0 +XXXXXXXXXX.XXXXXX zeek counter zeek_log_writer_writes_total writer,module,stream,filter-name,path Log::WRITER_ASCII,HTTP,HTTP::LOG,-,http 10.0 #close XXXX-XX-XX-XX-XX-XX