# logger2
A modern, feature-rich replacement for the classic Unix `logger(1)` CLI —
same core job (send a message to syslog), but with truecolor hex output,
emoji, JSON output, remote delivery over UDP/TCP, RFC 5424 support, and a
fully configurable TOML config file.
Written in Rust. Single static-ish binary, cross-platform, no runtime
dependencies.
```
$ logger2 -l warning "disk usage on /var is at 92%"
2026-07-01 09:41:06.243 ⚠️ WARN [hadi] disk usage on /var is at 92%
```
## Features
- **Drop-in familiar CLI** — mirrors util-linux `logger`'s flags (`-p`,
`-t`, `-i`, `-s`, `-f`, `-n`, `-P`, `-T`/`-d`, `-u`, `-r`, `-S`) so existing
scripts and muscle memory transfer directly.
- **Truecolor hex output** — per-level colors configured as `#RRGGBB` (or
overridden per-invocation with `-c`), rendered with 24-bit ANSI escapes.
- **Emoji decoration** — a configurable emoji per severity level, or an
ad-hoc override with `-e`.
- **Local *and* remote syslog** — writes to the local syslog Unix socket
(`/dev/log` on Linux, `/var/run/syslog` on macOS) by default, or to a
remote syslog daemon over UDP or TCP with `-n`/`--server`.
- **RFC 3164 and RFC 5424 framing** — pick the legacy BSD format or the
modern IETF format with structured data, plus RFC 6587 octet-counting
for TCP.
- **JSON output mode** — `--json` emits one structured JSON object per line
for easy piping into `jq`, log shippers, or other tooling.
- **Structured fields** — attach arbitrary `key=value` pairs with `-k`,
included in both console and JSON output and forwarded as RFC 5424
structured data.
- **Fully configurable via TOML** — colors, emoji, default priority, output
template, network settings, and more, all overridable per-invocation by
CLI flags.
- **Safe on every platform** — local Unix-socket syslog delivery is
Linux/macOS/BSD only; on other platforms (e.g. Windows) logger2 degrades
gracefully and tells you to use `--server` for remote delivery instead of
panicking or silently failing.
- **`--dry-run`** — see exactly what would be printed and sent, without
sending anything.
## Installation
### From crates.io
```
cargo install logger2
```
### From a release binary
Download the archive for your platform from the
[Releases page](https://github.com/licface/logger2/releases), extract it,
and put the `logger2` binary on your `PATH`.
### From source
```
git clone https://github.com/licface/logger2
cd logger2
cargo build --release
# binary at target/release/logger2
```
## Usage
```
logger2 [OPTIONS] [MESSAGE]...
```
If `MESSAGE` is omitted, logger2 reads from `--file`, then falls back to
stdin.
### Basic examples
```
# Simple message at the default priority (user.notice)
logger2 "backup completed successfully"
# Explicit facility.level priority (like the original logger)
logger2 -p local0.error "disk write failed"
# Friendly level name instead of spelling out facility.level
logger2 -l error "disk write failed"
# Custom tag and include the PID
logger2 -t backup-script -i "starting nightly backup"
# Read the message from a file
logger2 -f /var/log/app/last-error.txt -l error
# Pipe a message in
# One-off color/emoji override, ignoring the config file
logger2 -c "#FF00AA" -e "🚀" -l info "deploy started"
# Ship straight to a remote syslog collector over TCP with RFC 5424 framing
logger2 -n logs.example.com -P 6514 -T -r -l critical "node unreachable"
# Attach structured fields (shown in console output, JSON, and RFC 5424 SD)
logger2 --json -k request_id=abc123 -k user=alice -l info "request handled"
# See what would happen without actually sending or writing anything
logger2 --dry-run -l debug "just checking output"
```
### Levels
`trace`, `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`,
`emergency` — mapped to standard syslog severities 7 down to 0 (`trace` is a
non-standard convenience level that maps to severity 7, same as `debug`).
### Facilities
All standard syslog facilities are supported: `kern`, `user`, `mail`,
`daemon`, `auth`, `syslog`, `lpr`, `news`, `uucp`, `cron`, `authpriv`,
`ftp`, `ntp`, `security`, `console`, `solaris-cron`, and `local0`–`local7`.
## Configuration file
logger2 looks for a config file in this order (first match wins):
1. `--config <path>` / `LOGGER2_CONFIG` environment variable
2. `$XDG_CONFIG_HOME/logger2/config.toml` (or the platform equivalent,
e.g. `~/.config/logger2/config.toml` on Linux)
3. `~/.logger2.toml`
4. `/etc/logger2/config.toml` (Unix only)
5. Built-in defaults, if none of the above exist
Generate a starter config with:
```
logger2 --init-config
```
Inspect the fully-resolved effective config (defaults + file + no CLI
overrides) with:
```
logger2 --print-config
```
### Example config
```toml
[general]
default_priority = "user.notice"
default_tag = "" # empty = use the current username
timestamp_format = "%Y-%m-%d %H:%M:%S%.3f"
show_pid = false
max_message_size = 8192
[output]
stderr = true
syslog = true
json = false
template = "{timestamp} {emoji} {level} [{tag}] {message}"
[network]
server = "" # empty = deliver to the local syslog socket
port = 514
protocol = "udp" # "udp" or "tcp"
socket = "/dev/log" # local Unix socket path
rfc5424 = false
octet_count = false
connect_timeout_ms = 2000
[colors]
enabled = true
tag = "#87AFFF"
timestamp = "#808080"
message = "#FFFFFF"
[colors.levels]
trace = "#808080"
debug = "#00AFFF"
info = "#00FF00"
notice = "#00FFFF"
warning = "#FFFF00"
error = "#FF5555"
critical = "#FF00FF"
alert = "#FF0000"
emergency = "#FFFFFF"
[emoji]
enabled = true
[emoji.levels]
trace = "🔍"
debug = "🐛"
info = "ℹ️"
notice = "📝"
warning = "⚠️"
error = "❌"
critical = "🔥"
alert = "🚨"
emergency = "💀"
```
Command-line flags always take precedence over the config file, which in
turn takes precedence over built-in defaults.
### Output template placeholders
`{timestamp}`, `{emoji}`, `{level}`, `{tag}`, `{message}` are substituted
into `output.template`.
## Color and emoji behavior
- Colors are disabled automatically when output is not a TTY, when
`NO_COLOR` is set, or with `--no-color`. Force them on with
`--force-color` or `CLICOLOR_FORCE`.
- Emoji can be turned off globally in the config (`emoji.enabled = false`)
or per-invocation with `--no-emoji`.
- `-c`/`--color` and `-e`/`--emoji` override the level-based defaults for a
single invocation without touching the config file.
## Platform notes
- **Linux / macOS / BSD**: full support, including local syslog delivery
over the Unix domain socket.
- **Windows**: local Unix-socket syslog delivery is not available (there is
no `/dev/log` equivalent); use `-n`/`--server` to ship to a remote syslog
collector over UDP or TCP, which works everywhere. Console/JSON output
works identically on every platform.
## Exit codes
| 0 | Success |
| 1 | Delivery failed, or a usage/validation error occurred |
## Development
```
make build # debug build
make test # run unit + integration tests
make lint # clippy, warnings as errors
make fmt # rustfmt
make release # optimized release build
make cross-all # cross-compile for all supported targets (needs rustup)
make dist # cross-compile + package tarballs into dist/
```
## License
Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or
[MIT license](LICENSE-MIT) at your option.
## 👤 Author
[Hadi Cahyadi](mailto:cumulus13@gmail.com)
[](https://www.buymeacoffee.com/cumulus13)
[](https://ko-fi.com/cumulus13)
[Support me on Patreon](https://www.patreon.com/cumulus13)