LinkMesh

Search docs, blog and changelog

ENDE

Snippets · Sources

Use the timestamp in the log line, in the right time zone

Without a timestamp parser every record is stamped with the time the collector read it, which is wrong for anything read late: after a restart, a backlog, a rotated file. This config reads the time from the line ("22.10.2026 10:15:02") with a strptime layout and the Europe/Zurich location, so daylight saving time is handled: in our test the summer line became 08:15:02 UTC and the winter line 09:15:02 UTC.

Signals
Logs
Category
CollectionParsing
Source
Log files
Components
filelogbatchmemory_limiterotlphttp
Destination
OTLP/HTTP endpoint

OpenTelemetry Collector

OpenTelemetry Collector YAML
extensions:
  file_storage:
    directory: /var/lib/otelcol/storage
    create_directory: true

receivers:
  filelog:
    include: [/var/log/myapp/*.log]
    start_at: end
    storage: file_storage
    operators:
      # "22.10.2026 10:15:02 INFO message": the time has no zone, so the
      # location says which one it was written in.
      - type: regex_parser
        regex: '^(?P<ts>\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}:\d{2}) (?P<level>[A-Z]+) (?P<msg>.*)$'
        timestamp:
          parse_from: attributes.ts
          layout_type: strptime
          layout: '%d.%m.%Y %H:%M:%S'
          location: Europe/Zurich
        on_error: send

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 25
  batch:
    timeout: 5s

exporters:
  otlphttp:
    endpoint: https://your-backend:4318

service:
  extensions: [file_storage]
  pipelines:
    logs:
      receivers: [filelog]
      processors: [memory_limiter, batch]
      exporters: [otlphttp]

LinkMesh

LinkMesh has no built-in template for this job. Add it as a custom source in raw mode, with filelog as the component type and this body - the same lines as under filelog in the collector config:

Custom source body (filelog)
include: [/var/log/myapp/*.log]
start_at: end
storage: file_storage
operators:
  - type: regex_parser
    regex: '^(?P<ts>\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}:\d{2}) (?P<level>[A-Z]+) (?P<msg>.*)$'
    timestamp:
      parse_from: attributes.ts
      layout_type: strptime
      layout: '%d.%m.%Y %H:%M:%S'
      location: Europe/Zurich
    on_error: send

How custom components are validated and rolled out: create a custom source.

Download config.yamlValidated with otelcol-contrib v0.161.0 on 2026-10-26

Complete config files, each checked with the collector's own validate command (otelcol-contrib v0.161.0). Replace https://your-backend:4318 with your own OTLP endpoint before you run it.

Before and after

Example telemetry in, and what this exact config sent out when we ran it in otelcol-contrib v0.161.0. CI re-runs it on every change and fails if the output differs. Changed values are highlighted.

2 log records in, 2 log records out

  1. Before

    body
    22.10.2026 10:15:02 INFO user signed in

    After

    body
    22.10.2026 10:15:02 INFO user signed in
    timestamp
    2026-10-22T08:15:02.000Z
    attributes.ts
    22.10.2026 10:15:02
    attributes.level
    INFO
    attributes.msg
    user signed in
    attributes.log.file.name
    input.log
  2. Before

    body
    22.01.2026 10:15:02 INFO same wall-clock time in winter

    After

    body
    22.01.2026 10:15:02 INFO same wall-clock time in winter
    timestamp
    2026-01-22T09:15:02.000Z
    attributes.log.file.name
    input.log
    attributes.ts
    22.01.2026 10:15:02
    attributes.level
    INFO
    attributes.msg
    same wall-clock time in winter

The gotcha

A time without a zone is read as UTC unless you set location. In our test, without it, both lines were stamped 10:15:02 UTC - two hours off in summer and one in winter, with no warning. Set location to where the log is written, not where the collector runs.

Manage this across a fleet

LinkMesh manages collector configuration across a fleet from one self-hosted control plane, so a change like this is made once rather than host by host. The first 25 Collectors are free after a no-card registration in the OpenSight Customer Portal (5 without one).

Doing this in LinkMesh: Sources