# Typescript Logging Node Channel This channel can be used for node and provides support for log files and rollover of files. The channel is new since 2.2.0 (feedback is welcome). ## Getting started Before the channel can be used, you should first install typescript-logging and a style. For example: ```shell npm install --save typescript-logging # Core is always required npm install --save typescript-logging-category-style # One style is required ``` For more details about the logging library and/or flavors, please see: [typescript-logging](../README.md). With the logging library installed, you can then install this node channel: ```shell npm install --save typescript-logging-node-channel ``` The node channel is a custom channel which can be configured for typescript-logging library (again please look in the documentation of the main logging library for details). The following example defines a log configuration to be used for node, that configures and uses the node LogChannel. ```typescript // LogConfig.ts import {LogLevel} from "typescript-logging"; import {Category, CategoryProvider} from "typescript-logging-category-style"; import {NodeChannelProvider} from "typescript-logging-node-channel"; // Create the node channel, which writes the log files to a dist/log directory. Uses default settings. const channel = NodeChannelProvider.createLogChannel( NodeChannelProvider.createRetentionStrategyMaxFiles({ directory: "dist/log" }) ); // Create a provider const provider = CategoryProvider.createProvider("TestProvider", { level: LogLevel.Info, channel }); // Export function which creates a logger with given name export function getLogger(name: string): Category { return provider.getCategory(name); } ``` The following node-express example gets a new logger, and logs for two end points. ```typescript // app.ts (node-express example) import express, {Express, Request, Response} from "express"; import {getLogger} from "./config/LogConfig.js"; const app: Express = express(); const port = process.env.PORT || 3000; const log = getLogger("app.ts"); app.get("/", (req: Request, res: Response) => { log.info(() => "This is a logging message for / endpoint"); res.send("Some nice response"); }); app.get("/test", (req: Request, res: Response) => { log.info(() => "This is a logging message for /test endpoint"); res.send(`Write a response`); }); app.listen(port, () => { console.log(`[server]: Server is running at http://localhost:${port}`); }); ``` ## Configuration There are two node channels available: - LogChannel, can be created using `NodeChannelProvider.createLogChannel(..)` - RawLogChannel, can be created using `NodeChannelProvider.createRawLogChannel(..)` LogChannel uses a pre-defined way of how log messages are written. RawLogChannel instead allows full customization of the log message. For details on channels please see the main documentation of [typescript-logging](../README.md). The created channel must be passed along to the log provider you originally picked (CategoryServiceProvider in the example here). ### RetentionStrategy When creating a node channel you must pass along a `RetentionStrategy`. The channel ships with one out of the box which can be created using: `NodeChannelProvider.createRetentionStrategyMaxFiles(..)`. The RetentionStrategy determines where to log files, the naming, the size and rollover of files. The following shows the options available (from source): ```typescript /** * Specifies the retention options to use when logging to files. Only directory is required, the others have sane * defaults but can be set differently if needed. See respective properties for details. * * Defaults to: maximum 10 files, 1 file maximum size of 10 MegaBytes, encoding utf-8, namePrefix: application, extension: .log . * * Default logs to: [directory]/[namePrefix][number][extension] (e.g. application1.log, application2.log etc. based on defaults). */ export interface RetentionStrategyMaxFilesOptions { /** * Directory to write the log files in, if it does not exist an attempt is made to create the path. If that fails * the logging will bail out with an Error as logging would be impossible. */ readonly directory: string; /** * The encoding to use to read/write log files, default is utf-8. */ readonly encoding?: BufferEncoding; /** * The prefix name for a file, the default is 'application' */ readonly namePrefix?: string; /** * The extension of the file, the default is '.log' */ readonly extension?: string; /** * The maximum size of a file, defaults to 10 MB (MegaBytes). When full (or the next written log line does not fit) rolls over to the next file. */ readonly maxFileSize?: FileSize; /** * The maximum number of log files to keep around, defaults to 10. When the maximum is reached, the oldest file is deleted and writing starts * anew for that file. */ readonly maxFiles?: number; } ``` Only directory needs to be specified, the rest uses defaults. **Custom retention** If you'd like a different strategy, you can implement the `RetentionStrategy` interface. ```typescript /** * Retention strategy used by the NodeLogChannel. */ export interface RetentionStrategy { /** * The maximum file size allowed (when writing something > than this threshold a rollover will happen) */ maxFileSize: FileSize; /** * Encoding to use for writing files (or listing them) */ encoding: BufferEncoding; /** * Called when the NodeLogChannel wants to write a message the first time, this is only called once and allows for initialization/cleanup if needed. * * @param onRollOver Optional rollover function to be called when rollover occurs (when the user specified one when creating a channel, undefined otherwise. * Note that the actual function may not be what the user set as it can and will be wrapped in the default implementation. */ initialize(onRollOver?: (path: fs.PathLike) => void): void; /** * Called by the channel when it needs the next file to write to, *must* return the next file path to write to as well as * the current size of it when it exists, 0 if it doesn't exist (or empty file). * * @param mustRollOver When mustRollOver is true must rollover to the next file, even if the last file is not full yet. */ nextFile(mustRollOver: boolean): [path: fs.PathLike, size: number]; } ``` Please read the respective documentation of this interface, on what is expected exactly.