Kahibaro
Discord Login Register

Creating custom logs

Why Create Custom Logs?

System logs and audit logs cover a lot, but they don’t know about:

Custom logs let you:

This chapter focuses on how to create and manage custom logs in a Linux environment, and how to hook them into the existing logging stack.


Designing Your Custom Logs

Before writing any code, decide:

What to log

Typical categories:

Avoid:

Log levels

Stay consistent with common levels:

Decide which levels are used where, and stick to them.

Log format

Common choices:

  1. Plain text (human-friendly)
    Example:
    2025-01-01T12:00:00Z INFO user=alice action=login result=success
  2. Structured text (machine-friendly)
    • Key-value pairs: time=... level=INFO user=alice action=login
    • JSON: {"time":"...","level":"INFO","user":"alice","action":"login"}

If you plan to use centralized logging and searching, structured logs (especially JSON) are much easier to parse.


Basic Logging from Shell Scripts

For scripts, you usually have three goals:

Simple file-based logging

#!/usr/bin/env bash
LOG_FILE="/var/log/myapp/backup.log"
# Ensure directory exists
mkdir -p "$(dirname "$LOG_FILE")"
# Optionally restrict permissions
chmod 750 "$(dirname "$LOG_FILE")"
log() {
    local level="$1"; shift
    local msg="$*"
    # ISO 8601 timestamp
    local ts
    ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
    printf "%s [%s] %s\n" "$ts" "$level" "$msg" >> "$LOG_FILE"
}
log INFO "Backup job started"
if rsync -a /data/ /backup/; then
    log INFO "Backup completed successfully"
else
    log ERROR "Backup FAILED with exit code $?"
fi

Key points:

Logging to syslog from a script

Using the logger command:

#!/usr/bin/env bash
APP_NAME="my-backup"
log() {
    local level="$1"; shift
    local msg="$*"
    logger -t "$APP_NAME" -p "user.$(echo "$level" | tr '[:upper:]' '[:lower:]')" "$msg"
}
log INFO "Backup started"
# ...
log ERR "Backup failed: $reason"

Notes:

You can then view them with:

Custom Application Logs with syslog/journald

If your application runs as a service, integrating with syslog/journald is often better than writing random files under /var/log.

Sending logs to syslog directly (C-style API concept)

Many languages have libraries that wrap the system syslog(3) API. The pattern is:

  1. Open syslog with an identifier
  2. Log messages with a level
  3. Close when done (optional)

Conceptual flow:

In higher-level languages (Python, Go, etc.), you use built-in logging libraries that support syslog handlers/transports.

Journald-native logging

Systemd-aware applications can log directly to journald using:

Once logs are in the journal, you can:

Defining Log Locations and Permissions

Custom logs usually live under /var/log:

Key considerations:

Directory creation and ownership

For a service user myapp:

# As root (e.g. in install script or package post-install)
install -d -m 750 -o myapp -g myapp /var/log/myapp

This ensures:

File permissions

When you create log files manually, set permissions explicitly:

touch /var/log/myapp/app.log
chown myapp:myapp /var/log/myapp/app.log
chmod 640 /var/log/myapp/app.log

If your application creates the file, make sure its process runs as myapp and sets a safe umask (e.g. umask 027).


logrotate for Custom Logs

To avoid huge, unmanageable files, integrate your logs with logrotate.

Basic logrotate config for a custom log file

Create /etc/logrotate.d/myapp:

/var/log/myapp/app.log {
    weekly
    rotate 12
    compress
    delaycompress
    missingok
    notifempty
    create 640 myapp myapp
    postrotate
        # Reload or signal your daemon if needed
        systemctl kill -s HUP myapp.service 2>/dev/null || true
    endscript
}

Meaning:

Make sure your application handles SIGHUP or uses reopen-on-demand patterns if it keeps the log file open.


Custom Log Fields and Correlation

To make logs useful for debugging and incident analysis:

Use correlation IDs

Generate a unique ID per request/job/workflow and include it in all log entries related to that unit of work:

Example log line:

2025-01-01T12:00:30Z INFO correlation_id=... user=alice action=create_order order_id=42

This allows you to filter logs by correlation ID and see the full chain of events.

Include context

Beyond timestamp and level, useful fields include:

Use consistent names to make searching easier.


Application-Level Logging Patterns

Separating logs by concern

Common patterns:

You can:

Log verbosity control

Provide configuration for:

Common approaches:

Custom Logs in systemd Service Units

Systemd can manage where your logs go, especially for services you run.

Logging to journald via stdout/stderr

If your service writes logs to standard output/error, systemd captures them:

Unit example /etc/systemd/system/myapp.service:

[Unit]
Description=My Custom Application
[Service]
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp-binary
Restart=on-failure
# Optional tuning
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

Then read logs with:

This removes the need for manual file handling and lets you centralize logs easily.

Redirecting to a dedicated file from systemd

If you prefer files:

[Service]
User=myapp
Group=myapp
ExecStart=/opt/myapp/myapp-binary
StandardOutput=append:/var/log/myapp/app.log
StandardError=append:/var/log/myapp/app-error.log

Systemd creates and appends to these files; combine this with logrotate to manage size.


Integrating Custom Logs with Centralized Logging

Once you have custom logs, you often want them in:

Common integration patterns:

For structured logs, define a consistent schema (field names and types) to make dashboards and alerts easier to build.


Security Considerations for Custom Logs

When designing custom logs:

Testing and Validating Custom Logs

Before relying on your logging in production:

  1. Trigger known events
    • Run test actions and ensure they appear as expected.
  2. Check timestamps and time zones
    • Verify order and correlation with other logs.
  3. Check rotation
    • Force rotation:
      • logrotate -f /etc/logrotate.d/myapp
    • Ensure the application continues logging after rotation.
  4. Searchability
    • Try typical queries you’d do during an incident:
      • By user, by action, by correlation ID, by error code.
  5. Performance impact
    • Heavy synchronous logging can slow down applications.
    • Consider:
      • Asynchronous logging
      • Buffered writes
      • Reduced log level in hot paths

By designing, implementing, and integrating custom logs carefully, you ensure that your Linux systems and applications are observable, diagnosable, and compatible with your broader logging and auditing strategy.

Views: 24

Comments

Please login to add a comment.

Don't have an account? Register now!