/docs/linux-host-observability
hostmetrics + filelog
free plan / 1 gb-mo
telemtra.io
// collector guide

Linux host observability
with the OpenTelemetry Collector.

Collect host metrics, syslog, auth logs, and Nginx logs while preserving service, host, and environment context. Stream everything to Telemtra over OTLP.

Host metrics

Use the Collector Contrib hostmetrics receiver for CPU, memory, disk, filesystem, network, paging, and process metrics. For what each scraper emits — and which metrics like system.filesystem.utilization are off by default — see the host metrics reference.

receivers:
  hostmetrics:
    root_path: /hostfs
    collection_interval: 30s
    scrapers:
      cpu:
      memory:
      disk:
      filesystem:
      network:
      paging:
      processes:

Syslog and auth logs

File log paths vary by distribution. Start small, verify parsing, then expand. The filelog receiver tails existing files; it does not open a syslog listener. The example below parses ISO timestamps, host names, process names, and messages. Severity is extracted only when the source line includes [severity=...]; the next section shows how to preserve that field with rsyslog. Once these logs are flowing, the Linux log patterns reference covers which messages — SSH brute force, OOM kills, disk errors — are worth alerting on.

Merge this receiver into your Collector configuration (for example, host-logs.yaml). Keep any existing file_storage extension, receiver storage setting, and persistent offset volume. Docker examples assume a read-only host mount at /hostfs; for a native Collector, use /var/log/... instead.

receivers:
  filelog/system:
    include:
      - /hostfs/var/log/syslog
      - /hostfs/var/log/auth.log
    start_at: end
    include_file_path: true
    operators:
      - type: regex_parser
        parse_from: body
        on_error: send
        regex: '^(?P<timestamp>\d+-\d+-\d+T\S+)\s+(?P<host_name>\S+)\s+(?P<process_name>[^\[:]+)(?:\[(?P<process_pid>\d+)\])?:\s?(?:\[severity=(?P<syslog_severity>[a-z]+)\]\s?)?(?P<message>.*)$'
        timestamp:
          parse_from: attributes.timestamp
          layout_type: gotime
          layout: '2006-01-02T15:04:05.999999999Z07:00'
      - id: parse_syslog_severity
        type: severity_parser
        if: 'attributes.syslog_severity != nil and attributes.syslog_severity != ""'
        parse_from: attributes.syslog_severity
        overwrite_text: true
        preset: none
        mapping:
          debug: debug
          info: [info, notice]
          warn: [warning, warn]
          error: [err, error]
          fatal: [crit, alert, emerg]
      - type: move
        from: attributes.message
        to: body
        if: attributes.message != nil

Preserve syslog severity in the source files

Many default syslog file formats omit severity. The Collector cannot recover a missing level from a message reliably, and a failed login is not necessarily emitted at ERROR level. Preserve the severity supplied by the source instead of guessing from message text or assigning INFO to every line.

This procedure applies to Debian/Ubuntu hosts using rsyslog with /var/log/syslog and /var/log/auth.log. Inspect your distribution's rules before editing. It changes the format of new lines in those two files; update any other tools that parse them. It does not add a network listener or rewrite existing logs.

First define a format in /etc/rsyslog.d/49-telemtra-severity.conf. Creating the template alone does not activate it:

sudo tee /etc/rsyslog.d/49-telemtra-severity.conf >/dev/null <<'EOF'
template(
  name="TelemtraSeverityFormat"
  type="string"
  string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag% [severity=%syslogseverity-text%]%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
)
EOF
sudo rsyslogd -N1

The new lines will look like this:

2026-10-09T09:43:02.546985+03:00 linux-host example[123]: [severity=err] Example message

The parser accepts both this format and older ISO-formatted lines without the marker. It removes the marker from the displayed message and retains the original level in syslog_severity. Historical lines without a level remain unspecified.

Syslog levelOTel severity textOTel severity number
debugDEBUG5
info, noticeINFO9
warning, warnWARN13
err, errorERROR17
crit, alert, emergFATAL21

These explicit groups follow the Collector's severity mapping configuration. The file format uses rsyslog templates.

Validate, activate, and test

Back up your Collector configuration before editing. Validate all merged configuration files, then restart the Collector before activating the new rsyslog format. For an existing Compose service named collector with these two configuration mounts:

docker compose run --rm --no-deps --pull never collector validate \
  --config=/etc/otelcol/host-metrics.yaml \
  --config=/etc/otelcol/host-logs.yaml && \
docker compose restart collector

Use the actual paths and all configuration files from your startup command. The image must already be installed when using --pull never. If you change filenames, mounts, or the Compose startup command, apply those changes with docker compose up -d --pull never instead of only restarting. Retain the offset volume so file reading resumes from the saved positions.

Once Collector validation and startup succeed, back up and edit the existing rsyslog rules:

sudo cp -a /etc/rsyslog.d/50-default.conf \
  /etc/rsyslog.d/50-default.conf.bak-$(date +%Y%m%d%H%M%S)
sudoedit /etc/rsyslog.d/50-default.conf

Replace the two existing destination lines with the following. Do not append duplicate rules; leave the other destinations alone:

auth,authpriv.*          /var/log/auth.log;TelemtraSeverityFormat
*.*;auth,authpriv.none    -/var/log/syslog;TelemtraSeverityFormat

