Monitoring and Logging — syslog, journalctl, logrotate, Prometheus, Grafana
Monitoring and logging are the eyes and ears of every production system. This guide covers traditional syslog, systemd’s journalctl, log management with logrotate, and modern metrics monitoring with Prometheus and Grafana.
What You’ll Learn
You’ll configure rsyslog for centralized log collection, query logs with journalctl, automate log rotation with logrotate, collect system metrics with Prometheus node_exporter, and visualize everything in Grafana dashboards. DodaZIP uses Prometheus+Grafana for real-time compression cluster monitoring, and Durga Antivirus Pro uses centralized syslog for threat event correlation.
Why Monitoring and Logging Matter
You can’t fix what you can’t see. Logs tell you what happened after an outage; metrics tell you what’s happening right now. Together, they provide observability — the ability to understand a system’s internal state from its external outputs. Without monitoring, you’re flying blind.
Learning Path
flowchart LR
A[Shell Scripting] --> B[Monitoring & Logging<br/>You are here]
B --> C[Infrastructure Automation]
C --> D[Container Orchestration]
style B fill:#f90,color:#fff
syslog and rsyslog
Syslog is the standard logging protocol on Linux. Rsyslog is the modern high-performance implementation.
Rsyslog Configuration
# Main configuration
cat /etc/rsyslog.conf
# Common log facilities and priorities
# auth, authpriv, cron, daemon, kern, lpr, mail, news, syslog, user, uucp, local0-local7
# debug, info, notice, warning, err, crit, alert, emerg
# Default log destinations
cat /etc/rsyslog.d/50-default.conf
# *.info;mail.none;authpriv.none;cron.none /var/log/messages
# authpriv.* /var/log/secure
# mail.* /var/log/maillog
# cron.* /var/log/cron
# *.emerg :omusrmsg:*Centralized Logging Server
# On the log server (receiver)
# /etc/rsyslog.d/server.conf
module(load="imtcp")
module(load="imudp")
input(type="imtcp" port="514")
input(type="imudp" port="514")
# Template for organizing logs by host
$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
*.* ?RemoteLogs
# On client machines (senders)
# /etc/rsyslog.d/client.conf
*.* @@logserver.dodatech.com:514 # TCP (reliable)
*.* @logserver.dodatech.com:514 # UDP (faster)
# Restart
sudo systemctl restart rsyslogjournalctl — Systemd Logging
Journald collects logs from all systemd services, the kernel, and syslog:
# View all logs
journalctl
# Follow new logs (like tail -f)
journalctl -f
# Last N lines
journalctl -n 50
# Logs since boot
journalctl -b
# Previous boot logs
journalctl -b -1
# Logs for a specific service
journalctl -u nginx
journalctl -u sshd.service
# Logs for a specific time
journalctl --since "1 hour ago"
journalctl --since "2026-06-20" --until "2026-06-21"
# Logs by priority
journalctl -p err # Errors and above
journalctl -p warning # Warnings and above
# JSON output
journalctl -o json-pretty
# Show only kernel messages
journalctl -k
# Export to file
journalctl -u myapp > /tmp/myapp.log
# Show disk usage
journalctl --disk-usage
# Vacuum (clean old logs)
sudo journalctl --vacuum-time=30d # Keep 30 days
sudo journalctl --vacuum-size=500M # Keep 500MB maxExpected journalctl --disk-usage:
Archived and active journals take up 256.0M in the file system.Journald Configuration
# /etc/systemd/journald.conf
[Journal]
Storage=persistent # Logs survive reboot
Compress=yes # Compress old logs
Seal=yes # Cryptographic sealing
SplitMode=uid # Split by user
SyncIntervalSec=5m
RateLimitIntervalSec=30s
RateLimitBurst=10000
SystemMaxUse=1G # Max 1GB for system logs
MaxFileSec=1month # Rotate monthlylogrotate — Log Rotation
Logrotate prevents logs from consuming all disk space by rotating, compressing, and deleting old logs:
# Main configuration
cat /etc/logrotate.conf
# Default settings
# rotate 4 # Keep 4 old logs
# weekly # Rotate weekly
# create # Create new log after rotation
# compress # Compress old logs (gzip)
# include /etc/logrotate.d # Include individual configsExample logrotate Configurations
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 640 nginx adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 30
compress
maxsize 100M # Rotate if log reaches 100MB even if not daily
minsize 1M # Only rotate if > 1MB
missingok
notifempty
dateext # Add date to rotated file name
create 640 myapp myapp
postrotate
systemctl reload myapp
endscript
}Testing Logrotate
# Dry run
sudo logrotate -d /etc/logrotate.conf
# Force rotation
sudo logrotate -f /etc/logrotate.conf
# Debug mode
sudo logrotate -d /etc/logrotate.d/nginxExpected logrotate -d /etc/logrotate.d/nginx output:
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B
Handling 1 logs
rotating pattern: /var/log/nginx/*.log daily (14 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/nginx/access.log
Now: 2026-06-20 10:00
Last rotated at 2026-06-19 10:00
log needs rotating
rotating log /var/log/nginx/access.log, log->rotateCount is 14
...Prometheus Node Exporter
Node exporter exposes system metrics (CPU, memory, disk, network) in Prometheus format:
# Install node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-amd64.tar.gz
tar xzf node_exporter-1.8.0.linux-amd64.tar.gz
sudo mv node_exporter-1.8.0.linux-amd64/node_exporter /usr/local/bin/
# Create systemd service
sudo tee /etc/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Type=simple
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter \
--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/) \
--collector.textfile.directory=/var/lib/node_exporter/textfile
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# Create user and start
sudo useradd -rs /bin/false node_exporter
sudo systemctl enable --now node_exporterVerify Metrics
# Check metrics endpoint
curl -s http://localhost:9100/metrics | head -20Expected output:
# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 1234567.89
node_cpu_seconds_total{cpu="0",mode="system"} 23456.78
node_cpu_seconds_total{cpu="0",mode="user"} 123456.78
# HELP node_disk_read_bytes_total The total number of bytes read successfully.
# TYPE node_disk_read_bytes_total counter
node_disk_read_bytes_total{device="sda"} 1234567890123
# HELP node_filesystem_avail_bytes Filesystem space available to non-root users.
# TYPE node_filesystem_avail_bytes gauge
node_filesystem_avail_bytes{device="/dev/sda1",fstype="ext4",mountpoint="/"} 123456789012Prometheus Configuration
# /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets:
- 'web-01.dodatech.com:9100'
- 'web-02.dodatech.com:9100'
- 'db-01.dodatech.com:9100'
- 'app-01.dodatech.com:9100'Grafana Dashboards
Grafana visualizes Prometheus metrics in customizable dashboards:
# Install Grafana
sudo apt-get install -y software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y grafana
sudo systemctl enable --now grafana-serverUseful PromQL Queries for Dashboards
# CPU usage percentage
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Memory usage percentage
100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
# Disk usage percentage
100 * (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"})
/ node_filesystem_size_bytes{mountpoint="/"}
# Network receive rate (bytes/sec)
rate(node_network_receive_bytes_total{device="eth0"}[5m])
# Disk I/O rate
rate(node_disk_read_bytes_total{device="sda"}[5m])
# System load average
node_load15
# Uptime in days
time() - node_boot_time_secondsImport Node Exporter Full Dashboard
Grafana dashboard ID 1860 is the standard Node Exporter Full dashboard. Import it via:
- Grafana UI → Create → Import → Enter
1860→ Load
Setting Up Alerts
# prometheus-alert.yml — Alert rules
groups:
- name: node_alerts
rules:
- alert: InstanceDown
expr: up == 0
for: 5m
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} has been down for more than 5 minutes."
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
annotations:
summary: "High CPU on {{ $labels.instance }}"
description: "CPU usage is above 80% for 10 minutes."
- alert: DiskSpaceLow
expr: 100 * (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"})
/ node_filesystem_size_bytes{mountpoint="/"} > 90
for: 5m
annotations:
summary: "Low disk space on {{ $labels.instance }}"
description: "Disk usage is above 90%."Common Monitoring Mistakes
1. Not Setting Retention Policies
Logs and metrics grow without bounds. Set logrotate for logs, retention_time in Prometheus, and dashboard data retention in Grafana. Monitor storage usage.
2. Monitoring Everything
More metrics don’t equal better observability. Focus on the Four Golden Signals: latency, traffic, errors, and saturation. Start with 10 key metrics and expand as needed.
3. No Alert Fatigue Management
Too many alerts cause alert fatigue — critical alerts get ignored. Set appropriate thresholds, use for: duration to avoid flapping, and route alerts by severity.
4. Ignoring Log Compression
Uncompressed logs consume 5-10x more disk space. Enable compression in logrotate and journald. Archive old logs to cold storage.
5. Scraping Too Frequently
Prometheus scraping every 5 seconds on 1000 targets generates significant load. Default 15s is usually sufficient. Adjust based on metric churn.
6. Not Having a Logging Strategy
Logs are useless if you can’t find them in a crisis. Structure logs as JSON with consistent fields: timestamp, level, service, message, request_id. Use centralized logging for multi-server environments.
7. Dashboard Sprawl
Hundreds of dashboards nobody maintains or looks at. Keep dashboards focused — one per service or team. Archive unused dashboards.
Practice Questions
1. What’s the difference between syslog and journald? Syslog is the traditional text-based logging system, using rsyslog for routing. Journald is systemd’s structured binary logging with metadata (PID, priority, boot ID). They can work together — journald forwards to rsyslog.
2. How does logrotate prevent disk full issues? It rotates logs (renames + creates new), compresses old logs, removes logs older than the retention period, and can trigger reload signals to services so they write to the new file.
3. What’s the difference between Prometheus and Graphite? Prometheus pulls metrics via HTTP (pull model), has built-in alerting, and uses dimensional labels. Graphite uses push model with dot-separated metric names. Prometheus is more modern and widely adopted.
4. What are the Four Golden Signals of monitoring? Latency (response time), traffic (requests per second), errors (error rate), saturation (resource utilization). These four signals give a complete picture of system health.
5. Challenge: A server runs out of disk space every 3 months due to logs. Design a comprehensive log management strategy that prevents this and provides 90-day retention. Answer: Configure logrotate for all services with weekly rotation, 14 compressed copies, and maxsize limits. Set journald SystemMaxUse=2G. Add Prometheus node_exporter alert at 80% disk usage. Archive logs older than 30 days to S3/Glacier for remaining retention.
Mini Project: Server Monitoring Stack
Create a script that sets up a complete monitoring stack:
#!/bin/bash
# setup_monitoring.sh — Install and configure monitoring stack
# Usage: sudo ./setup_monitoring.sh
set -euo pipefail
echo "=== Setting Up Monitoring Stack ==="
# 1. Install and configure node_exporter
echo "Installing node_exporter..."
NODE_EXPORTER_VERSION="1.8.0"
cd /tmp
wget -q "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz"
tar xzf "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz"
sudo mv "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter" /usr/local/bin/
sudo useradd -rs /bin/false node_exporter 2>/dev/null || true
# Create systemd service
cat << 'SERVICEEOF' | sudo tee /etc/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Type=simple
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
Restart=always
[Install]
WantedBy=multi-user.target
SERVICEEOF
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
# 2. Install Prometheus
echo "Installing Prometheus..."
PROMETHEUS_VERSION="2.53.0"
cd /tmp
wget -q "https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz"
tar xzf "prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz"
sudo mv "prometheus-${PROMETHEUS_VERSION}.linux-amd64" /etc/prometheus
# Create prometheus config
cat << 'PROMEOF' | sudo tee /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
PROMEOF
sudo useradd -rs /bin/false prometheus 2>/dev/null || true
sudo chown -R prometheus:prometheus /etc/prometheus
cat << 'SERVICEEOF' | sudo tee /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus
After=network.target
[Service]
Type=simple
User=prometheus
ExecStart=/etc/prometheus/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus/
Restart=always
[Install]
WantedBy=multi-user.target
SERVICEEOF
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
# 3. Install Grafana
echo "Installing Grafana..."
sudo apt-get install -y -qq software-properties-common
sudo add-apt-repository -y "deb https://packages.grafana.com/oss/deb stable main" 2>/dev/null
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add - 2>/dev/null
sudo apt-get update -qq
sudo apt-get install -y -qq grafana
sudo systemctl enable --now grafana-server
# 4. Configure logrotate
cat << 'LOGEOF' | sudo tee /etc/logrotate.d/custom
/var/log/*.log {
weekly
rotate 12
compress
delaycompress
missingok
notifempty
create 640 root root
}
LOGEOF
echo ""
echo "=== Monitoring Stack Installed ==="
echo "Node Exporter: http://localhost:9100/metrics"
echo "Prometheus: http://localhost:9090"
echo "Grafana: http://localhost:3000 (admin/admin)"
echo ""
echo "Add the Prometheus data source in Grafana to start graphing."FAQ
What’s Next
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-20.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro