pub(super) fn logs_layer<S>(
        &self,
    ) -> Option<(opentelemetry_sdk::logs::LoggerProvider, impl Layer<S>)>
    where
        S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
    {
        let logging_endpoint = self.logging_endpoint.clone()?;
        let resource = self.service.clone().into_otlp_resource();

        let exporter = opentelemetry_otlp::new_exporter()
            .http()
            .with_endpoint(logging_endpoint)
            .build_log_exporter()
            .expect("Failed to create OTLP exporter"); // URL is validated.

        let provider = opentelemetry_sdk::logs::LoggerProvider::builder()
            .with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
            .with_resource(resource)
            .build();

        let layer =
            opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge::new(&provider);

        Some((provider, layer))
    }
Prepares an exporter for OTLP logs and layer for the `tracing` library.
Will return `None` if no logging URL was provided.

*Important*: we use `tracing` library to generate logs, and convert the logs
to OTLP format when exporting. However, `tracing` doesn't provide information
about timestamp of the log. While this value is optional in OTLP, some
collectors/processors may ignore logs without timestamp. Thus, you may need to
have a proxy collector, like `opentelemetry-collector-contrib` or `vector`, and
use the functionality there to set the timestamp. Here's example configuration
for `opentelemetry-collector-contrib`:

```text
processors:
transform/set_time_unix_nano:
log_statements:
- context: log
statements:
- set(time_unix_nano, observed_time_unix_nano)
```
core/lib/vlog/src/opentelemetry/mod.rs