# systemd-cat-native
`systemd` includes a utility called `systemd-cat`. This utility reads log lines from its standard input and sends them
to the local systemd journal. Its key limitation is that despite the fact that systemd journals support structured logs,
this command does not support sending structured logs to it.
`systemd-cat-native` is a Netdata supplied utility to push structured logs to systemd journals. Key features:
- reads [Journal Export Format](https://systemd.io/JOURNAL_EXPORT_FORMATS/) formatted log entries
- converts text fields into binary journal multiline log fields
- sends logs to any of these:
- local default `systemd-journald`,
- local namespace `systemd-journald`,
- remote `systemd-journal-remote` using HTTP or HTTPS, the same way `systemd-journal-upload` does.
- is the standard external logger of Netdata shell scripts
## Simple use:
```bash
printf "MESSAGE=hello world\nPRIORITY=6\n\n" | systemd-cat-native
```
The result:
![image](https://github.com/netdata/netdata/assets/2662304/689d5e03-97ee-40a8-a690-82b7710cef7c)
Sending `PRIORITY=3` (error):
```bash
printf "MESSAGE=hey, this is error\nPRIORITY=3\n\n" | systemd-cat-native
```
The result:
![image](https://github.com/netdata/netdata/assets/2662304/faf3eaa5-ac56-415b-9de8-16e6ceed9280)
Sending multi-line log entries (in this example we replace the text `--NEWLINE--` with a newline in the log entry):
```bash
printf "MESSAGE=hello--NEWLINE--world\nPRIORITY=6\n\n" | systemd-cat-native --newline='--NEWLINE--'
```
The result:
![image](https://github.com/netdata/netdata/assets/2662304/d6037b4a-87da-4693-ae67-e07df0decdd9)
Processing the standard `\n` string can be tricky due to shell escaping. This works, but note that
we have to add a lot of backslashes to printf.
```bash
printf "MESSAGE=hello\\\\nworld\nPRIORITY=6\n\n" | systemd-cat-native --newline='\n'
```
`systemd-cat-native` needs to receive it like this for newline processing to work:
```bash
# printf "MESSAGE=hello\\\\nworld\nPRIORITY=6\n\n"
MESSAGE=hello\nworld
PRIORITY=6
```
## Best practices
These are the rules about fields, enforced by `systemd-journald`:
- field names can be up to **64 characters**,
- field values can be up to **48k characters**,
- the only allowed field characters are **A-Z**, **0-9** and **underscore**,
- the **first** character of fields cannot be a **digit**
- **protected** journal fields start with underscore:
* they are accepted by `systemd-journal-remote`,
* they are **NOT** accepted by a local `systemd-journald`.
For best results, always include these fields:
- `MESSAGE=TEXT`
The `MESSAGE` is the body of the log entry.
This field is what we usually see in our logs.
- `PRIORITY=NUMBER`
`PRIORITY` sets the severity of the log entry.
`0=emerg, 1=alert, 2=crit, 3=err, 4=warn, 5=notice, 6=info, 7=debug`
- Emergency events (0) are usually broadcast to all terminals.
- Emergency, alert, critical, and error (0-3) are usually colored red.
- Warning (4) entries are usually colored yellow.
- Notice (5) entries are usually bold or have a brighter white color.
- Info (6) entries are the default.
- Debug (7) entries are usually grayed or dimmed.
- `SYSLOG_IDENTIFIER=NAME`
`SYSLOG_IDENTIFIER` sets the name of application.
Use something descriptive, like: `SYSLOG_IDENTIFIER=myapp`
You can find the most common fields at `man systemd.journal-fields`.
## Usage
```
Netdata systemd-cat-native v1.43.0-333-g5af71b875
This program reads from its standard input, lines in the format:
KEY1=VALUE1\n
KEY2=VALUE2\n
KEYN=VALUEN\n
\n
and sends them to systemd-journal.
- Binary journal fields are not accepted at its input
- Binary journal fields can be generated after newline processing
- Messages have to be separated by an empty line
- Keys starting with underscore are not accepted (by journald)
- Other rules imposed by systemd-journald are imposed (by journald)
Usage:
systemd-cat-native
[--newline=STRING]
[--log-as-netdata|-N]
[--namespace=NAMESPACE] [--socket=PATH]
[--url=URL [--key=FILENAME] [--cert=FILENAME] [--trust=FILENAME|all]]
The program has the following modes of logging:
* Log to a local systemd-journald or stderr
This is the default mode. If systemd-journald is available, logs will be
sent to systemd, otherwise logs will be printed on stderr, using logfmt
formatting. Options --socket and --namespace are available to configure
the journal destination:
--socket=PATH
The path of a systemd-journald UNIX socket.
The program will use the default systemd-journald socket when this
option is not used.
--namespace=NAMESPACE
The name of a configured and running systemd-journald namespace.
The program will produce the socket path based on its internal
defaults, to send the messages to the systemd journal namespace.
* Log as Netdata, enabled with --log-as-netdata or -N
In this mode the program uses environment variables set by Netdata for
the log destination. Only log fields defined by Netdata are accepted.
If the environment variables expected by Netdata are not found, it
falls back to stderr logging in logfmt format.
* Log to a systemd-journal-remote TCP socket, enabled with --url=URL
In this mode, the program will directly sent logs to a remote systemd
journal (systemd-journal-remote expected at the destination)
This mode is available even when the local system does not support
systemd, or even it is not Linux, allowing a remote Linux systemd
journald to become the logs database of the local system.
Unfortunately systemd-journal-remote does not accept compressed
data over the network, so the stream will be uncompressed.
--url=URL
The destination systemd-journal-remote address and port, similarly
to what /etc/systemd/journal-upload.conf accepts.
Usually it is in the form: https://ip.address:19532
Both http and https URLs are accepted. When using https, the
following additional options are accepted:
--key=FILENAME
The filename of the private key of the server.
The default is: /etc/ssl/private/journal-upload.pem
--cert=FILENAME
The filename of the public key of the server.
The default is: /etc/ssl/certs/journal-upload.pem
--trust=FILENAME | all
The filename of the trusted CA public key.
The default is: /etc/ssl/ca/trusted.pem
The keyword 'all' can be used to trust all CAs.
--namespace=NAMESPACE
Set the namespace of the messages sent.
--keep-trying
Keep trying to send the message, if the remote journal is not there.
NEWLINES PROCESSING
systemd-journal logs entries may have newlines in them. However the
Journal Export Format uses binary formatted data to achieve this,
making it hard for text processing.
To overcome this limitation, this program allows single-line text
formatted values at its input, to be binary formatted multi-line Journal
Export Format at its output.
To achieve that it allows replacing a given string to a newline.
The parameter --newline=STRING allows setting the string to be replaced
with newlines.
For example by setting --newline='--NEWLINE--', the program will replace
all occurrences of --NEWLINE-- with the newline character, within each
VALUE of the KEY=VALUE lines. Once this this done, the program will
switch the field to the binary Journal Export Format before sending the
log event to systemd-journal.
```