Coverage Report

Created: 2024-10-22 12:33

/build/source/nativelink-metric-collector/src/otel_exporter.rs
Line
Count
Source (jump to first uncovered line)
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
1
pub fn otel_export(
29
1
    mut root_prefix: String,
30
1
    meter: &Meter,
31
1
    root_collected_metrics: &RootMetricCollectedMetrics,
32
1
) {
33
1
    if !root_prefix.is_empty() {
  Branch (33:8): [True: 1, False: 0]
  Branch (33:8): [Folded - Ignored]
34
1
        root_prefix.push('_');
35
1
    }
0
36
1
    process_children(&mut root_prefix, meter, root_collected_metrics);
37
1
}
38
39
2
fn process_children(prefix: &mut String, meter: &Meter, children: &CollectedMetricChildren) {
40
9
    for (
name, child7
) in children {
41
7
        prefix.push_str(name);
42
7
        let mut added_prefix_len = name.len();
43
7
        match child {
44
6
            CollectedMetrics::Primitive(primitive) => {
45
6
                process_primitive(prefix, meter, primitive);
46
6
            }
47
1
            CollectedMetrics::Component(component) => {
48
1
                prefix.push('_');
49
1
                added_prefix_len += 1;
50
1
                process_children(prefix, meter, component);
51
1
            }
52
        }
53
7
        prefix.truncate(prefix.len() - added_prefix_len);
54
    }
55
2
}
56
57
6
fn process_primitive(prefix: &mut String, meter: &Meter, primitive: &CollectedMetricPrimitive) {
58
6
    match &primitive.value {
59
3
        Some(CollectedMetricPrimitiveValue::Counter(value)) => {
60
3
            if prefix.len() > MAX_METRIC_NAME_LENGTH {
  Branch (60:16): [True: 0, False: 3]
  Branch (60:16): [Folded - Ignored]
61
0
                info!("Metric name longer than 256 characters: {}", prefix);
62
0
                return;
63
3
            }
64
3
            let counter = meter
65
3
                .u64_counter(prefix.clone())
66
3
                .with_description(primitive.help.clone())
67
3
                .init();
68
3
            counter.add(*value, &[]);
69
        }
70
3
        Some(CollectedMetricPrimitiveValue::String(_value)) => {
71
3
            // We don't publish strings in metrics.
72
3
        }
73
0
        None => {}
74
    }
75
6
}