opentelemetry-rust
opentelemetry-rust copied to clipboard
Add default attributes for each metrics
Hi, is there a way we could give each metrics a list of default attributes?
Take the hyper-prometheus as an example. It contains the 3 metrics below.
Code: https://github.com/open-telemetry/opentelemetry-rust/blob/main/examples/hyper-prometheus/src/main.rs
let state = Arc::new(AppState {
exporter,
http_counter: meter
.u64_counter("example.http_requests_total")
.with_description("Total number of HTTP requests made.")
.init(),
http_body_gauge: meter
.u64_histogram("example.http_response_size_bytes")
.with_description("The metrics HTTP response sizes in bytes.")
.init(),
http_req_histogram: meter
.f64_histogram("example.http_request_duration_seconds")
.with_description("The HTTP request latencies in seconds.")
.init(),
});
And say, we would like to log the server location, tenant name, service name, and url for each metrics, which they first 3 are always the same for all metrics, while the url is the only one that changes. However, we will have to do this in every request call, which can be annoying to write, yet have to create/copy the data every time. We can make some helper functions to simplify the code a bit,, but still it will need to copy the strings around.
state.http_counter.add(&cx, 1, &[
KeyValue { key: "Region".into(), Value: "West US".into() }, // In real case, this might be passed in as String, so we will need to copy here.
KeyValue { key: "Tenant".into(), Value: "My Deployment".into() },
KeyValue { key: "Service".into(), Value: "My Service".into() },
KeyValue { key: "Url".into(), Value: "/foo".into() }, // or /bar, or something, depends on what request it is.
]);
......
state.http_req_histogram.record(
&cx,
request_start.elapsed().map_or(0.0, |d| d.as_secs_f64()),
&[
KeyValue { key: "Region".into(), value: "West US".into() },
KeyValue { key: "Tenant".into(), value: "My Deployment".into() },
KeyValue { key: "Service".into(), value: "My Service".into() },
KeyValue { key: "Url".into(), value: "/foo".into() }, // or /bar, or something, depends on what request it is.
],
);
......
So I wonder if we could create 2 new things to passing the default attributes:
- When creating
Meter
, we can add a list of default attributes that shares by all metrics. - When calling
meter
to create metrics, we can add the extra default attributes for each metrics.
I think we can add attributes
in get_meter
function in MeterProvider
, which is introduced in 1.13. s
[since 1.13.0] attributes (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry.
Thanks for helping, @TommyCpp ! and do you mean this MeterProvider: https://docs.rs/opentelemetry/latest/opentelemetry/metrics/trait.MeterProvider.html ? I did some search, I found this function in python open telemetry API, but not rust. but maybe I am not looking at the right place.
And later I found we can use promethues::Registry::new_custom function to create a registry with customized attributes, and register it to the exporter. However, it only allow us to add a set of global common attributes, but we could add attributes when creating the meters.
d do you mean this MeterProvider: https://docs.rs/opentelemetry/latest/opentelemetry/metrics/trait.MeterProvider.html
Yeah, we are still working on bringing some new parameters to the MeterProvider
so you can expect to have such ability on the next release. I will link the PR once it finishes
Woot! This is an awesome news! Thanks a lot!!
#815 has been released in #1156
And say, we would like to log the server location, tenant name, service name, and url for each metrics, which they first 3 are always the same for all metrics, while the url is the only one that changes
tenant name, service name, and url -- These should be modelled as Resource in OpenTelemetry @r12f FYI.
How does it work now?
How does it work now?
can you clarify which part are you asking about? InstrumentationScope support is already added (This can be thought of attributes for Meter, so applies to all instruments created from that Meter). Resource support is already added (applied to entire MeterProvider.)
Unfortunately, the docs are not so much explicit about this, and neither are the examples :( I'll address that soon.
pub fn init_meter(registry: &Registry) -> Result<Meter, ControllerError> {
let exporter = opentelemetry_prometheus::exporter()
.with_registry(registry.clone())
.build()
.map_err(|_| ControllerError::ConfigurationError)?;
let provider = MeterProvider::builder().with_reader(exporter).build();
// Ok(provider.meter("github-operator"))
Ok(provider.versioned_meter(
"github-operator",
Some("0.1.0"),
Some("0.1.0"),
Some(vec![
KeyValue::new(
"environment".to_string(),
std::env::var("APP_ENVIRONMENT").unwrap_or("local".into()),
),
KeyValue::new("app".to_string(), "github-operator".to_string()),
]),
))
}
attributes are ignored:
# HELP operator_results_total reconciliation results of the operator
# TYPE operator_results_total counter
operator_results_total{controller="repository-github-controller",status="ok",otel_scope_name="github-operator",otel_scope_version="0.1.0"} 3
# HELP otel_scope_info Instrumentation Scope metadata
# TYPE otel_scope_info gauge
otel_scope_info{otel_scope_name="github-operator",otel_scope_version="0.1.0"} 1
# HELP target_info Target metadata
# TYPE target_info gauge
target_info{service_name="github-operator",telemetry_sdk_language="rust",telemetry_sdk_name="opentelemetry",telemetry_sdk_version="0.21.2"} 1
^ Please open a new issue for that, as it seems to be only in the prometheus exporter.
Also, std::env::var("APP_ENVIRONMENT").unwrap_or("local".into()),
better fits Resource model, unless it is only applicable to a particular meter!