docs/sources/send-data/otel/_index.md
{{< docs/shared source="loki" lookup="otel.md" version="<LOKI_VERSION>">}}
Here are some example configs to change the default mapping of OTLP to Loki format:
limits_config:
otlp_config:
resource_attributes:
attributes_config:
- action: index_label
attributes:
- service.group
With the example config, here is how various kinds of Attributes would be stored:
service.group Resource Attribute as index labels.limits_config:
otlp_config:
resource_attributes:
ignore_defaults: true
attributes_config:
- action: index_label
regex: service.group
With the example config, here is how various kinds of Attributes would be stored:
service.group Resource Attribute as index labels.limits_config:
otlp_config:
resource_attributes:
attributes_config:
- action: index_label
regex: service.group
scope_attributes:
- action: drop
attributes:
- method.name
log_attributes:
- action: structured_metadata
attributes:
- user.id
- action: drop
regex: .*
With the example config, here is how various kinds of Attributes would be stored:
service.group Resource Attribute as index labels.method.name and store all other Scope Attributes as Structured Metadata.user.id as Structured Metadata and drop all other Log Attributes.By default, Loki stores OpenTelemetry log attributes as structured metadata. Two per-line limits apply to them:
max_structured_metadata_size: the total size of structured metadata per log line, 64KB by default.max_structured_metadata_entries_count: the number of structured metadata entries per log line, 128 by default.A large log attribute — for example exception.stacktrace, which some OpenTelemetry SDK log integrations attach when a log records an exception — can push a log line over these limits. The distributor rejects such entries with an HTTP 400 (non-retryable) response and counts them in the loki_discarded_samples_total metric with reason structured_metadata_too_large or structured_metadata_too_many; other valid entries in the same push request may still be ingested. For the exact error messages, refer to Troubleshoot ingestion errors.
If your stack traces are being rejected, use one of the following mitigations.
Use the OpenTelemetry Collector transform processor to append the stack trace to the log body and delete the attribute:
processors:
transform/stacktrace:
log_statements:
- context: log
statements:
- set(body, Concat([body, attributes["exception.stacktrace"]], "\n")) where attributes["exception.stacktrace"] != nil
- delete_key(attributes, "exception.stacktrace") where attributes["exception.stacktrace"] != nil
service:
pipelines:
logs:
processors: [transform/stacktrace] # append to your existing processors list
The set statement must come before delete_key. The stack trace then counts against the log line size limit instead: max_line_size, 256KB by default, with max_line_size_truncate available to truncate rather than reject oversized lines. If you collect logs with Grafana Alloy, the otelcol.processor.transform component applies the same statements.
log_attributes rule using action: drop under limits_config.otlp_config (Example 3 above shows the pattern). Rules are applied first-match-wins, so place the specific attribute before any catch-all regex.max_structured_metadata_size or max_structured_metadata_entries_count for a tenant through runtime overrides.