| 
 | 1 | +use opentelemetry::logs::LogRecord;  | 
 | 2 | +use opentelemetry_semantic_conventions as semcov;  | 
 | 3 | +use std::error::Error;  | 
 | 4 | + | 
 | 5 | +#[derive(Debug)]  | 
 | 6 | +struct ErrorAsExceptionLogProcessor;  | 
 | 7 | + | 
 | 8 | +impl opentelemetry_sdk::logs::LogProcessor for ErrorAsExceptionLogProcessor {  | 
 | 9 | +    fn emit(  | 
 | 10 | +        &self,  | 
 | 11 | +        data: &mut opentelemetry_sdk::logs::SdkLogRecord,  | 
 | 12 | +        _instrumentation: &opentelemetry::InstrumentationScope,  | 
 | 13 | +    ) {  | 
 | 14 | +        if let Some(severity) = data.severity_number() {  | 
 | 15 | +            if severity >= opentelemetry::logs::Severity::Error {  | 
 | 16 | +                // TODO: Check if exception attributes are already present  | 
 | 17 | +                data.add_attribute(semcov::attribute::EXCEPTION_TYPE, "error");  | 
 | 18 | +                if let Some(body) = data.body() {  | 
 | 19 | +                    data.add_attribute(  | 
 | 20 | +                        semcov::attribute::EXCEPTION_MESSAGE,  | 
 | 21 | +                        any_value_to_string(body),  | 
 | 22 | +                    );  | 
 | 23 | +                }  | 
 | 24 | +            }  | 
 | 25 | +        }  | 
 | 26 | +    }  | 
 | 27 | + | 
 | 28 | +    fn force_flush(&self) -> opentelemetry_sdk::error::OTelSdkResult {  | 
 | 29 | +        Ok(())  | 
 | 30 | +    }  | 
 | 31 | +}  | 
 | 32 | + | 
 | 33 | +fn any_value_to_string(v: &opentelemetry::logs::AnyValue) -> String {  | 
 | 34 | +    match v {  | 
 | 35 | +        opentelemetry::logs::AnyValue::String(v) => v.to_string(),  | 
 | 36 | +        _ => format!("{:?}", v).into(),  | 
 | 37 | +    }  | 
 | 38 | +}  | 
 | 39 | + | 
 | 40 | +fn main() -> Result<(), Box<dyn Error + Send + Sync>> {  | 
 | 41 | +    let client = reqwest::blocking::Client::new();  | 
 | 42 | + | 
 | 43 | +    let exporter = opentelemetry_application_insights::Exporter::new_from_env(client)?;  | 
 | 44 | + | 
 | 45 | +    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()  | 
 | 46 | +        .with_log_processor(ErrorAsExceptionLogProcessor)  | 
 | 47 | +        .with_batch_exporter(exporter)  | 
 | 48 | +        .build();  | 
 | 49 | +    let otel_log_appender =  | 
 | 50 | +        opentelemetry_appender_log::OpenTelemetryLogBridge::new(&logger_provider);  | 
 | 51 | +    log::set_boxed_logger(Box::new(otel_log_appender))?;  | 
 | 52 | +    log::set_max_level(log::Level::Info.to_level_filter());  | 
 | 53 | + | 
 | 54 | +    // Log via `log` crate.  | 
 | 55 | +    let fruit = "apple";  | 
 | 56 | +    let price = 2.99;  | 
 | 57 | +    let colors = ("red", "green");  | 
 | 58 | +    log::info!(fruit, price, colors:sval; "info! {fruit} is {price}");  | 
 | 59 | +    log::warn!("warn!");  | 
 | 60 | +    log::error!("error!");  | 
 | 61 | + | 
 | 62 | +    // Force export before exit.  | 
 | 63 | +    logger_provider.shutdown()?;  | 
 | 64 | + | 
 | 65 | +    Ok(())  | 
 | 66 | +}  | 
0 commit comments