Expand description
An Azure Application Insights exporter implementation for OpenTelemetry Rust.
Disclaimer: This is not an official Microsoft product.
§Usage
§Trace
This requires the trace (enabled by default) and opentelemetry-http/reqwest features.
use opentelemetry::{global, trace::Tracer};
use opentelemetry_sdk::trace::SdkTracerProvider;
fn main() {
let connection_string = std::env::var("APPLICATIONINSIGHTS_CONNECTION_STRING").unwrap();
let exporter = opentelemetry_application_insights::Exporter::new_from_connection_string(
connection_string,
reqwest::blocking::Client::new(),
)
.expect("valid connection string");
let tracer_provider = SdkTracerProvider::builder()
.with_batch_exporter(exporter)
.build();
global::set_tracer_provider(tracer_provider.clone());
let tracer = global::tracer("example");
tracer.in_span("main", |_cx| {});
tracer_provider.shutdown().unwrap();
}
§Logs
This requires the logs (enabled by default) and opentelemetry-http/reqwest features.
use log::{Level, info};
use opentelemetry_appender_log::OpenTelemetryLogBridge;
use opentelemetry_sdk::logs::SdkLoggerProvider;
fn main() {
// Setup exporter
let connection_string = std::env::var("APPLICATIONINSIGHTS_CONNECTION_STRING").unwrap();
let exporter = opentelemetry_application_insights::Exporter::new_from_connection_string(
connection_string,
reqwest::blocking::Client::new(),
)
.expect("valid connection string");
let logger_provider = SdkLoggerProvider::builder()
.with_batch_exporter(exporter)
.build();
let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
log::set_boxed_logger(Box::new(otel_log_appender)).unwrap();
log::set_max_level(Level::Info.to_level_filter());
// Log
let fruit = "apple";
let price = 2.99;
info!("{fruit} costs {price}");
// Export remaining logs before exiting
logger_provider.shutdown().unwrap();
}
§Metrics
This requires the metrics (enabled by default) and opentelemetry-http/reqwest features.
use opentelemetry::global;
use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider};
use std::time::Duration;
fn main() {
// Setup exporter
let connection_string = std::env::var("APPLICATIONINSIGHTS_CONNECTION_STRING").unwrap();
let exporter = opentelemetry_application_insights::Exporter::new_from_connection_string(
connection_string,
reqwest::blocking::Client::new(),
)
.expect("valid connection string");
let reader = PeriodicReader::builder(exporter).build();
let meter_provider = SdkMeterProvider::builder().with_reader(reader).build();
global::set_meter_provider(meter_provider.clone());
// Record value
let meter = global::meter("example");
let histogram = meter.f64_histogram("pi").build();
histogram.record(3.14, &[]);
// Simulate work, during which metrics will periodically be reported.
std::thread::sleep(Duration::from_secs(300));
meter_provider.shutdown().unwrap();
}
§Live Metrics
This requires the live-metrics feature and the experimental async runtime span processor API behind the opentelemetry_sdk/experimental_trace_batch_span_processor_with_async_runtime feature.
Enable live metrics collection: https://learn.microsoft.com/en-us/azure/azure-monitor/app/live-stream.
Metrics are based on traces. See attribute mapping below for how traces are mapped to requests, dependencies and exceptions and how they are deemed “successful” or not.
To configure role, instance, and machine name provide service.name
, service.instance.id
, and
host.name
resource attributes respectively in the resource.
Sample telemetry is not supported, yet.
use opentelemetry::{global, trace::Tracer};
use opentelemetry_sdk::trace::SdkTracerProvider;
#[tokio::main]
async fn main() {
let connection_string = std::env::var("APPLICATIONINSIGHTS_CONNECTION_STRING").unwrap();
let exporter = opentelemetry_application_insights::Exporter::new_from_connection_string(
connection_string,
reqwest::blocking::Client::new(),
)
.expect("valid connection string");
let tracer_provider = SdkTracerProvider::builder()
.with_span_processor(opentelemetry_sdk::trace::span_processor_with_async_runtime::BatchSpanProcessor::builder(exporter.clone(), opentelemetry_sdk::runtime::Tokio).build())
.with_span_processor(opentelemetry_application_insights::LiveMetricsSpanProcessor::new(exporter, opentelemetry_sdk::runtime::Tokio))
.build();
global::set_tracer_provider(tracer_provider.clone());
// ... send traces ...
tracer_provider.shutdown().unwrap();
}
§Async runtimes and HTTP clients
In order to support different async runtimes, the exporter requires you to specify an HTTP
client that works with your chosen runtime. The opentelemetry-http
crate comes with support
for:
reqwest
: enable the opentelemetry-http/reqwest feature and configure the exporter with eitherwith_client(reqwest::Client::new())
orwith_client(reqwest::blocking::Client::new())
.- and more…
Alternatively you can bring any other HTTP client by implementing the HttpClient
trait.
Map async/sync clients with the appropriate builder methods:
- Sync clients with
{SdkTracerProvider,SdkLoggerProvider}.with_batch_exporter
/PeriodicReader::builder
. If you’re already in an async context when creating the client, you might need to create it usingstd::thread::spawn(reqwest::blocking::Client::new).join().unwrap()
. - Async clients with the corresponding experimental async APIs. Or with the pipeline API and
build_batch
/install_batch
.
§Attribute mapping
OpenTelemetry and Application Insights are using different terminology. This crate tries its best to map OpenTelemetry fields to their correct Application Insights pendant.
§Resource
Resource and instrumentation library attributes map to the following fields for spans, events and metrics (the mapping tries to follow the OpenTelemetry semantic conventions for resource).
OpenTelemetry attribute key | Application Insights field |
---|---|
service.namespace + service.name | Context: Cloud role (ai.cloud.role ) |
k8s.deployment.name | Context: Cloud role (ai.cloud.role ) |
k8s.replicaset.name | Context: Cloud role (ai.cloud.role ) |
k8s.statefulset.name | Context: Cloud role (ai.cloud.role ) |
k8s.job.name | Context: Cloud role (ai.cloud.role ) |
k8s.cronjob.name | Context: Cloud role (ai.cloud.role ) |
k8s.daemonset.name | Context: Cloud role (ai.cloud.role ) |
k8s.pod.name | Context: Cloud role instance (ai.cloud.roleInstance ) |
service.instance.id | Context: Cloud role instance (ai.cloud.roleInstance ) |
device.id | Context: Device id (ai.device.id ) |
device.model.name | Context: Device model (ai.device.model ) |
service.version | Context: Application version (ai.application.ver ) |
telemetry.sdk.name + telemetry.sdk.version | Context: Internal SDK version (ai.internal.sdkVersion ) |
ai.* | Context: AppInsights Tag (ai.* ) |
If service.name
is the default (i.e. starts with “unknown_service:”), the Kubernetes based
values take precedence.
§Spans
The OpenTelemetry SpanKind determines the Application Insights telemetry type:
OpenTelemetry SpanKind | Application Insights telemetry type |
---|---|
CLIENT , PRODUCER , INTERNAL | Dependency |
SERVER , CONSUMER | Request |
The Span’s status determines the Success field of a Dependency or Request. Success is false
if
the status Error
; otherwise true
.
The following of the Span’s attributes map to special fields in Application Insights (the mapping tries to follow the OpenTelemetry semantic conventions for trace).
Note: for INTERNAL
Spans the Dependency Type is always "InProc"
.
OpenTelemetry attribute key | Application Insights field |
---|---|
user.id | Context: Authenticated user id (ai.user.authUserId ) |
SpanKind::Server + http.request.method + http.route | Context: Operation Name (ai.operation.name ) |
ai.* | Context: AppInsights Tag (ai.* ) |
url.full | Dependency Data |
db.query.text | Dependency Data |
http.request.header.host | Dependency Target |
server.address + server.port | Dependency Target |
network.peer.address + network.peer.port | Dependency Target |
db.namespace | Dependency Target |
http.response.status_code | Dependency Result code |
db.system.name | Dependency Type |
messaging.system | Dependency Type |
rpc.system | Dependency Type |
"HTTP" if any http. attribute exists | Dependency Type |
"DB" if any db. attribute exists | Dependency Type |
url.full | Request Url |
url.scheme + http.request.header.host + url.path + url.query | Request Url |
url.scheme + server.address + server.port + url.path + url.query | Request Url |
client.address | Request Source |
network.peer.address | Request Source |
http.response.status_code | Request Response code |
All other attributes are directly converted to custom properties.
For Requests the attributes http.request.method
and http.route
override the Name.
§Deprecated attributes
The following deprecated attributes also work:
Attribute | Deprecated attribute |
---|---|
user.id | enduser.id |
db.namespace | db.name |
db.query.text | db.statement |
db.system.name | db.system |
http.request.method | http.method |
http.request.header.host | http.host |
http.response.status_code | http.status_code |
url.full | http.url |
url.scheme | http.scheme |
url.path + url.query | http.target |
client.address | http.client_ip |
network.peer.address | server.socket.address (for client spans) |
network.peer.address | net.sock.peer.addr (for client spans) |
network.peer.address | net.peer.ip (for client spans) |
network.peer.port | server.socket.port (for client spans) |
network.peer.port | net.sock.peer.port (for client spans) |
network.peer.address | client.socket.address (for server spans) |
network.peer.address | net.sock.peer.addr (for server spans) |
network.peer.address | net.peer.ip (for server spans) |
server.address | net.peer.name (for client spans) |
server.port | net.peer.port (for client spans) |
server.address | net.host.name (for server spans) |
server.port | net.host.port (for server spans) |
§Events
Events are converted into Exception telemetry if the event name equals "exception"
(see
OpenTelemetry semantic conventions for exceptions) with the following mapping:
OpenTelemetry attribute key | Application Insights field |
---|---|
exception.type | Exception type |
exception.message | Exception message |
exception.stacktrace | Exception call stack |
Events are converted into Event telemetry if the event name equals "ai.custom"
with the
following mapping:
OpenTelemetry attribute key | Application Insights field |
---|---|
ai.customEvent.name | Event name |
All other events are converted into Trace telemetry with the following mapping:
OpenTelemetry attribute key | Application Insights field |
---|---|
level (tracing::Level ) | Severity level |
All other attributes are directly converted to custom properties.
§Logs
Logs are reported similar to events:
- If they contain an
exception.type
orexception.message
attribute, they’re converted to Exception telemetry with the same attribute mapping as events. - Otherwise they’re converted to Trace telemetry.
§Metrics
Metrics get reported to Application Insights as Metric Data. The Aggregation
determines how
the data is represented.
Aggregator | Data representation |
---|---|
Histogram | aggregation with sum, count, min, and max (buckets are not exported) |
ExponentialHistogram | aggregation with sum, count, min, and max (buckets are not exported) |
Gauge | one measurement |
Sum | aggregation with only a value |
Modules§
- attrs
- Attributes for Application Insights context fields
Structs§
- Exporter
- Application Insights span exporter
- Live
Metrics Span Processor - Application Insights live metrics span processor
Enums§
- Error
- Errors that occurred during span export.
Traits§
- Http
Client - A minimal interface necessary for sending requests over HTTP. Used primarily for exporting telemetry over HTTP. Also used for fetching sampling strategies for JaegerRemoteSampler