Skip to content

Commit 2992f46

Browse files
authored
feat(otap-dataflow): Add scope_name selector to Metric views (open-telemetry#2527)
# Change Summary Add `scope_name` selector to Metric views - Optional config alongside existing `instrument_name` - Fixed yaml indentation of `fake-debug` configs ## What issue does this PR close? * Closes open-telemetry#2500 ## How are these changes tested? Ran the fake debug configs and queried admin `/metrics` endpoint to see resulting views ## Are there any user-facing changes? No
1 parent 854ffd8 commit 2992f46

4 files changed

Lines changed: 108 additions & 21 deletions

File tree

rust/otap-dataflow/configs/fake-debug-noop-promethueus-telemetry.yaml

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@ engine:
99
host: "0.0.0.0"
1010
port: 9090
1111
path: "/metrics"
12-
views:
13-
- selector:
14-
instrument_name: "logs.produced"
15-
stream:
16-
name: "otlp.logs.produced.count"
17-
description: "Count of logs produced"
12+
views:
13+
- selector:
14+
scope_name: "fake_data_generator.receiver.metrics"
15+
instrument_name: "logs.produced"
16+
stream:
17+
name: "otlp.logs.produced.count"
18+
description: "Count of logs produced"
19+
- selector:
20+
scope_name: "debug.processor.pdata.metrics"
21+
instrument_name: "logs.consumed"
22+
stream:
23+
name: "debug.logs.consumed.count"
24+
description: "Count of log messages consumed by debug processor"
1825
resource:
1926
service.name: "fake-debug-noop-service"
2027
groups:
@@ -23,10 +30,10 @@ groups:
2330
main:
2431
policies:
2532
channel_capacity:
26-
control:
27-
node: 100
28-
pipeline: 100
29-
pdata: 128
33+
control:
34+
node: 100
35+
pipeline: 100
36+
pdata: 128
3037

3138
nodes:
3239
receiver:

rust/otap-dataflow/configs/fake-debug-noop-telemetry.yaml

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,19 @@ engine:
1010
otlp:
1111
protocol: "grpc/protobuf"
1212
endpoint: "http://127.0.0.1:43480"
13-
views:
14-
- selector:
15-
instrument_name: "logs.produced"
16-
stream:
17-
name: "otlp.logs.produced.count"
18-
description: "Count of logs produced"
13+
views:
14+
- selector:
15+
scope_name: "fake_data_generator.receiver.metrics"
16+
instrument_name: "logs.produced"
17+
stream:
18+
name: "otlp.logs.produced.count"
19+
description: "Count of logs produced"
20+
- selector:
21+
scope_name: "debug.processor.pdata.metrics"
22+
instrument_name: "logs.consumed"
23+
stream:
24+
name: "debug.logs.consumed.count"
25+
description: "Count of log messages consumed by debug processor"
1926
resource:
2027
service.name: "fake-debug-noop-service"
2128
service.instance.id: "${env:STATEFULSET_ORDINAL:-unknown}"
@@ -25,10 +32,10 @@ groups:
2532
main:
2633
policies:
2734
channel_capacity:
28-
control:
29-
node: 100
30-
pipeline: 100
31-
pdata: 128
35+
control:
36+
node: 100
37+
pipeline: 100
38+
pdata: 128
3239

3340
nodes:
3441
receiver:

rust/otap-dataflow/crates/config/src/pipeline/telemetry/metrics/views.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ pub struct ViewConfig {
2121
pub struct MetricSelector {
2222
/// The name of the instrument to match.
2323
pub instrument_name: Option<String>,
24-
// TODO: Add more selector fields.
24+
/// The instrumentation scope (meter) name to match.
25+
/// When set, the view only applies to instruments created under this scope.
26+
pub scope_name: Option<String>,
2527
}
2628

2729
/// OpenTelemetry Metric Stream configuration.
@@ -51,6 +53,7 @@ mod tests {
5153
config.selector.instrument_name.as_deref(),
5254
Some("requests.total")
5355
);
56+
assert_eq!(config.selector.scope_name.as_deref(), None);
5457
assert_eq!(config.stream.name.as_deref(), Some("http.requests.total"));
5558
assert_eq!(
5659
config.stream.description.as_deref(),
@@ -83,7 +86,33 @@ mod tests {
8386
"#;
8487
let config: ViewConfig = serde_yaml::from_str(yaml_str).unwrap();
8588
assert_eq!(config.selector.instrument_name.as_deref(), None);
89+
assert_eq!(config.selector.scope_name.as_deref(), None);
8690
assert_eq!(config.stream.name.as_deref(), None);
8791
assert_eq!(config.stream.description.as_deref(), None);
8892
}
93+
94+
#[test]
95+
fn test_view_config_with_scope_name() {
96+
let yaml_str = r#"
97+
selector:
98+
instrument_name: "successful_rows"
99+
scope_name: "azure_monitor_exporter.metrics"
100+
stream:
101+
name: "exporter_sent_log_records"
102+
description: "Number of log records successfully sent by the exporter."
103+
"#;
104+
let config: ViewConfig = serde_yaml::from_str(yaml_str).unwrap();
105+
assert_eq!(
106+
config.selector.instrument_name.as_deref(),
107+
Some("successful_rows")
108+
);
109+
assert_eq!(
110+
config.selector.scope_name.as_deref(),
111+
Some("azure_monitor_exporter.metrics")
112+
);
113+
assert_eq!(
114+
config.stream.name.as_deref(),
115+
Some("exporter_sent_log_records")
116+
);
117+
}
89118
}

rust/otap-dataflow/crates/telemetry/src/otel_sdk/meter_provider/views_provider.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ impl DeclarativeView {
4343
) -> impl Fn(&Instrument) -> Option<Stream> + Send + Sync + 'static {
4444
let config = self.config.clone();
4545
move |instrument: &Instrument| {
46+
if let Some(scope_name) = &config.selector.scope_name
47+
&& instrument.scope().name() != scope_name
48+
{
49+
return None;
50+
}
4651
if let Some(instrument_name) = &config.selector.instrument_name
4752
&& instrument.name() != instrument_name
4853
{
@@ -75,6 +80,7 @@ mod tests {
7580
let view_config = ViewConfig {
7681
selector: MetricSelector {
7782
instrument_name: Some("requests.total".to_string()),
83+
scope_name: None,
7884
},
7985
stream: MetricStream {
8086
name: Some("http.requests.total".to_string()),
@@ -92,6 +98,7 @@ mod tests {
9298
let view_config = ViewConfig {
9399
selector: MetricSelector {
94100
instrument_name: Some("requests.total".to_string()),
101+
scope_name: None,
95102
},
96103
stream: MetricStream {
97104
name: Some("http.requests.total".to_string()),
@@ -115,6 +122,7 @@ mod tests {
115122
let view_config = ViewConfig {
116123
selector: MetricSelector {
117124
instrument_name: Some("requests.total".to_string()),
125+
scope_name: None,
118126
},
119127
stream: MetricStream {
120128
name: Some("http.requests.total".to_string()),
@@ -124,4 +132,40 @@ mod tests {
124132
let declarative_view = DeclarativeView::new(view_config);
125133
let _view_function = declarative_view.to_view_funtion();
126134
}
135+
136+
#[test]
137+
fn test_views_provider_configure_with_scope_name() {
138+
let view_config = ViewConfig {
139+
selector: MetricSelector {
140+
instrument_name: Some("requests.total".to_string()),
141+
scope_name: Some("my.scope".to_string()),
142+
},
143+
stream: MetricStream {
144+
name: Some("http.requests.total".to_string()),
145+
description: Some("Total number of HTTP requests".to_string()),
146+
},
147+
};
148+
let views_config = vec![view_config];
149+
let sdk_meter_builder = SdkMeterProvider::builder();
150+
let result = ViewsProvider::configure(sdk_meter_builder, views_config);
151+
assert!(result.is_ok());
152+
}
153+
154+
#[test]
155+
fn test_views_provider_configure_with_scope_name_only() {
156+
let view_config = ViewConfig {
157+
selector: MetricSelector {
158+
instrument_name: None,
159+
scope_name: Some("azure_monitor_exporter.metrics".to_string()),
160+
},
161+
stream: MetricStream {
162+
name: None,
163+
description: Some("Scoped metrics".to_string()),
164+
},
165+
};
166+
let views_config = vec![view_config];
167+
let sdk_meter_builder = SdkMeterProvider::builder();
168+
let result = ViewsProvider::configure(sdk_meter_builder, views_config);
169+
assert!(result.is_ok());
170+
}
127171
}

0 commit comments

Comments
 (0)