> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-telemetry/opentelemetry-rust/llms.txt
> Use this file to discover all available pages before exploring further.

# opentelemetry-appender-log

> Bridge log crate events to OpenTelemetry logs

# opentelemetry-appender-log

**Version:** 0.31.0

The `opentelemetry-appender-log` crate provides a log appender that bridges the [`log`](https://crates.io/crates/log) crate to OpenTelemetry's Logs Bridge API, enabling `log` events to be exported via OpenTelemetry.

## Installation

```toml theme={null}
[dependencies]
opentelemetry-appender-log = "0.31"
log = { version = "0.4", features = ["kv", "std"] }
```

### Feature Flags

* `with-serde`: Support complex values as attributes without stringifying (enables `serde` serialization)
* `experimental_metadata_attributes`: Include code location metadata (file path, line number, module) as attributes

## Quick Start

### Basic Setup

```rust theme={null}
use opentelemetry_sdk::logs::{BatchLogProcessor, SdkLoggerProvider};
use opentelemetry_appender_log::OpenTelemetryLogBridge;

// 1. Create OpenTelemetry logger provider with an exporter
let exporter = opentelemetry_stdout::LogExporter::default();
let logger_provider = SdkLoggerProvider::builder()
    .with_log_processor(BatchLogProcessor::builder(exporter).build())
    .build();

// 2. Create the log bridge
let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);

// 3. Set as the global logger
log::set_boxed_logger(Box::new(otel_log_appender)).unwrap();
log::set_max_level(log::LevelFilter::Info);

// 4. Use the log crate as normal
log::info!("Application started");
log::error!("Something went wrong");
```

### With Key-Value Attributes

```rust theme={null}
use log::info;

info!(
    target: "my_system",
    user_id = 42,
    user_name = "Alice";
    "User logged in"
);
```

## Core Types

<ParamField path="OpenTelemetryLogBridge<P, L>" type="struct">
  Log appender that implements `log::Log` trait and forwards log records to OpenTelemetry
</ParamField>

```rust theme={null}
use opentelemetry_appender_log::OpenTelemetryLogBridge;
use opentelemetry_sdk::logs::SdkLoggerProvider;

let provider: SdkLoggerProvider = /* ... */;
let bridge = OpenTelemetryLogBridge::new(&provider);
```

## Field Mapping

This section describes how `log` records map to OpenTelemetry log records:

### Body

The stringified message from `log::Record::args()` becomes the log body.

```rust theme={null}
log::info!("Request processed");
// -> LogRecord.body = "Request processed"
```

### Severity

`log::Level` maps to OpenTelemetry severity:

| `log::Level` | Severity Text | Severity Number |
| ------------ | ------------- | --------------- |
| `Error`      | Error         | 17              |
| `Warn`       | Warn          | 13              |
| `Info`       | Info          | 9               |
| `Debug`      | Debug         | 5               |
| `Trace`      | Trace         | 1               |

### Target

The `log::Record::target()` becomes the OpenTelemetry `InstrumentationScope` name.

```rust theme={null}
log::info!(target: "my_module", "Event occurred");
// -> InstrumentationScope.name = "my_module"
```

### Attributes

Key-value pairs from `log::Record::key_values()` are converted to attributes.

## Type Conversion

### Without `with-serde` Feature

| Type           | OpenTelemetry Type          | Notes                                            |
| -------------- | --------------------------- | ------------------------------------------------ |
| `i8`-`i64`     | `AnyValue::Int`             |                                                  |
| `u8`-`u64`     | `AnyValue::Int`             | If value fits in `i64`, otherwise stringified    |
| `i128`, `u128` | `AnyValue::Int` or `String` | Converted to `i64` if possible, else stringified |
| `f32`, `f64`   | `AnyValue::Double`          |                                                  |
| `bool`         | `AnyValue::Boolean`         |                                                  |
| `&str`         | `AnyValue::String`          |                                                  |
| Other          | `AnyValue::String`          | Stringified via `Debug` trait                    |

### With `with-serde` Feature

Enables rich type support using `serde`:

| Type           | OpenTelemetry Type          | Notes                                  |
| -------------- | --------------------------- | -------------------------------------- |
| Primitives     | As above                    | Same as without serde                  |
| `Bytes`        | `AnyValue::Bytes`           | Binary data                            |
| `Option::None` | -                           | Discarded                              |
| `Option::Some` | Any                         | Uses inner value                       |
| Sequences      | `AnyValue::ListAny`         | Arrays, slices, tuples                 |
| Maps/Structs   | `AnyValue::Map`             | Structured data                        |
| Enum variants  | `AnyValue::String` or `Map` | Unit variants as string, others as map |

## Metadata Attributes

With the `experimental_metadata_attributes` feature:

```toml theme={null}
[dependencies]
opentelemetry-appender-log = { version = "0.31", features = ["experimental_metadata_attributes"] }
opentelemetry-semantic-conventions = "0.31"
```

```rust theme={null}
log::warn!("Configuration issue detected");
// Automatically includes:
// - code.filepath: "src/main.rs"
// - code.line_number: 42
// - code.function_name: "my_module::function"
```

## Examples

### Basic Logging

```rust theme={null}
use log::{info, warn, error};

info!("Server started on port 8080");
warn!("High memory usage detected");
error!("Database connection failed");
```

### Structured Logging

```rust theme={null}
use log::info;

info!(
    user_id = 12345,
    action = "purchase",
    amount = 99.99;
    "User completed purchase"
);
```

### With Custom Target

```rust theme={null}
use log::info;

info!(target: "http_server", 
    method = "GET",
    path = "/api/users",
    status = 200;
    "Request processed"
);
```

### Complex Types (with serde)

```rust theme={null}
use log::info;
use serde::Serialize;

#[derive(Serialize)]
struct UserContext {
    id: u64,
    role: String,
}

let user = UserContext { 
    id: 42, 
    role: "admin".to_string() 
};

info!(
    user = log::kv::Value::from_serde(&user);
    "User authenticated"
);
```

## Performance Considerations

* The bridge evaluates `enabled()` before processing log records
* Use appropriate log levels to avoid unnecessary overhead
* Consider using `BatchLogProcessor` for better performance
* The `with-serde` feature adds overhead for complex types

## Integration with OTLP

```rust theme={null}
use opentelemetry_otlp::LogExporter;
use opentelemetry_sdk::logs::{BatchLogProcessor, SdkLoggerProvider};
use opentelemetry_appender_log::OpenTelemetryLogBridge;

let exporter = LogExporter::builder()
    .with_http()
    .build()?;

let logger_provider = SdkLoggerProvider::builder()
    .with_log_processor(BatchLogProcessor::builder(exporter).build())
    .build();

let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
log::set_boxed_logger(Box::new(otel_log_appender)).unwrap();
```

## Differences from Direct Logging

<Warning>
  This bridge is designed for applications already using the `log` crate. If you're starting fresh, consider using the `tracing` crate with [`opentelemetry-appender-tracing`](/api/opentelemetry-appender-tracing), which provides better structured logging support.
</Warning>

## Related Crates

* **[opentelemetry](/api/opentelemetry)** - Core API with Logs Bridge API
* **[opentelemetry-sdk](/api/opentelemetry-sdk)** - SDK with log processors
* **[opentelemetry-appender-tracing](/api/opentelemetry-appender-tracing)** - Bridge for `tracing` crate
* **[log](https://crates.io/crates/log)** - Logging facade for Rust

## Documentation

<Card title="Full API Documentation" icon="book" href="https://docs.rs/opentelemetry-appender-log/0.31.0">
  View complete API reference on docs.rs
</Card>

<Card title="log Crate" icon="arrow-up-right-from-square" href="https://docs.rs/log/">
  Documentation for the log crate
</Card>

## Minimum Rust Version

**MSRV:** 1.75.0