Validate before restarting rsyslog. Continue only if both commands succeed:

sudo rsyslogd -N1 && sudo systemctl restart rsyslog
sudo systemctl is-active rsyslog

If validation or restart fails, restore 50-default.conf from the timestamped backup, validate again, and restart rsyslog. The Collector parser also accepts the previous format.

Generate four harmless test messages through the host's existing logging system:

logger -p user.info -t telemtra-severity-test "Severity check: INFO"
logger -p user.warning -t telemtra-severity-test "Severity check: WARN"
logger -p user.err -t telemtra-severity-test "Severity check: ERROR"
logger -p authpriv.warning -t telemtra-severity-test "Auth severity check: WARN"

sudo grep -E 'telemtra-severity-test: ' /var/log/syslog /var/log/auth.log | tail -4
docker compose logs --since=2m --tail=50 collector

Allow a moment for rsyslog to write the files. Confirm the lines contain [severity=info], [severity=warning], or [severity=err]. Then search Telemtra for Severity check and Auth severity check under your host-log service and current time range. Expect INFO, WARN, ERROR, and WARN respectively. Seeing markers in the files verifies rsyslog; seeing the mapped levels in Telemtra verifies the complete pipeline. Only new events gain severity.

Nginx access and error logs

Nginx writes a request log (access.log) and a diagnostic log (error.log) in different formats. Read both with one filelog receiver, route by filename, and parse each so status codes, methods, and error levels become structured fields in Telemtra. The Nginx monitoring reference covers which statuses and error messages to alert on once they flow.

receivers:
  filelog/nginx:
    include:
      - /hostfs/var/log/nginx/access.log
      - /hostfs/var/log/nginx/error.log
    start_at: end
    include_file_path: true
    operators:
      - type: router
        routes:
          - output: parse_access
            expr: 'attributes["log.file.path"] matches ".*/access\.log$"'
          - output: parse_error
            expr: 'attributes["log.file.path"] matches ".*/error\.log$"'
      - id: parse_access
        type: regex_parser
        parse_from: body
        on_error: send
        regex: '^(?P<client_ip>\S+) - (?P<remote_user>\S+) \[(?P<timestamp>[^\]]+)\] "(?P<method>\S+) (?P<target>\S+) (?P<protocol>[^"]+)" (?P<status>\d+) (?P<body_bytes_sent>\d+) "(?P<referer>[^"]*)" "(?P<user_agent>[^"]*)"$'
        timestamp:
          parse_from: attributes.timestamp
          layout_type: gotime
          layout: '02/Jan/2006:15:04:05 -0700'
      - id: parse_error
        type: regex_parser
        parse_from: body
        on_error: send
        regex: '^(?P<timestamp>\d+/\d+/\d+ \d+:\d+:\d+) \[(?P<level>\w+)\] (?P<message>.*)$'
      - type: add
        field: attributes["log.source"]
        value: nginx

Send to Telemtra

Merge the following shared settings with the hostmetrics and filelog/system receivers above; define each top-level YAML key only once per file. Keep existing processor and exporter settings when updating an installed Collector. To include the optional Nginx receiver, add filelog/nginx to the logs pipeline receiver list. Telemtra authenticates every request with the x-api-key header. Create the key in the Telemtra app under workspace settings → API keys, then inject it through an environment variable so it is never hardcoded in the config file:

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 256
    spike_limit_mib: 64
  batch:
  resource/host:
    attributes:
      - key: service.name
        value: linux-host
        action: upsert
      - key: host.name
        value: ${env:TELEMTRA_HOST_NAME}
        action: upsert
      - key: deployment.environment
        value: production
        action: upsert
  resource/system_logs:
    attributes:
      - key: service.name
        value: linux-system
        action: upsert
      - key: host.name
        value: ${env:TELEMTRA_HOST_NAME}
        action: upsert
      - key: deployment.environment
        value: production
        action: upsert

exporters:
  otlp/telemtra:
    endpoint: ${env:TELEMTRA_INGEST_ENDPOINT}
    headers:
      x-api-key: ${env:TELEMTRA_API_KEY}

service:
  pipelines:
    metrics:
      receivers: [hostmetrics]
      processors: [memory_limiter, resource/host, batch]
      exporters: [otlp/telemtra]
    logs:
      receivers: [filelog/system]
      processors: [memory_limiter, resource/system_logs, batch]
      exporters: [otlp/telemtra]

Supply these values from an env file or your secret manager. Use the public TLS endpoint in production:

TELEMTRA_API_KEY=tk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TELEMTRA_INGEST_ENDPOINT=ingest.telemtra.io:443
TELEMTRA_HOST_NAME=your-linux-host

When running the collector in Docker, pass these with --env-file (or Compose env_file) so the key stays out of the image and the YAML.

Permissions

If files are owned by syslog:adm or similar, run the collector with a user/group that can read those files. Avoid broad host permissions when a narrow group membership is enough.

Telemtra fields

  • service.name becomes the service selector.
  • deployment.environment becomes the environment selector.
  • host.name becomes the host selector shared by logs, traces, metrics, alerts, and dashboards.

Now that logs are flowing, see which log patterns to monitor and alert on. For OTLP protocol details see What is OTLP? For Windows hosts, see Windows Event Logs. New to Telemtra? Start with the quickstart for the minimum config across every supported stack. Create a workspace to get an API key.