@spinajs/log-common
v2.0.487
Published
Log lib for all spinejs related libs
Downloads
8,529
Readme
@spinajs/log-common
Shared, dependency-light contracts for the SpinaJS logging stack. This package
holds no logging implementation of its own; it defines the abstract types that
@spinajs/log, @spinajs/internal-logger and the various log-source packages
implement. Depend on it when you write a custom log target or a custom
Log implementation, and want to avoid a circular dependency on @spinajs/log.
What lives here
| Export | Purpose |
| --- | --- |
| Log (abstract) | The logger contract: trace/debug/info/warn/error/fatal/security/success, child, write, addVariable, timeStart/timeEnd. |
| LogTarget<T> (abstract) | A sink that receives ILogEntry objects and writes them somewhere ( console, file, HTTP, ... ). |
| createLogMessageObject | Builds a normalized ILogEntry from the many call shapes the Log methods accept. |
| LogLevel / StrToLogLevel / LogLevelStrings | Level enum and string<->enum maps. |
| ILogEntry, ILogRule, ICommonTargetOptions, IFileTargetOptions, ILogOptions | Config and payload shapes. |
The LogTarget contract
abstract class LogTarget<T extends ICommonTargetOptions> extends SyncService {
public HasError: boolean; // true after a failed write, cleared on the next success
public Error: Error | null | unknown; // the last write error, or null
public Options: T; // merged options ( includes the default layout )
public abstract write(data: ILogEntry): void;
}A target receives fully-formed ILogEntry objects. It is responsible for:
- honouring
Options.enabled( skip whenfalse), - rendering
data.Variablesthrough itsOptions.layout, - setting
HasError = true/Error = errwhen a write fails and clearing them (HasError = false,Error = null) on the next successful write. Consumers can poll these fields to detect a degraded sink.
createLogMessageObject
createLogMessageObject(
err: Error | string,
message: string | any[],
level: LogLevel,
logger: string,
variables: any,
...args: any[]
): ILogEntryIt normalizes the two calling conventions the Log methods accept:
- Message overload —
erris the format string ( orundefined) andmessagecarries the format arguments, e.g.log.info("hello %s", "world"). - Error overload —
erris anErrorandmessageis the human message, e.g.log.error(err, "could not connect").
Rules it applies:
sMsg = (err instanceof Error || !err) ? message : err— anerrstring is itself the message body, so a barelog.info("hi")works.tMsg = args.length ? format(sMsg, ...args) : sMsg— runsutil.format-style substitution ( seeformat.ts;%s %d %i %f %j %o %O %%) only when there are args.Variables.erroris set only for theErroroverload.Variables.logger = logger ?? messageandVariables.levelis the upper-cased level string.
The returned entry is:
{
Level: LogLevel,
Variables: {
error, // Error | undefined
level, // "INFO" | "ERROR" | ...
logger, // logger name
message, // formatted message
...variables
}
}Layout variables
A target's layout is a template string resolved by @spinajs/configuration's
format(variables, layout). Every key on ILogEntry.Variables is available as
${key}. The always-present variables are:
| Variable | Value |
| --- | --- |
| ${datetime} | timestamp of the entry |
| ${level} | upper-cased level, e.g. INFO |
| ${message} | the formatted message |
| ${error} | the Error ( use ${error:message} for its message ) |
| ${logger} | the logger name |
Conditional blocks are supported, e.g. ${?error} ... ${/error} only renders
when error is set. Any custom variable you attach via log.addVariable(name, value)
or the config variables array is also available as ${name}.
The default layout ( applied to every target unless overridden ) is:
${datetime} ${level} ${message}${?error} Exception: ${error:message}${/error} (${logger})Writing a custom target
import { Injectable } from "@spinajs/di";
import { format } from "@spinajs/configuration";
import { LogTarget, ILogEntry, ICommonTargetOptions } from "@spinajs/log-common";
@Injectable("MyTarget") // referenced by `type: "MyTarget"` in config
export class MyTarget extends LogTarget<ICommonTargetOptions> {
public write(data: ILogEntry): void {
if (!this.Options.enabled) return;
try {
// render with the configured layout and send it somewhere
send(format(data.Variables, this.Options.layout));
this.HasError = false;
this.Error = null;
} catch (err) {
this.HasError = true;
this.Error = err;
}
}
}See @spinajs/log for the concrete targets and the rules/targets configuration.
