in src/lib.rs [227:339]
fn init_metrics(config: Config) -> (Option<PrometheusRegistry>, SdkMeterProvider) {
let mut keys = vec![KeyValue::new(SERVICE_NAME_KEY, config.service_name.clone())];
if let Some(resource_attributes) = config.resource_attributes {
for attribute in resource_attributes {
keys.push(KeyValue::new(attribute.key, attribute.value));
}
}
let mut meter_provider_builder = SdkMeterProvider::builder().with_resource(Resource::new(keys));
// Setup Prometheus Registry if configured
let prometheus_registry = if let Some(prometheus_config) = config.prometheus_config {
let registry = prometheus::Registry::new();
match opentelemetry_prometheus::exporter()
.with_registry(registry.clone())
.build()
{
Ok(exporter) => {
meter_provider_builder = meter_provider_builder.with_reader(exporter);
Some(PrometheusRegistry {
registry,
port: prometheus_config.port,
})
}
Err(e) => {
error!("unable to setup prometheus endpoint due to: {:?}", e);
None
}
}
} else {
None
};
// Add Metrics Exporters
if let Some(export_targets_list) = config.metrics_export_targets {
for export_target in export_targets_list {
let export_config = ExportConfig {
endpoint: export_target.url.clone(),
timeout: Duration::from_secs(export_target.timeout),
protocol: Protocol::Grpc,
};
let temporality_selector: Box<dyn TemporalitySelector> =
if let Some(temporality) = export_target.temporality {
match temporality {
Temporality::Delta => Box::new(DeltaTemporalitySelector::new()),
_ => Box::new(DefaultTemporalitySelector::new()),
}
} else {
Box::new(DefaultTemporalitySelector::new())
};
let mut exporter_builder = opentelemetry_otlp::new_exporter().tonic();
if let Some(bearer_token_provider_fn) = export_target.bearer_token_provider_fn {
let auth_interceptor = AuthIntercepter {
bearer_token_provider_fn,
};
exporter_builder = exporter_builder.with_interceptor(auth_interceptor);
}
exporter_builder = match handle_tls(
exporter_builder,
&export_target.url,
export_target.ca_cert_path,
Duration::from_secs(export_target.timeout),
) {
Ok(exporter_builder) => exporter_builder,
Err(_) => {
continue;
}
};
let exporter = match exporter_builder
.with_export_config(export_config)
.build_metrics_exporter(
// TODO: Make this also part of config?
Box::new(DefaultAggregationSelector::new()),
temporality_selector,
) {
Ok(exporter) => exporter,
Err(e) => {
error!(
"unable to set export to {} due to {:?}",
export_target.url, e
);
continue;
}
};
let reader = PeriodicReader::builder(exporter, runtime::Tokio)
.with_interval(Duration::from_secs(export_target.interval_secs))
.build();
meter_provider_builder = meter_provider_builder.with_reader(reader);
}
}
if config.emit_metrics_to_stdout {
let exporter = MetricsExporterBuilder::default()
.with_encoder(|writer, data| {
if let Err(e) = serde_json::to_writer_pretty(writer, &data) {
error!("writing metrics to log failed due to: {:?}", e);
}
Ok(())
})
.build();
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
meter_provider_builder = meter_provider_builder.with_reader(reader);
}
let meter_provider = meter_provider_builder.build();
global::set_meter_provider(meter_provider.clone());
(prometheus_registry, meter_provider)
}