Collect syslog and journald logs
Overview
Section titled “Overview”Linux hosts expose their system logs in two places: the classic syslog stream that daemons such as rsyslog and syslog-ng write and forward over the network, and the systemd journal that journald maintains as a structured binary store. The OpenTelemetry Collector reads both — the syslog receiver listens for forwarded syslog messages, and the journald receiver shells out to journalctl to read the journal — and ships either to Osuite over OTLP.
Use the syslog receiver when a syslog daemon is already running and you want to point its output at the Collector, including centralized setups where many hosts forward to one collector. Use the journald receiver when you want system logs straight from the journal without a forwarding daemon in the path. For application log files on disk, see Collect log files.
Prerequisites
Section titled “Prerequisites”- The OpenTelemetry Collector (contrib distribution) — both receivers ship in
opentelemetry-collector-contrib. - An Osuite ingest token and endpoint — see Getting Started.
- For syslog:
rsyslogorsyslog-ngrunning on the host, with permission to add a forwarding rule. - For journald: the Collector must run where the
journalctlbinary and the journal files are available — see Run the Collector where the journal lives.
Collect syslog over the network
Section titled “Collect syslog over the network”The syslog receiver opens a TCP or UDP listener, parses each incoming message as RFC 5424 or RFC 3164, and emits a structured log record. It maps the syslog priority to the record’s severity and the syslog timestamp to the record’s time automatically, so no separate severity or timestamp parser is needed.
Configure the Collector
Section titled “Configure the Collector”This otel-collector.yaml listens for RFC 5424 messages over TCP on port 54527, promotes the parsed message to the log body, and exports to Osuite. The listen port is arbitrary — match it in the daemon config below.
receivers: syslog: tcp: listen_address: "0.0.0.0:54527" protocol: rfc5424 operators: - type: move from: attributes.message to: body
processors: batch: {} resourcedetection: detectors: [system]
exporters: otlp/osuite: endpoint: ingest.<region>.osuite.io:443 tls: insecure: false headers: x-osuite-ingest-token: <your-ingest-token>
service: pipelines: logs: receivers: [syslog] processors: [batch, resourcedetection] exporters: [otlp/osuite]For UDP transport, replace the tcp block with udp:
syslog: udp: listen_address: "0.0.0.0:54527" protocol: rfc5424Forward from rsyslog
Section titled “Forward from rsyslog”Add a forwarding rule in /etc/rsyslog.d/60-osuite.conf. This sends every message to the Collector over TCP in RFC 5424 format, matching protocol: rfc5424 above:
*.* action(type="omfwd" target="127.0.0.1" port="54527" protocol="tcp" template="RSYSLOG_SyslogProtocol23Format")Reload rsyslog with systemctl restart rsyslog. The RSYSLOG_SyslogProtocol23Format template emits RFC 5424; to send the traditional BSD format instead, use RSYSLOG_TraditionalForwardFormat and set protocol: rfc3164 on the receiver.
Forward from syslog-ng
Section titled “Forward from syslog-ng”Add a destination and log path in /etc/syslog-ng/conf.d/osuite.conf. The syslog() driver sends RFC 5424 over TCP:
destination d_osuite { syslog("127.0.0.1" transport("tcp") port(54527));};
log { source(s_src); destination(d_osuite);};Reload with systemctl restart syslog-ng. s_src is the default source defined in the stock syslog-ng.conf; adjust the name if your configuration differs.
Parsing, severity, and timestamps
Section titled “Parsing, severity, and timestamps”- Protocol — set
protocoltorfc5424for the modern structured format orrfc3164for the traditional BSD format. The value must match what the daemon sends. - Severity — the receiver reads the syslog PRI header and sets the record’s
SeverityNumberautomatically, so filtering by level in the Logs Explorer works without extra operators. - Timestamps — RFC 3164 timestamps carry no year or timezone. Set
location(for examplelocation: America/New_York) on the receiver so they are interpreted in the host’s zone; RFC 5424 timestamps are unambiguous and need nolocation. - Sender identity — the parsed
hostname,appname, andfacilityare kept as attributes. In centralized setups where many hosts forward to one Collector, filter by thehostnameattribute to isolate a sender, sinceresourcedetectiontags records with the Collector’s host, not the origin’s.
Collect journald logs
Section titled “Collect journald logs”The journald receiver reads the systemd journal by invoking journalctl. It is useful on hosts where journald is the system of record and you would rather not run a separate syslog daemon.
Run the Collector where the journal lives
Section titled “Run the Collector where the journal lives”The simplest and recommended path is to run the Collector directly on the host — as a systemd service or a plain binary — where journalctl is already on PATH and the journal under /var/log/journal (persistent) or /run/log/journal (volatile) is readable. The config below assumes this.
If you must run the Collector in a container, either build a custom image that installs journalctl and bind-mount the host journal read-only, or mount the host root and point journalctl at it through a chroot:
docker run -v /:/host:ro --user 0 otel/opentelemetry-collector-contribThen set root_path: /host on the receiver so it runs journalctl against the host’s journal.
Configure the Collector
Section titled “Configure the Collector”By default the receiver places the entire journal entry as a structured map in the record body. This otel-collector.yaml promotes the message to the body, lifts the systemd unit to an attribute, maps the journal priority to severity, and exports to Osuite:
receivers: journald: start_at: end priority: info
processors: batch: {} resourcedetection: detectors: [system]
exporters: otlp/osuite: endpoint: ingest.<region>.osuite.io:443 tls: insecure: false headers: x-osuite-ingest-token: <your-ingest-token>
service: pipelines: logs: receivers: [journald] processors: [batch, resourcedetection] exporters: [otlp/osuite]Filter by unit and priority
Section titled “Filter by unit and priority”Reading the whole journal is often too much. Narrow it at the receiver so only the units and severities you care about are collected:
journald: start_at: end units: - ssh - nginx - kubelet priority: infounits— collect only these systemd units. Omit to read every unit.priority— drop anything below this syslog priority.infokeepsinfoand more severe; usewarningorerrto reduce volume further.matches— for finer control, filter on any journal field (for example_SYSTEMD_UNITor_TRANSPORT); each list entry is a set of ANDed conditions.start_at—endreads only new entries (default);beginningbackfills the existing journal on first start.
Parsing and severity mapping
Section titled “Parsing and severity mapping”The receiver does not map severity on its own — a fresh record keeps SeverityNumber unset even though the journal carries a PRIORITY field. Add operators to promote the message and map the numeric syslog priority (0 = emergency through 7 = debug) to OpenTelemetry severity:
journald: start_at: end priority: info operators: - type: move from: body._SYSTEMD_UNIT to: attributes["systemd.unit"] - type: severity_parser parse_from: body.PRIORITY mapping: fatal: - "0" - "1" - "2" error: "3" warn: - "4" - "5" info: "6" debug: "7" - type: move from: body.MESSAGE to: bodyThe severity_parser and the unit move run while the body is still the full journal map, so they read body.PRIORITY and body._SYSTEMD_UNIT. The final move replaces the body with just MESSAGE; do it last, after everything else you want has been lifted out. Other journal fields such as _PID or SYSLOG_IDENTIFIER are available in the body map and can be moved to attributes the same way before that final step.
Verify in Osuite
Section titled “Verify in Osuite”What you should see
Within a minute, system log records appear in the Logs Explorer. Syslog records carry hostname, appname, and facility attributes with severity already set from the PRI header; journald records carry systemd.unit and the severity mapped from PRIORITY. Filtering by severity returns the expected levels.
Troubleshooting
Section titled “Troubleshooting”- No syslog records — confirm the daemon is forwarding to the Collector’s
listen_addressand port, that the transport matches (tcpvsudp), and thatprotocolmatches the format the daemon sends. A firewall between daemon and Collector will silently drop the traffic. - Garbled syslog messages — the
protocolsetting does not match the sender. RFC 5424 output parsed asrfc3164(or the reverse) produces malformed records. journalctl: command not foundor the receiver fails to start — the Collector is running in an environment without thejournalctlbinary; run it on the host or use the container workaround above.- Empty journald output — the journal may be volatile only. Confirm the process can read
/var/log/journalor/run/log/journal, and thatpriorityis not filtering everything out. - Severity always unset for journald — the
severity_parseroperator is missing orparse_fromdoes not point atbody.PRIORITY.
No data in Osuite after a few minutes? Work through these checks.
- Endpoint — confirm the exporter targets exactly
ingest.<region>.osuite.io:443for your region, over TLS. - Token — confirm the ingest header carries a valid
<your-ingest-token>and has not been rotated. - Pipeline — confirm the signal you expect (traces, logs, or metrics) is wired into an active pipeline with the
otlp/osuiteexporter attached. - Export errors — check the application or Collector logs for OTLP export failures (auth, DNS, TLS, connection refused).
- Network — confirm the host has outbound access to the ingest endpoint on port
443. - Timing — allow up to a minute for the first data to appear before assuming a failure.
Still stuck? Ask the Investigation Agent or contact support.