Logging

Control what the ORM reports and where it goes.
Configuration is the third argument to the Stabilize constructor.

Configuration

db.ts
import { Stabilize, LogLevel } from "stabilize-orm";
import type { DBConfig, CacheConfig, LoggerConfig } from "stabilize-orm";
const dbConfig: DBConfig = {
type: DBType.SQLite,
connectionString: "./app.db",
};
const cacheConfig: CacheConfig = { enabled: false, ttl: 60 };
const loggerConfig: LoggerConfig = {
level: LogLevel.Debug,
filePath: "logs/stabilize.log",
maxFileSize: 5 * 1024 * 1024, // 5MB
maxFiles: 3,
};
const orm = new Stabilize(dbConfig, cacheConfig, loggerConfig);

Log Levels

Levels are ordered by severity, and the setting is a maximum: a message is written when its level is at or below the configured one. Set Debug to see everything, Error to see only failures.

levels.ts
LogLevel.Debug // 0 - everything, including every query
LogLevel.Info // 1 - default: normal operation
LogLevel.Warn // 2 - warnings and errors
LogLevel.Error // 3 - failures only
// level: LogLevel.Warn => Warn and Error are written, Debug and Info are not

Defaults

typescript
level LogLevel.Info
filePath null // console only
maxFileSize 1 * 1024 * 1024 // 1MB
maxFiles 3

File Output & Rotation

Logging goes to the console unless you set filePath. Once the file reaches maxFileSize it is rotated — the current file becomes .1, existing rotations shift up, and the oldest is deleted once there are maxFiles of them. With the defaults that is a hard ceiling of about 4MB on disk:

rotation.txt
logs/stabilize.log <- current
logs/stabilize.log.1 <- previous
logs/stabilize.log.2 <- oldest kept
<- .3 deleted on next rotation

What Gets Logged

methods.ts
logQuery(query: string, params: any[], executionTime?: number): void
logError(error: Error): void
logMetrics(metrics: PoolMetrics): void
logInfo(message: string): void
logWarn(message: string): void
logDebug(message: string): void

PoolMetrics is { activeConnections, idleConnections, totalConnections }.

Writing to the File Is Not Awaited

The public log methods write asynchronously and return void immediately — a query is never delayed by a log write. The trade-off is that a write still in flight when the process exits is lost, so do not rely on the file containing the very last line before a crash:

exit.ts
import { StabilizeLogger, LogLevel } from "stabilize-orm";
// Stabilize keeps its logger private, so it is not reachable as
// `orm.logger`. Build one with the same config to write through the
// same sink.
const logger = new StabilizeLogger({
level: LogLevel.Info,
filePath: "logs/stabilize.log",
});
logger.logInfo("shutting down");
// The write above may not have reached disk yet.
// Give it a moment before exiting if the line matters.
await new Promise((resolve) => setTimeout(resolve, 50));
process.exit(0);

Query logging is loud

LogLevel.Debug logs every statement. That is what you want while diagnosing a slow endpoint, and a serious throughput cost in production — the formatting alone can dominate a fast query. Leave production at Info or higher.