Skip to content

Logging

ZinTrust features a robust, file-based logging system that helps you monitor your application and debug issues.

Basic Usage

Use the Logger namespace to record information:

typescript
import { Logger } from '@zintrust/core';

Logger.info('User logged in', { userId: 1 });
Logger.error('Database connection failed', { error: err.message });
Logger.debug('Query executed', { sql: query });

Log Levels

ZinTrust supports standard log levels:

  • debug: Detailed information for debugging.
  • info: General application events.
  • warn: Exceptional events that are not errors.
  • error: Runtime errors that require attention.

Environment Configuration

Control logging behavior using environment variables:

LOG_LEVEL

Controls the minimum log level that will be recorded. The logging system uses priority-based filtering:

env
# Default: debug (captures all logs)
LOG_LEVEL=debug    # Captures: debug, info, warn, error
LOG_LEVEL=info     # Captures: info, warn, error
LOG_LEVEL=warn     # Captures: warn, error
LOG_LEVEL=error    # Captures: error only

The logger is initialized in the Application constructor with the environment setting:

typescript
// In src/boot/Application.ts
if (!Env.DISABLE_LOGGING) {
  Logger.initialize(undefined, undefined, undefined, Env.LOG_LEVEL);
}

Development Example:

bash
# Development: Capture all logs including debug
export LOG_LEVEL=debug
zin start

Production Example:

bash
# Production: Only capture warnings and errors
export LOG_LEVEL=warn
NODE_ENV=production npm start

DISABLE_LOGGING

Completely disables the logging system. Use with caution:

env
# Default: false (logging enabled)
DISABLE_LOGGING=true   # Disables all logging
DISABLE_LOGGING=false  # Enables logging

Warning: Disabling logging in production removes the ability to debug production issues. Only disable logging if you have alternative observability systems in place.

Log Files

Logs are stored in the logs/ directory:

  • logs/app/: General application logs.
  • logs/errors/: Error-specific logs.
  • logs/cli/: CLI command execution logs.
  • logs/migrations/: Database migration logs.

Log Rotation

ZinTrust automatically rotates log files daily or when they reach a certain size (default 10MB), keeping your disk space usage under control.

Viewing Logs

You can view and tail logs using the CLI:

bash
# View recent logs
zin logs

# Tail logs in real-time
zin logs --follow

# Filter by level
zin logs --level error

Error Handling

ZinTrust enforces a "Zero-Swallow" safety guarantee: all errors must be logged before being handled or re-thrown.

Required Logger.error() in Catch Blocks

The ESLint rule no-restricted-syntax enforces that every catch block includes a Logger.error() call:

typescript
// ❌ INVALID - ESLint Error
try {
  const { User } = await import('@app/Models/User');
  await User.query().get();
} catch (error) {
  // Missing Logger.error() call!
  return null;
}

// ✅ VALID - Compliant with safety rule
try {
  const { User } = await import('@app/Models/User');
  await User.query().get();
} catch (error) {
  Logger.error('Database query failed', error);
  return null;
}

How Log Level Filtering Works

Important: Logger.error() calls are always required in catch blocks, regardless of LOG_LEVEL setting. The filtering happens inside the Logger, not at the call site:

typescript
// This error WILL BE LOGGED even if LOG_LEVEL=warn
try {
  await connectDatabase();
} catch (error) {
  Logger.error('Database connection failed', error); // Always executes
}

// At runtime:
// - If LOG_LEVEL=error → This error message is recorded
// - If LOG_LEVEL=warn  → This error message is recorded (warn < error priority)
// - If LOG_LEVEL=info  → This error message is recorded
// - If LOG_LEVEL=debug → This error message is recorded

Why This Matters

The safety guarantee ensures that:

  1. No Silent Failures: Every error path includes logging
  2. Production Debugging: Error logs are always available when needed
  3. Consistency: All catch blocks follow the same pattern

You control which errors appear in production logs using LOG_LEVEL, but you cannot prevent an error from being logged through code—only through environment configuration.

Example: Handling and Filtering Errors

typescript
// Source code - always has Logger.error()
async function processPayment(userId: number) {
  try {
    return await paymentGateway.charge(userId);
  } catch (error) {
    Logger.error('Payment processing failed', error); // Always executed
    throw error; // Re-throw after logging
  }
}

// Runtime behavior:
// $ LOG_LEVEL=error   → Only payment errors appear in logs
// $ LOG_LEVEL=info    → Payment errors + info messages appear
// $ LOG_LEVEL=debug   → All details including debug logs appear

Log Cleanup (File retention) 🔧

To prevent logs from growing unbounded on disk, ZinTrust includes a scheduled log cleanup job that will delete old or excess log files based on environment-configured retention rules. The job runs in long-running runtimes (Node.js, Fargate) and can also be invoked on-demand via the CLI command zin logs:cleanup.

Environment Variables

  • LOG_CLEANUP_ENABLED (boolean) — Enable the scheduled cleanup job. Default: true when LOG_TO_FILE is true, otherwise false.
  • LOG_CLEANUP_INTERVAL_MS (number) — Interval in milliseconds between scheduled cleanup runs. Default: 3600000 (1 hour).
  • LOG_MAX_TOTAL_SIZE (number) — Maximum total size in bytes allowed for the logs/ directory. Files are removed until total size is under this threshold. Default: unset (no size-based removal by default).
  • LOG_KEEP_FILES (number) — Minimum number of recent log files to keep regardless of size or age. Default: 0.

Usage

  • One-off cleanup (useful for CI or maintenance):
bash
# Run cleanup and print deleted count
zin logs:cleanup
  • Enable scheduled runs (Node/Fargate):
bash
export LOG_TO_FILE=true
export LOG_CLEANUP_ENABLED=true
export LOG_CLEANUP_INTERVAL_MS=3600000

npm run start

Note: On serverless platforms (Cloudflare Workers, Lambda) the scheduler does not start automatically to avoid background timers in ephemeral runtimes.

See scheduling.md for the schedule system, and zin schedule:list / zin schedule:run for manual triggering.

Cloud Logging Backends

ZinTrust can optionally forward logs to cloud backends in addition to console/file output. These backends are best-effort and designed to be non-blocking.

KV Logger (Cloudflare KV)

Writes batched error/fatal events into a KV namespace. This is useful in Cloudflare Workers where file logging is not available.

Environment variables:

env
KV_LOG_ENABLED=false
KV_NAMESPACE=CACHE
KV_LOG_RETENTION_DAYS=30

Notes:

  • KV_NAMESPACE should match the Workers binding name you configured.
  • Retention is applied via KV expiration (TTL).

Slack Notification Logger

Sends warn/error/fatal events to a Slack incoming webhook (batched to avoid spamming).

Environment variables:

env
SLACK_LOG_ENABLED=false
SLACK_LOG_WEBHOOK_URL=
SLACK_LOG_LEVELS=warn,error,fatal
SLACK_LOG_BATCH_WINDOW_MS=5000

HTTP Endpoint Logger

Sends logs to an external HTTP endpoint (for Loggly/Papertrail/Datadog/custom ingestion). This is the supported integration path when you don’t have a dedicated provider-specific driver.

Environment variables:

env
HTTP_LOG_ENABLED=false
HTTP_LOG_ENDPOINT_URL=
HTTP_LOG_BATCH_SIZE=50
HTTP_LOG_AUTH_TOKEN=

Released under the MIT License.