@egi/smart-log
v1.0.0
Published
Smart logging library with severity levels, flexible formatting, and optional DB persistence
Maintainers
Readme
smart-log
A TypeScript logging library with severity levels, flexible formatting, stack trace integration, and optional persistence via a pluggable db writer.
Installation
npm install @egi/smart-logQuick Start
import { smartLog, SmartSeverityLevel } from "@egi/smart-log";
smartLog.info("Application started");
smartLog.warning("Low disk space");
smartLog.error(new Error("Something went wrong"));A singleton instance smartLog is exported for convenience. Create additional instances as needed:
import { SmartLog } from "@egi/smart-log";
const log = new SmartLog({ logLevel: SmartSeverityLevel.Debug });
log.debug("detailed trace");Severity Levels
enum SmartSeverityLevel {
None = 0, Fatal = 1, Error = 2, Warning = 3,
Info = 4, Verbose = 5, Debug = 6, All = 9
}Methods: fatal(), error(), warning(), info(), verbose(), debug(), write() (no severity).
Each method accepts a string, an Error, or a string + SmartMessageOptions:
log.error("fetch failed", { data: err, location: "api.ts:42" });
log.info("user logged in", { type: "BACKEND", timestamp: new Date() });
log.debug("internal detail", { skipConsole: true }); // db writer only
log.info("console only", { skipDatabase: true }); // console onlyOptions
const log = new SmartLog({
logLevel: SmartSeverityLevel.Info, // minimum level to process
logChannels: true, // route to console.error/warn/info/debug by level
location: true, // include caller location in output
leading: "[APP]", // prefix every line
separator: " | ", // separator between format elements
lowerCase: false, // lowercase severity codes
user: "admin", // user id stamped on each log entry
dbWriter: myWriter, // persist entries (see below)
outputHook: (text, msg) => {}, // side-effect hook; return { suppress: true } to skip console
formatHook: (text, msg) => text, // transform output text before console
stackProvider: () => new Error(), // custom stack source for caller detection
});Log Format
The output format is fully configurable via sequence. Elements can be enum values, fixed strings, or functions:
import { SmartLog, SmartLogFormatElement } from "@egi/smart-log";
const log = new SmartLog({
leading: "%",
lowerCase: true,
location: true,
sequence: [
SmartLogFormatElement.Severity,
"myapp",
SmartLogFormatElement.Timestamp,
SmartLogFormatElement.Message,
SmartLogFormatElement.Location,
() => process.pid.toString()
]
});| Element | Output |
|---|---|
| Severity | Single letter code: F E W I I D |
| Type | First letter of the location type (App → A) |
| Timestamp | 2024-03-15 14:30:00.000 |
| Message | The log message text |
| Location | [file.ts:42 (functionName)] |
Default sequence: Severity - Type - Timestamp: Message [Location]
Output Hook
outputHook is called after formatting and before console output. Use it for side effects — writing to a file, sending to a remote service, emitting events — without needing to implement a full ISmartLogDbWriter.
Return false to prevent the entry from appearing on the console. Both sync and async hooks are supported.
import { SmartLog, LogMessage } from "@egi/smart-log";
const log = new SmartLog({
outputHook: (text: string, message: LogMessage) => {
fs.appendFileSync("app.log", text + "\n");
// return false to hide from console as well
}
});
// or set it later:
log.setOutputHook(async (text, message) => {
await sendToSlack(text);
return false; // already sent, no need to also print
});
// transform text only:
log.setFormatHook((text) => `[MyApp] ${text}`);formatHook and outputHook serve different purposes:
| Hook | Purpose | Must return |
|---|---|---|
| formatHook | Transform the formatted text | Modified string |
| outputHook | Side effects / suppress console | void or false |
Database Persistence
Implement ISmartLogDbWriter to persist log entries:
import { ISmartLogDbWriter, LogMessage } from "@egi/smart-log";
class MyDbWriter implements ISmartLogDbWriter {
write(entry: LogMessage): Promise<void> | void {
// entry contains: severityLevel, type, location, message, data, timestamp, user
return db.insert("logs", entry);
}
}
const log = new SmartLog({ dbWriter: new MyDbWriter() });
// change or disable the writer at runtime:
log.setDbWriter(null);The writer receives the raw LogMessage object — sync or async writers are both supported.
Location Types
enum SmartLocation {
App = "APP",
Frontend = "FRONTEND",
Backend = "BACKEND",
Database = "DATABASE",
UpgradeManager = "UPGRADE-MANAGER"
}Date Utilities
import { toSmartDbDate, toSmartDbTimestamp, smartDbToDate, smartDbToDateTime } from "@egi/smart-log";
toSmartDbDate(new Date()) // "2024-03-15 14:30:00"
toSmartDbTimestamp(new Date()) // "2024-03-15 14:30:00.000"
smartDbToDate("2024-03-15 14:30:00") // Date object
smartDbToDateTime(1710508200000) // Luxon DateTime objectSmartError
A structured error class for use throughout the stack:
import { SmartError, SmartSeverityLevel, SmartLocation } from "@egi/smart-log";
throw new SmartError({
message: "Record not found",
code: 404,
type: SmartSeverityLevel.Error,
location: SmartLocation.Backend
});SmartTools
Utility singleton for string conversions and stack inspection:
import { tools } from "@egi/smart-log";
tools.camelCase("my_field_name") // "myFieldName"
tools.snakeCase("myFieldName") // "my_field_name"
tools.kebabCase("MyComponent") // "my-component"
tools.pascalCase("my_model") // "MyModel"
tools.getCallerFromStack() // "src/app.ts:42 (doSomething)"