Fluxtail
Feature / OTLP

OTLP Logs: Send OpenTelemetry Log Data to Fluxtail

Use OTLP logs when services already emit OpenTelemetry log data and need a structured transport path into Fluxtail. An OTLP log path should preserve resource attributes, service context, severity, timestamps, log attributes, and trace identifiers when those fields are present.

OTLP logs OpenTelemetry Collectors OTLP receiver
Transport path

OTLP logs move OpenTelemetry log records from SDKs, agents, or Collectors into a receiver.

Resource context

Resource attributes such as service.name, environment, host, pod, container, and region should remain usable after ingestion.

Readable result

A log record should still show a clear message, severity, timestamp, service, and trace context after transport.

Mixed sources

OTLP logs can sit beside HTTP, Syslog, GELF, Kubernetes, Fluent Bit, and other collector-fed streams.

Transport

Send OpenTelemetry Logs Over OTLP

OTLP logs are the OpenTelemetry-native way to move log records from SDKs, agents, or Collectors into a receiver. The useful test is not only whether the event arrives, but whether service identity, severity, timestamps, trace context, and attributes remain readable after ingestion.

01

Use OTLP when OpenTelemetry is already in the path

OTLP log ingestion fits services that already emit OpenTelemetry log data or run Collectors, language SDKs, Kubernetes agents, or telemetry pipelines that can export logs through OTLP.

02

Keep logs close to traces and metrics

OTLP keeps logs near the same context model used for traces and metrics, including resource attributes, severity fields, log attributes, and trace identifiers.

03

Use the OpenTelemetry logging page for field strategy

The OpenTelemetry logging page covers service context, trace context, and readable log records. This OTLP page stays focused on the receiver path and verification.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Fields

What Should Survive OTLP Log Ingestion

An OTLP receiver path is useful when resource attributes, log record fields, and event attributes remain available for reading and filtering.

01

Resource attributes

Preserve service.name, service.namespace, service.version, deployment.environment, host.name, k8s.namespace.name, k8s.pod.name, k8s.container.name, cloud.provider, and cloud.region when they are present.

Resource attributes to preserve
text
1service.name
2service.version
3deployment.environment
4host.name
5k8s.namespace.name
6k8s.pod.name
7k8s.container.name
02

Log record fields

Keep timestamp, severity_text, severity_number, body, trace_id, span_id, and attributes. Fluxtail should receive enough structure to show the human-readable message while retaining the machine-readable context around it.

03

Attributes for filtering

Put event details into attributes when they should be searchable later: http.method, http.route, http.status_code, error.type, error.message, tenant.id, job.name, queue.name, or provider names.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Payload shape

Example OTLP-Style Log Payload

This example shows the kind of structure worth preserving. It is not an exact supported API contract.

01

Resource and log record shape

The resource describes the source. The log record describes the event. Attributes keep filterable details separate from the human-readable body.

OTLP-style payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "deployment.environment": "prod",
6 "k8s.namespace.name": "payments"
7 }
8 },
9 "scopeLogs": [{
10 "logRecords": [{
11 "severityText": "ERROR",
12 "body": { "stringValue": "payment authorization failed" },
13 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
14 "spanId": "8d1c2f4a91b76e20",
15 "attributes": {
16 "http.route": "/v1/charges",
17 "http.status_code": 502,
18 "error.type": "ProviderTimeout"
19 }
20 }]
21 }]
22}
OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Result

How the Log Appears in Fluxtail

A readable ingested row should preserve the message plus searchable context.

01

Keep the row readable

The row should expose timestamp, level, message, service, environment, host, trace_id, span_id, and useful attributes without forcing the full payload into the visible line.

Readable Fluxtail row
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The original event should remain available for deeper inspection while the row stays scannable.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Verification

Verify the OTLP Receiver Path

Do not stop at “the collector sent something.” Confirm that the fields needed for reading and filtering survived the receiver path.

01

Send one known log record

Start with one known log record from one service. Confirm that it appears in Fluxtail with the expected timestamp, readable severity, readable body, service identity, and resource attributes.

02

Confirm trace and span identifiers

When the source emits traceId and spanId, verify that those identifiers remain available for filtering and correlation after ingestion.

03

Filter on preserved fields

Filter by service.name, deployment.environment, severity, k8s.namespace.name, trace_id, or error.type. If those filters fail, inspect Collector processors and exporters before changing application code.

04

Check a second source shape

Send another log with a different severity or Kubernetes context to confirm the receiver path handles more than one event shape.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Readability

Keep OpenTelemetry Logs Readable After Transport

OTLP can preserve rich structure, but readability depends on what the source emits and how the destination presents it.

01

Use stable field names

Keep service, environment, severity, route, status, trace, pod, and error fields stable across services so the same filters work during real production traffic.

02

Keep message bodies concise

Use the body for the readable event message. Put operational dimensions into attributes instead of packing everything into one long text field.

03

Use live tail for the result

After ingestion, live tail, filters, facets, histograms, alerts, MCP diagnostics, and AI chat can operate on the centralized log stream.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Related

Related Guides

OTLP logs often appear beside OpenTelemetry field design, log aggregation, Kubernetes logging, and collector setup.

01

OpenTelemetry logging

Use the OpenTelemetry logging page for field context, trace context, severity, and readable OTel log records.

02

Log aggregation

Use the log aggregation page when OTLP logs need to land beside HTTP, Syslog, GELF, Kubernetes, and collector-fed streams.

03

Kubernetes and Fluent Bit

Use the Kubernetes and Fluent Bit pages when pod, namespace, container, and collector context are the main setup concerns.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

OTLP example

An OTLP-style log payload should keep resource and event context

The example is illustrative, not an exact endpoint contract. Use it to check which fields should survive an OTLP receiver path.

OTLP-style log payload
json
1{
2 "resource": {
3 "attributes": {
4 "service.name": "billing-api",
5 "service.version": "2026.04.25",
6 "deployment.environment": "prod",
7 "k8s.namespace.name": "payments",
8 "k8s.pod.name": "billing-api-7d9f8c6c9b-42r9x"
9 }
10 },
11 "scopeLogs": [{
12 "scope": { "name": "billing-api.logger" },
13 "logRecords": [{
14 "timeUnixNano": "1777137025123000000",
15 "severityText": "ERROR",
16 "severityNumber": 17,
17 "body": { "stringValue": "payment authorization failed" },
18 "traceId": "7b5f4f2a2c8148e79c8c1f3a6e9d1123",
19 "spanId": "8d1c2f4a91b76e20",
20 "attributes": {
21 "http.route": "/v1/charges",
22 "http.status_code": 502,
23 "error.type": "ProviderTimeout"
24 }
25 }]
26 }]
27}

Use the receiver documentation for exact endpoint and protocol mode. This block shows the field shape worth preserving.

How the log appears after ingestion
output
2026-04-25T14:30:25Z ERROR billing-api prod payment authorization failed trace=7b5f4f2a2c8148e79c8c1f3a6e9d1123 route=/v1/charges status=502 error=ProviderTimeout

The result should keep the message readable and keep resource, trace, and event attributes filterable.

Related

Related pages

Next step

Send one real source and read the logs

The fastest check is to point one real source at Fluxtail and see whether the resulting stream is easier to read.

Point one real source at Fluxtail.

Create a receiver, send one source, and inspect the first stream.