Coverage Report

Created: 2025-04-19 16:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/nativelink-metric-collector/src/otel_exporter.rs
Line
Count
Source
1
// Copyright 2024 The NativeLink Authors. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use opentelemetry::metrics::Meter;
16
use tracing::info;
17
18
use crate::metrics_collection::{
19
    CollectedMetricChildren, CollectedMetricPrimitive, CollectedMetricPrimitiveValue,
20
    CollectedMetrics, RootMetricCollectedMetrics,
21
};
22
23
/// The maximum length of a metric name that otel supports.
24
/// Going beyond this limit causes otel to complain.
25
const MAX_METRIC_NAME_LENGTH: usize = 256;
26
27
/// Export the collected metrics to the OpenTelemetry meter.
28
0
pub fn otel_export(
29
0
    mut root_prefix: String,
30
0
    meter: &Meter,
31
0
    root_collected_metrics: &RootMetricCollectedMetrics,
32
0
) {
33
0
    if !root_prefix.is_empty() {
  Branch (33:8): [True: 0, False: 0]
  Branch (33:8): [Folded - Ignored]
34
0
        root_prefix.push('_');
35
0
    }
36
0
    process_children(&mut root_prefix, meter, root_collected_metrics);
37
0
}
38
39
0
fn process_children(prefix: &mut String, meter: &Meter, children: &CollectedMetricChildren) {
40
0
    for (name, child) in children {
41
0
        prefix.push_str(name);
42
0
        let mut added_prefix_len = name.len();
43
0
        match child {
44
0
            CollectedMetrics::Primitive(primitive) => {
45
0
                process_primitive(prefix, meter, primitive);
46
0
            }
47
0
            CollectedMetrics::Component(component) => {
48
0
                prefix.push('_');
49
0
                added_prefix_len += 1;
50
0
                process_children(prefix, meter, component);
51
0
            }
52
        }
53
0
        prefix.truncate(prefix.len() - added_prefix_len);
54
    }
55
0
}
56
57
0
fn process_primitive(prefix: &mut String, meter: &Meter, primitive: &CollectedMetricPrimitive) {
58
0
    match &primitive.value {
59
0
        Some(CollectedMetricPrimitiveValue::Counter(value)) => {
60
0
            if prefix.len() > MAX_METRIC_NAME_LENGTH {
  Branch (60:16): [True: 0, False: 0]
  Branch (60:16): [Folded - Ignored]
61
0
                info!("Metric name longer than 256 characters: {}", prefix);
62
0
                return;
63
0
            }
64
0
            let counter = meter
65
0
                .u64_counter(prefix.clone())
66
0
                .with_description(primitive.help.clone())
67
0
                .build();
68
0
            counter.add(*value, &[]);
69
        }
70
0
        Some(CollectedMetricPrimitiveValue::String(_value)) => {
71
0
            // We don't publish strings in metrics.
72
0
        }
73
0
        None => {}
74
    }
75
0
}