A lightweight, self-contained observability agent for monitoring Ubuntu servers with disk usage tracking, kernel monitoring, Docker container health, and webhook-based alerting.
- 📊 Disk Usage Monitoring — Track largest directories with configurable thresholds
- 🐳 Docker Log Monitoring — Filter container logs for errors, panics, OOM events
- 🔍 Kernel Monitoring — Monitor dmesg for critical kernel events
- 💓 Heartbeat — Periodic alive signals for health tracking
- 🔄 Event Deduplication — Reduce noise with smart event hashing
- 📈 Performance Stats — Track collector performance metrics
- 🔔 Webhook Alerts — Discord, Slack, and custom API notifications
- 🔒 Dead Man's Switch — Detect silent failures with receiver-side monitoring
- 📝 Log Rotation — Automatic log rotation with lumberjack
- 🔄 Hot Reload — Update config without restart (SIGHUP)
- 🏗️ Dual Mode — Run as collector (agent) or receiver (central server)
Download the latest release for your platform from GitHub Releases:
# Linux amd64
wget https://github.com/YOUR_USERNAME/baadhal/releases/latest/download/baadal-linux-amd64.tar.gz
tar -xzf baadal-linux-amd64.tar.gz
chmod +x baadal-linux-amd64
# Verify checksum
sha256sum -c baadal-linux-amd64.tar.gz.sha256git clone https://github.com/YOUR_USERNAME/baadhal.git
cd baadhal
go mod download
go build -o baadal main.goBaadal uses a YAML configuration file (config.yml) with comprehensive options for each monitoring component.
app:
name: "baadal"# Application name (used in logs)enabled: true # Master switch - set to false to disablelog_level: "info"# Logging level: debug | info | warn | errorheartbeat:
enabled: true # Enable periodic heartbeat eventsinterval: "*/5 * * * *"# Cron expression for heartbeat frequency# Examples:# "*/5 * * * *" - Every 5 minutes# "*/10 * * * *" - Every 10 minutes# "0 * * * *" - Every hourdeduplication:
enabled: true # Enable event deduplicationwindow_seconds: 60# Time window to check for duplicates# Events with identical type+host+data # within this window are discardedHeartbeat Details:
- Sends periodic "alive" signals to receiver
- Includes uptime in seconds
- Helps detect collector crashes or network issues
- Recommended: 5-10 minutes for production
Deduplication Details:
- Uses MD5 hash of (type + host + data) for comparison
- Prevents alert spam from repeated errors
- Memory-efficient with automatic cleanup every 5 minutes
- Recommended: 60-300 seconds depending on alert frequency
transport:
mode: "remote"# "remote" or "local"remote: # Used when mode = "remote"endpoint: "http://receiver-ip:5170/ingest"# Receiver URL# Use Tailscale/VPN IP for securityauth:
enabled: false # Enable bearer token authenticationtoken: "your-secret-token"# Must match receiver tokenbatch_size: 10# Send after N events accumulateflush_interval: "5s"# Or send after this time (whichever first)retry_attempts: 3# Number of retries on failureretry_delay: "2s"# Delay between retry attemptslocal: # Used when mode = "local"log_output: "/var/log/baadal/events.log"# Local file pathMode Selection:
- remote: Recommended for production - sends to central receiver
- local: For testing or standalone logging
Remote Transport Tips:
- Use
batch_size: 1andflush_interval: "1s"for real-time alerting - Use
batch_size: 50andflush_interval: "30s"to reduce network traffic - Enable
auth.enabled: truefor production deployments
Endpoint Examples:
endpoint: "http://192.168.1.100:5170/ingest"# Local networkendpoint: "http://100.x.x.x:5170/ingest"# Tailscaleendpoint: "https://monitor.example.com/ingest"# Public (use HTTPS + auth!)disk:
enabled: true # Enable disk usage monitoringpaths: # Directories to scan
- / # Root filesystem
- /var # Common log location
- /var/lib/docker # Docker data
- /home # User directories
- /tmp # Temporary files
- /opt # Optional softwaretop_n: 5# Report top N largest directoriesmax_depth: 3# Maximum directory depth to scan# Higher = more detail but slowerschedule: "*/5 * * * *"# Cron schedule for scans# Examples:# "*/15 * * * *" - Every 15 minutes# "0 */2 * * *" - Every 2 hours# "0 3 * * *" - Daily at 3 AMalert:
enabled: true # Enable alerting for disk usagecondition: "size_gb > 20"# Alert when directory exceeds 20 GB# Can adjust threshold as neededwebhooks: # Webhook names to fire (from webhooks section)
- discord
- custom-apiPath Selection Tips:
- Start with root paths (
/,/var,/home) - Add Docker path if running containers:
/var/lib/docker - Add application-specific paths:
/opt/myapp,/data - Avoid network mounts (slow scans)
Performance Tuning:
# Fast scan (less detail, every 30 min)max_depth: 2schedule: "*/30 * * * *"# Detailed scan (more detail, hourly)max_depth: 4schedule: "0 * * * *"# Daily deep scanmax_depth: 5schedule: "0 2 * * *"# 2 AM dailyAlert Threshold Examples:
condition: "size_gb > 10"# Alert at 10 GBcondition: "size_gb > 50"# Alert at 50 GBcondition: "size_gb > 100"# Alert at 100 GBdmesg:
enabled: true # Enable kernel message monitoringschedule: "*/1 * * * *"# Check every minute (recommended)filter_levels: # Kernel log levels to monitor
- err # Error conditions
- crit # Critical conditions
- alert # Action must be taken immediately
- emerg # System is unusable# Available but not recommended for production:# - warn # Warning conditions (very noisy)# - notice # Normal but significant# - info # Informational# - debug # Debug-level messagesalert:
enabled: true # Enable alertingcondition: "level == crit"# Alert on critical messages# Options: emerg, alert, crit, errwebhooks:
- discordFilter Level Guide:
| Level | Severity | Typical Issues | Recommended |
|---|---|---|---|
emerg | Emergency | Kernel panic, system crash | ✅ Yes |
alert | Alert | Hardware failure, critical bug | ✅ Yes |
crit | Critical | Hard disk errors, memory issues | ✅ Yes |
err | Error | Driver errors, non-critical failures | ✅ Yes |
warn | Warning | Deprecation notices, soft errors | |
notice | Notice | Normal but significant | ❌ Too noisy |
info | Info | General information | ❌ Too noisy |
debug | Debug | Debug messages | ❌ Development only |
Alert Condition Examples:
condition: "level == crit"# Only critical errorscondition: "level == alert"# Alert-level and abovecondition: "level == emerg"# Only emergency (kernel panic)Best Practices:
- Run every 1-2 minutes for timely kernel error detection
- Filter to
err, crit, alert, emergonly - Don't include
warn- generates too many false positives
docker:
enabled: true # Enable Docker log monitoringcontainers: # Which containers to monitor
- "all"# Monitor all running containers# OR specify by name:# - "nginx"# - "postgres"# - "redis"tail_lines: 100# Number of recent log lines to check# Higher = more coverage but slowerschedule: "*/2 * * * *"# Check every 2 minutesfilter_keywords: # Keywords to search for in logs
- "error"# Generic errors
- "fatal"# Fatal errors
- "panic"# Go panic, Python panic
- "OOM"# Out of memory
- "killed"# Process killed
- "segfault"# Segmentation fault
- "exception"# Exceptions (add if using Python/Java)alert:
enabled: truecondition: "keyword == fatal"# Alert on "fatal" keyword matcheswebhooks:
- discord
- custom-apiContainer Selection:
# Monitor all containerscontainers: ["all"]# Monitor specific containerscontainers:
- "nginx"
- "postgres-primary"
- "redis"# Monitor by pattern (use "all" and filter in alerts)containers: ["all"]filter_keywords: ["error", "fatal"]Keyword Selection by Stack:
Node.js/JavaScript:
filter_keywords:
- "error"
- "fatal"
- "uncaughtException"
- "unhandledRejection"
- "ECONNREFUSED"
- "ETIMEDOUT"Python:
filter_keywords:
- "error"
- "fatal"
- "exception"
- "traceback"
- "critical"Java/Spring:
filter_keywords:
- "error"
- "exception"
- "OutOfMemoryError"
- "StackOverflowError"
- "SQLException"Go:
filter_keywords:
- "error"
- "fatal"
- "panic"
- "deadlock"Database (Postgres/MySQL):
filter_keywords:
- "error"
- "fatal"
- "panic"
- "deadlock"
- "connection refused"Alert Condition Examples:
condition: "keyword == fatal"# Only fatal errorscondition: "keyword == panic"# Only panicscondition: "keyword == OOM"# Only out of memoryPerformance Tips:
# Frequent checks (every minute)tail_lines: 50schedule: "*/1 * * * *"# Balanced (every 2 minutes)tail_lines: 100schedule: "*/2 * * * *"# Less frequent but thorough (every 5 minutes)tail_lines: 500schedule: "*/5 * * * *"Baadal supports multiple webhook destinations for alerts. Each webhook can have custom templates.
webhooks:
- name: "discord"enabled: trueurl: "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"method: POSTheaders:
Content-Type: "application/json"payload_template: | { "content": "🚨 {{.Title}}", "embeds": [{ "description": "{{.Message}}", "fields": [ {"name": "Host", "value": "{{.Hostname}}", "inline": true}, {"name": "Type", "value": "{{.Type}}", "inline": true}, {"name": "Severity", "value": "{{.Severity}}", "inline": true}, {"name": "Time", "value": "{{.Timestamp}}", "inline": true} ], "color": 16711680 }] }How to Get Discord Webhook URL:
- Open Discord server → Server Settings → Integrations
- Click "Webhooks" → "New Webhook"
- Choose channel, copy webhook URL
- Paste in config.yml
Discord Color Codes:
"color": 16711680# Red (critical)"color": 16776960# Yellow (warning)"color": 65280# Green (info)"color": 3447003# Blue (info) - name: "slack"enabled: trueurl: "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"method: POSTheaders:
Content-Type: "application/json"payload_template: | { "text": "🚨 *{{.Title}}*", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "*{{.Title}}*\n{{.Message}}" } }, { "type": "section", "fields": [ {"type": "mrkdwn", "text": "*Host:*\n{{.Hostname}}"}, {"type": "mrkdwn", "text": "*Type:*\n{{.Type}}"}, {"type": "mrkdwn", "text": "*Severity:*\n{{.Severity}}"}, {"type": "mrkdwn", "text": "*Time:*\n{{.Timestamp}}"} ] } ] }How to Get Slack Webhook URL:
- Visit https://api.slack.com/apps
- Create New App → "From scratch"
- Enable "Incoming Webhooks"
- Add New Webhook to Workspace
- Copy webhook URL
- name: "custom-api"enabled: trueurl: "https://your-api.com/alerts"method: POSTheaders:
Authorization: "Bearer YOUR_API_TOKEN"Content-Type: "application/json"X-Custom-Header: "baadal-alerts"payload_template: | { "alert": "{{.Title}}", "host": "{{.Hostname}}", "timestamp": "{{.Timestamp}}", "type": "{{.Type}}", "severity": "{{.Severity}}", "message": "{{.Message}}", "data": {{.Data}} } - name: "pagerduty"enabled: trueurl: "https://events.pagerduty.com/v2/enqueue"method: POSTheaders:
Content-Type: "application/json"payload_template: | { "routing_key": "YOUR_INTEGRATION_KEY", "event_action": "trigger", "payload": { "summary": "{{.Title}}", "severity": "critical", "source": "{{.Hostname}}", "custom_details": { "message": "{{.Message}}", "type": "{{.Type}}", "timestamp": "{{.Timestamp}}" } } } - name: "email"enabled: trueurl: "https://api.sendgrid.com/v3/mail/send"method: POSTheaders:
Authorization: "Bearer YOUR_SENDGRID_API_KEY"Content-Type: "application/json"payload_template: | { "personalizations": [{ "to": [{"email": "alerts@example.com"}] }], "from": {"email": "baadal@example.com"}, "subject": "{{.Title}}", "content": [{ "type": "text/plain", "value": "{{.Message}}\n\nHost: {{.Hostname}}\nTime: {{.Timestamp}}" }] }Template Variables:
{{.Title}}- Alert title{{.Message}}- Alert message{{.Hostname}}- Source hostname{{.Host}}- Same as Hostname{{.Timestamp}}- ISO8601 timestamp (IST timezone){{.Type}}- Event type (disk_usage, dmesg, docker_log, etc.){{.Severity}}- Alert severity (critical, warning, info){{.Data}}- Raw JSON event data
The receiver runs on your central monitoring server and accepts events from all collectors.
receiver:
enabled: true # Enable receiver modeport: 5170# Port to listen onauth:
enabled: false # Enable authenticationtoken: "your-secret-token"# Must match collector tokens# IMPORTANT: Enable in production!log_output: "/var/log/baadal/events.log"# Where to write eventslog_rotation: # Automatic log rotation (via lumberjack)max_size_mb: 50# Rotate after 50 MBmax_backups: 3# Keep 3 old log filesmax_age_days: 7# Delete logs older than 7 dayscompress: true # Gzip old log filesdead_mans_switch: # Detect missing collectorsenabled: truetimeout_minutes: 10# Alert if no events for 10 minutescheck_interval: "*/2 * * * *"# Check every 2 minuteswebhooks:
- discordpromtail: # Optional: Forward to Lokienabled: falseendpoint: "http://localhost:9080/loki/api/v1/push"Log Rotation Examples:
High-frequency monitoring (lots of events):
log_rotation:
max_size_mb: 100# Larger filesmax_backups: 7# Keep more historymax_age_days: 14# 2 weeks retentioncompress: trueLow-frequency monitoring:
log_rotation:
max_size_mb: 20# Smaller filesmax_backups: 3# Less historymax_age_days: 7# 1 week retentioncompress: trueDead Man's Switch:
- Monitors when each collector last sent events
- Fires webhook alert if collector goes silent
- Helps detect crashed collectors or network issues
Dead Man's Switch Examples:
# Tight monitoring (5 min timeout)timeout_minutes: 5check_interval: "*/1 * * * *"# Relaxed monitoring (30 min timeout)timeout_minutes: 30check_interval: "*/10 * * * *"# Daily check (for non-critical servers)timeout_minutes: 1440# 24 hourscheck_interval: "0 * * * *"# Hourly checkAuthentication:
# Development (no auth)auth:
enabled: false# Production (required!)auth:
enabled: truetoken: "use-a-long-random-string-here"# Generate token: openssl rand -base64 32Configure how this server identifies itself in events:
node:
hostname: ""# Empty = auto-detect from OS# Or set manually: "web-server-01"environment: "production"# Environment label# Options: production, staging, dev, testtags: # Custom tags for filtering/grouping
- "ubuntu"
- "backend"
- "api-server"
- "us-east-1"Hostname Examples:
hostname: ""# Auto-detect (recommended)hostname: "web-server-01"# Manual overridehostname: "db-primary"# For databaseshostname: "worker-03"# For worker nodesEnvironment Best Practices:
environment: "production"# Live production serversenvironment: "staging"# Staging/QA environmentenvironment: "development"# Dev serversenvironment: "test"# CI/CD test runnersTag Examples:
By Role:
tags: ["web-server", "nginx", "frontend"]tags: ["database", "postgres", "primary"]tags: ["worker", "celery", "background-jobs"]By Location:
tags: ["aws", "us-east-1", "production"]tags: ["on-premise", "datacenter-1"]tags: ["cloud", "digitalocean", "sgp1"]By Stack:
tags: ["nodejs", "express", "api"]tags: ["python", "django", "web"]tags: ["go", "microservice"]Here's a production-ready config.yml with all features enabled:
# ─────────────────────────────────────────────# Baadal — Production Configuration# ─────────────────────────────────────────────app:
name: "baadal"enabled: truelog_level: "info"heartbeat:
enabled: trueinterval: "*/5 * * * *"deduplication:
enabled: truewindow_seconds: 60transport:
mode: "remote"remote:
endpoint: "http://100.64.1.100:5170/ingest"# Replace with your receiver IPauth:
enabled: truetoken: "your-generated-secret-token-here"# Generate: openssl rand -base64 32batch_size: 10flush_interval: "5s"retry_attempts: 3retry_delay: "2s"disk:
enabled: truepaths:
- /
- /var
- /var/lib/docker
- /home
- /opttop_n: 5max_depth: 3schedule: "*/10 * * * *"alert:
enabled: truecondition: "size_gb > 50"webhooks:
- discorddmesg:
enabled: trueschedule: "*/1 * * * *"filter_levels:
- err
- crit
- alert
- emergalert:
enabled: truecondition: "level == crit"webhooks:
- discorddocker:
enabled: truecontainers:
- "all"tail_lines: 100schedule: "*/2 * * * *"filter_keywords:
- "error"
- "fatal"
- "panic"
- "OOM"
- "killed"
- "segfault"alert:
enabled: truecondition: "keyword == fatal"webhooks:
- discordwebhooks:
- name: "discord"enabled: trueurl: "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_TOKEN"method: POSTheaders:
Content-Type: "application/json"payload_template: | { "content": "🚨 {{.Title}}", "embeds": [{ "description": "{{.Message}}", "fields": [ {"name": "Host", "value": "{{.Hostname}}", "inline": true}, {"name": "Type", "value": "{{.Type}}", "inline": true}, {"name": "Severity", "value": "{{.Severity}}", "inline": true}, {"name": "Time", "value": "{{.Timestamp}}", "inline": true} ], "color": 16711680 }] }receiver:
enabled: false # Set to true only on receiver serverport: 5170auth:
enabled: truetoken: "your-generated-secret-token-here"# Must match collector tokenlog_output: "/var/log/baadal/events.log"log_rotation:
max_size_mb: 50max_backups: 3max_age_days: 7compress: truedead_mans_switch:
enabled: truetimeout_minutes: 10check_interval: "*/2 * * * *"webhooks:
- discordnode:
hostname: ""# Auto-detectenvironment: "production"tags:
- "ubuntu"
- "web-server"
- "backend"# Run directly
./baadal --mode=collector --config=config.yml
# Run in background
nohup ./baadal --mode=collector --config=config.yml > /dev/null 2>&1&# Check it's running
ps aux | grep baadal# Run directly
./baadal --mode=receiver --config=config.yml
# Run in background
nohup ./baadal --mode=receiver --config=config.yml > /dev/null 2>&1&# On collector servers
sudo bash install.sh collector
# On receiver server
sudo bash install.sh receiver
# Service management
sudo systemctl start baadal
sudo systemctl enable baadal # Start on boot
sudo systemctl status baadal
sudo journalctl -u baadal -f # Follow logs# Reload configuration without restart
sudo systemctl kill -s HUP baadal
# Restart service
sudo systemctl restart baadal
# Stop service
sudo systemctl stop baadalBaadal supports reloading configuration without restart:
# If running via systemd
sudo systemctl kill -s HUP baadal
# If running manually (get PID first)
ps aux | grep baadal
kill -HUP <PID>What gets reloaded:
- ✅ Schedule intervals
- ✅ Alert thresholds
- ✅ Webhook configurations
- ✅ Filter keywords
- ✅ Paths to monitor
- ❌ Mode (collector/receiver) - requires restart
# Pull from GitHub Container Registry
docker pull ghcr.io/YOUR_USERNAME/baadhal:latest
# Run collector
docker run -d \
--name baadal-collector \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v $(pwd)/config.yml:/app/config.yml:ro \
-e MODE=collector \
--restart unless-stopped \
ghcr.io/YOUR_USERNAME/baadhal:latest
# Run receiver
docker run -d \
--name baadal-receiver \
-p 5170:5170 \
-v $(pwd)/config.yml:/app/config.yml:ro \
-v baadal-logs:/var/log/baadal \
-e MODE=receiver \
--restart unless-stopped \
ghcr.io/YOUR_USERNAME/baadhal:latest
# View logs
docker logs -f baadal-collector
docker logs -f baadal-receiver
# Reload config
docker kill -s HUP baadal-collectorversion: '3.8'services:
# Receiver (central monitoring server)baadal-receiver:
image: ghcr.io/YOUR_USERNAME/baadhal:latestcontainer_name: baadal-receiverports:
- "5170:5170"volumes:
- ./config.yml:/app/config.yml:ro
- baadal-logs:/var/log/baadalenvironment:
- MODE=receiverrestart: unless-stoppedhealthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:5170/health"]interval: 30stimeout: 3sretries: 3# Collector (on same server or different server)baadal-collector:
image: ghcr.io/YOUR_USERNAME/baadhal:latestcontainer_name: baadal-collectorvolumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config.yml:/app/config.yml:roenvironment:
- MODE=collectorrestart: unless-stoppedvolumes:
baadal-logs:| Type | Description | Data Fields | Triggers |
|---|---|---|---|
disk_usage | Directory size monitoring | top_dirs, scan_root, total_scanned_gb | When scanned |
dmesg | Kernel message monitoring | level, message, kernel_ts | On new kernel messages |
docker_log | Container log monitoring | container, line, matched_keyword | On keyword match |
heartbeat | Periodic health signal | status, uptime_seconds | On schedule |
lifecycle | Start/stop events | event, mode, version, uptime_seconds | On start/stop |
collector_stats | Performance metrics | disk_scan_ms, events_sent, events_deduped, cycle_total_ms | Every 5 min |
dead_mans_switch | Missing host alert | N/A (webhook only) | Receiver detects silence |
Disk Usage Event:
{
"timestamp": "2026-03-06T18:45:00+05:30",
"type": "disk_usage",
"host": "web-server-01",
"environment": "production",
"tags": ["ubuntu", "backend"],
"data": {
"top_dirs": [
{
"path": "/var/lib/docker",
"size_gb": 45.3,
"size_mb": 46387,
"rank": 1
}
],
"scan_root": "/var",
"total_scanned_gb": 67.8
},
"alert_triggered": true,
"alert_condition": "size_gb > 20"
}Docker Log Event:
{
"timestamp": "2026-03-06T18:50:12+05:30",
"type": "docker_log",
"host": "api-server-02",
"environment": "production",
"tags": ["nodejs", "api"],
"data": {
"container": "api-backend",
"line": "Fatal error: Cannot connect to database",
"matched_keyword": "fatal"
},
"alert_triggered": true,
"alert_condition": "keyword == fatal"
}Heartbeat Event:
{
"timestamp": "2026-03-06T18:55:00+05:30",
"type": "heartbeat",
"host": "worker-01",
"environment": "production",
"tags": ["worker", "celery"],
"data": {
"status": "alive",
"uptime_seconds": 86400
},
"alert_triggered": false
}┌─────────────────────────────────────────────────────────────────┐
│ Monitored Servers │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Collector #1 │ │ Collector #2 │ │ Collector #N │ │
│ │ │ │ │ │ │ │
│ │ - Disk scan │ │ - Disk scan │ │ - Disk scan │ │
│ │ - Dmesg │ │ - Dmesg │ │ - Dmesg │ │
│ │ - Docker │ │ - Docker │ │ - Docker │ │
│ │ - Heartbeat │ │ - Heartbeat │ │ - Heartbeat │ │
│ │ - Dedup │ │ - Dedup │ │ - Dedup │ │
│ └───────┬──────┘ └───────┬──────┘ └───────┬──────┘ │
│ │ │ │ │
└──────────┼─────────────────┼──────────────────┼────────────────┘
│ │ │
│ Batched │ Batched │ Batched
│ Events │ Events │ Events
│ (HTTP/JSON) │ (HTTP/JSON) │ (HTTP/JSON)
│ │ │
└─────────────────┼──────────────────┘
│
▼
┌──────────────────────────────┐
│ Central Receiver Server │
│ │
│ - HTTP endpoint (port 5170) │
│ - Authentication │
│ - Log rotation (lumberjack) │
│ - Dead man's switch │
│ - Webhook dispatcher │
└───────────┬──────────────────┘
│
├─────────────┬──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Discord │ │ Slack │ │ Custom │
│ Webhook │ │ Webhook │ │ API │
└──────────┘ └──────────┘ └──────────┘
- Collection: Collectors run scheduled jobs (cron)
- Deduplication: Events checked against recent history
- Batching: Events accumulated until batch_size or flush_interval
- Transport: HTTP POST to receiver with optional auth
- Logging: Receiver writes to rotated log file
- Alerting: Matching conditions trigger webhooks
- Dead Man's Switch: Receiver monitors for missing collectors
Collector (per server):
- CPU: < 1% average
- Memory: ~15-20 MB
- Disk I/O: Minimal (reads only during scans)
- Network: < 1 KB/min average
Receiver:
- CPU: < 1% average
- Memory: ~20-30 MB + log buffer
- Disk I/O: Sequential writes only
- Network: Depends on number of collectors
- Go 1.24+
- Docker (for container log monitoring)
go test ./...
go vet ./...
gofmt -s -l .- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -am 'Add amazing feature') - Push to the branch (
git push origin feature/amazing) - Open a Pull Request
MIT License - see LICENSE file for details.
Built with:
- cron — Cron scheduler
- lumberjack — Log rotation
- Docker SDK — Container monitoring
- yaml.v3 — YAML parsing
- 🐛 Report Issues
- 💬 Discussions
- 📧 Email: your-email@example.com
Made with ☁️ by the Baadal Team