-
Notifications
You must be signed in to change notification settings - Fork 0
Logging and Debug
InitORM\Database exposes two complementary observability features:
| Feature | What it captures | Configured via |
|---|---|---|
| Failure log | Per-failure messages — SQL + (optionally) bound parameters |
log + debug credentials |
| Query profiler | Every executed query with timing and arguments |
enableQueryLog() / disableQueryLog()
|
This page covers the failure log. For the profiler, see Query Profiler.
The log key accepts a file path, a callable, or any object with a critical(string) method.
DB::createImmutable([
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'log' => __DIR__ . '/var/log/db.log',
]);The Logger writes via file_put_contents() with append mode. The path may contain {year} / {month} / {day} placeholders — they're replaced at write time, so daily-rotated logs work out of the box:
'log' => __DIR__ . '/var/log/db-{year}-{month}-{day}.log',
// → var/log/db-2026-05-24.logAny callable that accepts a single string works:
DB::createImmutable([
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'log' => function (string $message): void {
error_log($message);
},
]);[$object, 'method'] arrays count as callables too — perfect for adapting third-party loggers:
$monolog = new \Monolog\Logger('db');
$monolog->pushHandler(new \Monolog\Handler\StreamHandler('php://stderr'));
DB::createImmutable([
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'log' => [$monolog, 'critical'],
]);Any object that exposes a critical(string $message) method is accepted. This is the contract \Psr\Log\LoggerInterface already satisfies, so you can pass a PSR-3 logger directly:
DB::createImmutable([
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'log' => $psr3Logger, // any PSR-3 LoggerInterface
]);If your logger uses a different method name, wrap it in a closure:
'log' => fn (string $msg) => $myLogger->error($msg),Only query failures. Successful queries do not produce log entries — that's what the Query Profiler is for. The two systems are independent.
A failure log message looks like:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'app.usrs' doesn't exist
SQL : SELECT id, name FROM usrs WHERE active = :active
When debug: true, the failure message is augmented with the bound parameters (JSON-encoded):
DB::createImmutable([
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'debug' => true,
]);Then the same failure logs as:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'app.usrs' doesn't exist
SQL : SELECT id, name FROM usrs WHERE active = :active
PARAMS : {":active":1}
⚠ Enable
debugin development only. Parameter dumps include user-supplied values — possibly credentials, emails, PII. Treat them as sensitive.
The two settings compose freely:
DB::createImmutable([
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'log' => $psr3Logger,
'debug' => true,
]);That gives you full failure messages (with params) routed through your PSR-3 pipeline.
A complete production-style setup:
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
$logger = new Logger('db');
$logger->pushHandler(new RotatingFileHandler(__DIR__ . '/var/log/db.log', 14, Logger::WARNING));
$logger->pushHandler(new StreamHandler('php://stderr', Logger::ERROR));
DB::createImmutable([
'dsn' => $_ENV['DB_DSN'],
'username' => $_ENV['DB_USER'],
'password' => $_ENV['DB_PASS'],
'log' => $logger,
'debug' => $_ENV['APP_ENV'] === 'dev',
]);For per-message structured logging (e.g. correlating with request IDs), use a closure:
$requestId = bin2hex(random_bytes(8));
DB::createImmutable([
'dsn' => $_ENV['DB_DSN'],
'log' => function (string $msg) use ($requestId, $logger): void {
$logger->critical($msg, ['request_id' => $requestId]);
},
]);The Logger is initialised once from the credentials. To change it mid-flight (rare), reach into the underlying Connection:
$db->getConnection()->createLog('manual entry');…but typically you wire the right sink at boot and forget about it.
- Query Profiler — for "what queries did I just run?" rather than "what failed?"
- Configuration — every credential
- FAQ — "how do I integrate with X logger?"
InitORM Database · MIT · maintained by Muhammet ŞAFAK · part of the InitORM stack
Getting Started
Core Operations
Cross-Cutting
Reference
Upgrading
Project