Collecting file logs with the OpenTelemetry Collector lets existing applications keep writing plain text while the Collector emits those lines as OpenTelemetry log records. It is useful when an application is not sending OTLP logs yet, but its file output still needs to flow through the same telemetry pipeline as traces and metrics.

The file_log receiver belongs to the contrib Collector distribution and tails matching files on disk. The receiver becomes active only when it appears in a logs pipeline, and the debug exporter gives a local proof path before a backend exporter is added.

A temporary log file under /tmp/checkout-api keeps the smoke test separate from production logs. After the receiver emits the sample lines, replace the path with the application log glob and run the Collector under a user or service account that can read the selected files.

Steps to collect file logs with the OpenTelemetry Collector:

  1. Confirm the local Collector distribution includes the file_log receiver and debug exporter.
    $ otelcol-contrib components
    buildinfo:
        command: otelcol-contrib
        description: OpenTelemetry Collector Contrib
        version: 0.154.0
    receivers:
    ##### snipped #####
        - name: file_log
          module: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.154.0
          stability:
            logs: Beta
    ##### snipped #####
    exporters:
    ##### snipped #####
        - name: debug
          module: go.opentelemetry.io/collector/exporter/debugexporter v0.154.0
          stability:
            logs: Development
            metrics: Development
            traces: Development

    The core Collector build may not include file_log. Use the contrib or Kubernetes Collector distribution for this receiver.

  2. Create a temporary application log directory.
    $ mkdir -p /tmp/checkout-api
  3. Write the first test log line.
    $ printf '2026-06-18T10:15:01Z INFO order accepted id=1001\n' > /tmp/checkout-api/app.log
  4. Create the Collector configuration file.
    $ vi otelcol-filelog.yaml
  5. Add a file_log receiver, batch processor, and debug exporter.
    receivers:
      file_log:
        include:
          - /tmp/checkout-api/app.log
        start_at: beginning
        include_file_path: true
        resource:
          service.name: checkout-api
    
    processors:
      batch:
        timeout: 1s
    
    exporters:
      debug:
        verbosity: detailed
    
    service:
      pipelines:
        logs:
          receivers: [file_log]
          processors: [batch]
          exporters: [debug]

    start_at: beginning makes the smoke test read the line already present in the file. For a production handoff, use the default end behavior when old log files should not be backfilled. Plain text lines remain in the log record body until parser operators extract timestamps, severity, or structured attributes.

  6. Validate the Collector configuration.
    $ otelcol-contrib validate --config=otelcol-filelog.yaml

    No output and exit status 0 means the configuration parsed successfully.

  7. Start the Collector with the test configuration.
    $ otelcol-contrib --config=otelcol-filelog.yaml
    2026-06-18T06:17:46.353Z    info    service@v0.154.0/service.go:264    Everything is ready. Begin running and processing data.
    2026-06-18T06:17:46.558Z    info    fileconsumer/file.go:423    Started watching file    {"otelcol.component.id": "file_log", "path": "/tmp/checkout-api/app.log"}
    2026-06-18T06:17:47.595Z    info    Logs    {"otelcol.component.id": "debug", "otelcol.signal": "logs", "log records": 1}
    Resource attributes:
         -> service.name: Str(checkout-api)
    LogRecord #0
    Body: Str(2026-06-18T10:15:01Z INFO order accepted id=1001)
    Attributes:
         -> log.file.name: Str(app.log)
         -> log.file.path: Str(/tmp/checkout-api/app.log)

    Leave this terminal running so the receiver can continue polling the file.

  8. Append a new log line from another terminal.
    $ printf '2026-06-18T10:15:05Z ERROR payment timeout id=1002\n' >> /tmp/checkout-api/app.log
  9. Confirm the appended line appears in the Collector output.
    2026-06-18T06:17:57.606Z    info    Logs    {"otelcol.component.id": "debug", "otelcol.signal": "logs", "log records": 1}
    Resource attributes:
         -> service.name: Str(checkout-api)
    LogRecord #0
    Body: Str(2026-06-18T10:15:05Z ERROR payment timeout id=1002)
    Attributes:
         -> log.file.path: Str(/tmp/checkout-api/app.log)
         -> log.file.name: Str(app.log)

    The Body field proves the appended file line became an OpenTelemetry log record. The log.file.path attribute proves the record came from the expected file.

  10. Stop the foreground Collector process with Ctrl+C after the test record appears.
  11. Remove the temporary test files after moving the receiver block into the active Collector configuration.
    $ rm -r /tmp/checkout-api otelcol-filelog.yaml