v0.21

logging and errors

introduction

dframework provides a dual channel logging system that writes to both the console and persistent log files. it includes an error handler that renders error pages, classifies stack traces by component type, maps compiled view errors back to their original template lines, and provides diagnostic tips for common mistakes.

the logger

log levels

the logger supports six log levels, each with its own color coding and behavior.

level color purpose
debug cyan development only messages, suppressed unless debug mode is enabled
info blue general informational messages
hot orange hot reload events during local development
warn yellow non critical warnings
error red errors and exceptions
table magenta structured tabular data output

the minimum log level is determined by whether debug mode is enabled. when app.debug is true, all levels including debug are output. when debug is disabled, debug messages are suppressed.

writing log messages

each log level has a corresponding method accessible via the global Log facade or named import (import { Log } from 'dframework'). all methods accept variadic arguments that are automatically formatted.

1import { Log } from 'dframework';
2
3Log.debug('cache miss for key:', cacheKey);
4Log.info('user registered:', user.email);
5Log.warn('rate limit approaching for ip:', clientIp);
6Log.error('payment failed:', error);

the logger formats different argument types. strings are output as is, Error objects display their full stack trace, promises display as Promise { <pending> }, and objects are pretty printed with a depth of 3 and color support in the local environment.

table logging

the Log.table() method renders an array of objects as a formatted ascii table with box drawing characters.

1app.logger.table([
2 { name: 'users', rows: 1250, size: '2.4 MB' },
3 { name: 'posts', rows: 8340, size: '15.1 MB' },
4 { name: 'sessions', rows: 89, size: '0.1 MB' }
5], 'database overview');
1database overview
2┌─────────┬──────┬─────────┐
3│ name │ rows │ size │
4├─────────┼──────┼─────────┤
5│ users │ 1250 │ 2.4 MB │
6│ posts │ 8340 │ 15.1 MB │
7│ sessions│ 89 │ 0.1 MB │
8└─────────┴──────┴─────────┘

log output

console output

in the local environment, all log messages are output to the console with ansi color coding. error and warning messages use console.error to separate them from standard output.

in the production environment, colors are stripped and only warn and error messages go to console.error. all other levels use console.log.

file output

every log message is simultaneously written to a persistent log file. log files are stored in the logs directory at the root of your project, separated by environment.

1logs/
2├── dev/
3│ ├── dframework_2026-06-04.log
4│ └── dframework_2026-06-05.log
5└── prod/
6 ├── dframework_2026-06-04.log
7 └── dframework_2026-06-05.log

the local environment writes to logs/dev/ and production writes to logs/prod/. ansi color codes are automatically stripped from file output.

log file rotation and retention

file logging uses a dedicated background worker thread communicating over a lock free atomic ring buffer. log formatting and encoding execute without blocking the main event loop, preserving strict sequential order while isolating all disk io.

log files are rotated daily at midnight. each file is named with the date (dframework_YYYY-MM-DD.log). when the date changes, the background worker closes the previous file descriptor and opens the new daily file descriptor automatically.

the framework does not automatically delete older log files. retention cleanup is intentionally delegated to the application level via scheduled commands or cron jobs, allowing teams to determine their own retention and compliance policies.

you can clear or prune older log files using the cli or schedule it in a task:

1dstrn logs:clear
2dstrn logs:clear --env=prod
3dstrn logs:clear --before=2026-01-01
4dstrn logs:clear --after=2026-05-01 --archive
5dstrn logs:clear --preview

debug bar integration

in the local environment with debug mode enabled, log messages and performance telemetry are automatically captured by the request context and included in the debug bar response. each log entry records its level, message (with colors stripped), and timestamp.

query profiling and n+1 detection

the debug bar tracks every database query executed during the request lifecycle, measuring execution latency and highlighting repeated queries.

when three or more queries with identical normalized shapes execute in a single request, the debug bar displays an indicator badge. clicking the badge opens a diagnostic modal displaying:

configuration

the logger reads its configuration from the application config.

config key effect
app.env determines the log file directory (dev vs prod) and console color mode
app.debug when true, enables the debug log level and activates the debug error page
1// config/app.js
2export default {
3 env: 'local',
4 debug: true
5};

the error handler

the ErrorHandler class manages error rendering and logging throughout the application. it is instantiated during app boot and caches all error page templates for instant rendering.

error pages

dframework includes built in error page templates for 404 and 500 (along with debug in local development). each page uses the framework's view template syntax and displays a styled error screen to the user.

when an error occurs, the error handler selects the appropriate template based on the status code. if no view template exists for the specific code, the error handler sends a plain text ${status} Error response.

custom error pages

you can override any built in error page by placing a file with the same name in your views/errors directory. user error pages take priority over the framework defaults.

1views/errors/
2├── 404.d
3├── 500.d
4└── 503.d

your custom error pages have access to the {{ status }} placeholder which is replaced with the numeric status code.

debug error page

when app.debug is true and the error is not a 404, the framework renders a detailed debug error page instead of the production error page. the debug page displays:

this page is designed for development only and is never shown in the production environment.

error tips

the error handler includes a pattern matching system that recognizes common error messages and provides diagnostic tips. when an error is logged, the handler checks the message against a list of known patterns.

error pattern tip
Unexpected reserved word check for missing async keyword before method definitions
Cannot read properties of undefined verify object exists before accessing properties
is not a function verify the method exists and is properly imported
Cannot find module check import path and ensure file exists
await is only valid in async add async keyword to the function declaration
EADDRINUSE port is already in use, stop other processes or use a different port
ER_NO_SUCH_TABLE run migrations to create the database table
ER_BAD_FIELD_ERROR column does not exist in table, check schema or migration
ER_DUP_ENTRY duplicate value for unique constraint, check data or schema

tips are displayed in cyan below the error message in the console output.

1[Socket] Template rendering failed: Cannot read properties of undefined (reading 'name')
2tip: verify object exists before accessing properties
3 ▸ [controller] UserController controllers/UserController.js:42
4 ▸ [view] home views/home.d:15

stack trace classification

the error handler transforms raw stack traces into classified, color coded frames that highlight the most relevant parts of the trace.

frame categories

each stack frame is classified into a category based on its file path.

category color matched path
controller yellow /controllers/
middleware blue /middlewares/
model green /models/
view magenta view:///
route accent /routes/
job cyan /jobs/
command cyan /console/
config orange /config/
migration white /migrations/
seeder white /seeders/
app white anything within the project root

frames from node_modules and the framework's core directory are automatically filtered out. only your application code is shown in the trace.

1 ▸ [controller] register controllers/AuthController.js:28
2 ▸ [model] create models/User.js:15
3 ▸ [view] auth.register views/auth/register.d:42

view line mapping

when an error originates from a compiled view template, the error handler maps the compiled javascript line number back to the original line in the .d template file. this is done using the line map generated during view compilation, ensuring that the stack trace points to the exact line in your template that caused the error rather than the generated code.

hot reload path resolution

in the local environment, the framework uses cache busted file paths (.hot-*) for hot reloading. the error handler resolves these back to the original file paths in the stack trace, so you always see clean, recognizable paths.