Simple tool to tail a log file and forward matching lines to Slack. A lightweight alternative to observability pipelines (e.g., Vector or Filebeat + Logstash) for this specific scenario.
Install via pipx:
pipx install git+https://github.com/ojuuji/log2slack.gitInstall via pip:
python3 -m venv .venv
source .venv/bin/activate
pip install git+https://github.com/ojuuji/log2slack.gitRun log2slack from the command line:
log2slack --config /path/to/config.tomlBelow are listed available configuration options and their defaults. Options marked "required" have no default.
[watcher]
# file is required
# file = "/path/to/log/file"
poll_interval = 0.5
[filter]
rules = []
[queue]
max_log_lines = 200
coalesce_rule = ""
[slack]
# hook_url is required
# hook_url = "https://hooks.slack.com/services/XXX/YYY/ZZZ"
channel = "log2slack"
username = "log2slack"
send_interval = 1.0
max_lines_per_msg = 20log2slack starts reading at the end of the log file specified via watcher.file. When there are no more lines to read, it waits watcher.poll_interval seconds and attempts to read again. If the log file is recreated or truncated, log2slack starts reading from the beginning.
In case some lines need to be ignored, configure filter.rules. It is a list of regex rules with a gitignore-like evaluation:
- Rules are checked in order from top to bottom.
!at the beginning of the rule negates it (turns allow into deny).- Last match wins. If it is negated, line is ignored, otherwise it is sent to Slack.
- If nothing matches -> default = allow. To have default = deny add
!.as the first rule - Rules are case-sensitive. Use
(?i)for case-insensitive matching (e.g.!(?i)debug).
Filtered lines are then added to a queue which holds up to queue.max_log_lines lines.
If the queue is full, lines are dropped. Queue counts dropped lines and includes this info in the Slack message. For example, here was a gap of 12 lines:
example log line 19
example log line 20
(...dropped 12 lines...)
example log line 33
Sequential duplicate lines do not increase the queue size. Instead, queue counts them and includes this info in the Slack message similar to the dropped lines:
example log line 40
this line is repeated 20 times
(...repeated 19 times...)
example log line 61
By default, the entire line is compared with the previous one to detect sequential duplicates. To compare only part of the line (e.g., to ignore timestamps), set queue.coalesce_rule to a regex with a named capture group payload. If the regex matches, only the payload group is used for duplicate detection.
For example, if all lines start with a timestamp like this:
[27-May-2026 12:57:59 UTC] example log line 42
then sufficient queue.coalesce_rule would be:
[queue]
coalesce_rule = '^\[[^]]+\]\s*(?P<payload>.*)'Slack messages are sent at most once every slack.send_interval seconds.
Each message contains at most slack.max_lines_per_msg lines. Note, this includes repeated/dropped info lines so a single log line may result in up to three lines in the Slack message.
Here is example of using log2slack as a systemd service under user foo (make sure foo can read the log file):
[Unit]
Description=log2slack
After=network-online.target
[Service]
User=foo
# Use the exact path from: pipx which log2slack
ExecStart=/home/foo/.local/bin/log2slack -c /etc/log2slack/config.toml
Restart=on-failure
[Install]
WantedBy=multi-user.target