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:
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:
# 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 onlyThe logger is initialized in the Application constructor with the environment setting:
// In src/boot/Application.ts
if (!Env.DISABLE_LOGGING) {
Logger.initialize(undefined, undefined, undefined, Env.LOG_LEVEL);
}Development Example:
# Development: Capture all logs including debug
export LOG_LEVEL=debug
zin startProduction Example:
# Production: Only capture warnings and errors
export LOG_LEVEL=warn
NODE_ENV=production npm startDISABLE_LOGGING
Completely disables the logging system. Use with caution:
# Default: false (logging enabled)
DISABLE_LOGGING=true # Disables all logging
DISABLE_LOGGING=false # Enables loggingWarning: 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:
# View recent logs
zin logs
# Tail logs in real-time
zin logs --follow
# Filter by level
zin logs --level errorError 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:
// ❌ 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:
// 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 recordedWhy This Matters
The safety guarantee ensures that:
- No Silent Failures: Every error path includes logging
- Production Debugging: Error logs are always available when needed
- 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
// 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 appearLog 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:truewhenLOG_TO_FILEistrue, otherwisefalse.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 thelogs/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):
# Run cleanup and print deleted count
zin logs:cleanup- Enable scheduled runs (Node/Fargate):
export LOG_TO_FILE=true
export LOG_CLEANUP_ENABLED=true
export LOG_CLEANUP_INTERVAL_MS=3600000
npm run startNote: On serverless platforms (Cloudflare Workers, Lambda) the scheduler does not start automatically to avoid background timers in ephemeral runtimes.
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:
KV_LOG_ENABLED=false
KV_NAMESPACE=CACHE
KV_LOG_RETENTION_DAYS=30Notes:
KV_NAMESPACEshould 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:
SLACK_LOG_ENABLED=false
SLACK_LOG_WEBHOOK_URL=
SLACK_LOG_LEVELS=warn,error,fatal
SLACK_LOG_BATCH_WINDOW_MS=5000HTTP 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:
HTTP_LOG_ENABLED=false
HTTP_LOG_ENDPOINT_URL=
HTTP_LOG_BATCH_SIZE=50
HTTP_LOG_AUTH_TOKEN=