|
2 | 2 |
|
3 | 3 | > 🎯 Target runtime: es2023 ([Node >= 20](https://node.green/#ES2023)) |
4 | 4 |
|
5 | | -A simple logger to use with minimal dependencies. |
6 | | -By default, the logger is standalone and can be easily configured to log |
7 | | -messages to various transports. |
| 5 | +A simple logger to use with @shiftcode-only dependencies. |
| 6 | +The LoggerService is standalone and can be configured to log messages to various transports. |
8 | 7 |
|
9 | | -# Usage |
| 8 | +## Basic Usage |
10 | 9 |
|
11 | 10 | ```typescript |
12 | | -import { Logger, LogLevel, LogTransport, BaseLoggerService } from '@shiftcode/logger' |
| 11 | +import { LogLevel, BaseLoggerService, ConsoleJsonLogTransport } from '@shiftcode/logger' |
13 | 12 |
|
14 | | -// Create a transport for logging to the console with a specific log level |
15 | | -const transport = new LogTransport( |
16 | | - LogLevel.DEBUG, // This controls the minimum log level |
17 | | -) |
| 13 | +// Create a logger service with one or more transports |
| 14 | +const loggerService = new BaseLoggerService([new ConsoleJsonLogTransport({ logLevel: LogLevel.DEBUG })]) |
18 | 15 |
|
19 | | -// BaseLoggerService is used to manage loggers and their transports |
20 | | -const baseLoggerService = new BaseLoggerService([transport]) |
| 16 | +// Get a logger instance with a name and optional color |
| 17 | +const logger = loggerService.getInstance('MyLogger', '#abcdef') |
21 | 18 |
|
22 | | -// Create a logger instance with a specific name and color |
23 | | -const logger = baseLoggerService.getInstance('MyLogger', '#abcdef') |
| 19 | +// Use the logger |
| 20 | +logger.debug('Debug message', { someData: 'value' }) |
| 21 | +logger.info('Info message') |
| 22 | +logger.warn('Warning message') |
| 23 | +logger.error('Error occurred', new Error('Something went wrong')) |
| 24 | +``` |
| 25 | + |
| 26 | +## Intended Behavior |
| 27 | + |
| 28 | +The Following is the intended behavior - but implementation is due to the Log Transports. |
| 29 | +Not everything is applicable to every transport. |
| 30 | + |
| 31 | +### Message Field |
| 32 | + |
| 33 | +- If the first argument is a string, it becomes the `message` field |
| 34 | +- If no string message is provided but an `Error` is passed, the error's message becomes the log message |
| 35 | + |
| 36 | +### Error Handling |
| 37 | + |
| 38 | +- Errors can be passed at any position in the arguments |
| 39 | +- The first `Error` found is extracted and [formatted](./src/utils/format-error.function.ts) into the `error` field with: |
| 40 | + - `name`: Error class name |
| 41 | + - `location`: Code location extracted from stack trace |
| 42 | + - `message`: Error message |
| 43 | + - `stack`: Full stack trace |
| 44 | + - `cause`: Recursively formatted if present |
| 45 | + |
| 46 | +### Data Handling |
| 47 | + |
| 48 | +- **BigInt**: Automatically converted to string for JSON serialization |
| 49 | +- **Circular References**: Detected and replaced with `<circular reference>` placeholder (see [`getJsonStringifyReplacer`](./src/utils/get-json-stringify-replacer.function.ts)) |
| 50 | +- **Map/Set**: Serialized using the default `jsonMapSetStringifyReplacer` (can be customized) |
| 51 | +- Remaining arguments after message and error extraction are placed in the `data` field |
| 52 | + |
| 53 | +### Message Buffering |
| 54 | + |
| 55 | +Log messages below the configured level are buffered (default: 50 messages). |
| 56 | +When an `ERROR` level log occurs, all buffered messages are flushed first, providing context for the error. |
| 57 | + |
| 58 | +## Log Transports |
| 59 | + |
| 60 | +### [ConsoleJsonLogTransport](./src/console-json-log-transport/console-json-log.transport.ts) |
| 61 | + |
| 62 | +**Purpose**: Structured JSON logging optimized for AWS Lambda / cloud environments. |
24 | 63 |
|
25 | | -// Logging messages at different levels |
26 | | -logger.debug('This is a debug message') |
27 | | -logger.info('This is an info message') |
28 | | -logger.warn('This is a warning message') |
29 | | -logger.error('This is an error message') |
| 64 | +Outputs logs as JSON strings (or JS objects) that can be parsed by AWS CloudWatch and other log aggregation services. |
| 65 | + |
| 66 | +```typescript |
| 67 | +import { ConsoleJsonLogTransport, LogLevel } from '@shiftcode/logger' |
| 68 | + |
| 69 | +const transport = new ConsoleJsonLogTransport({ logLevel: LogLevel.INFO }) |
| 70 | +``` |
| 71 | + |
| 72 | +See [`ConsoleJsonLogTransportConfig`](./src/console-json-log-transport/console-json-log-transport-config.ts) for all options. |
| 73 | + |
| 74 | +**Output format**: |
| 75 | + |
| 76 | +```json |
| 77 | +{ |
| 78 | + "level": "INFO", |
| 79 | + "timestamp": "2024-01-15T10:30:00.000Z", |
| 80 | + "logger": "MyService", |
| 81 | + "message": "Processing request", |
| 82 | + "data": { "requestId": "abc123" } |
| 83 | +} |
30 | 84 | ``` |
| 85 | + |
| 86 | +### [NodeConsoleLogTransport](./src/node/node-console-log-transport/node-console-log.transport.ts) |
| 87 | + |
| 88 | +**Purpose**: Human-readable colored console output for local Node.js development. |
| 89 | + |
| 90 | +Uses colorized output with emojis for log levels and `util.inspect` for object formatting. |
| 91 | + |
| 92 | +```typescript |
| 93 | +import { NodeConsoleLogTransport, LogLevel } from '@shiftcode/logger/node' |
| 94 | + |
| 95 | +const transport = new NodeConsoleLogTransport({ logLevel: LogLevel.DEBUG }) |
| 96 | +``` |
| 97 | + |
| 98 | +See [`NodeConsoleLogTransportConfig`](./src/node/node-console-log-transport/node-console-log-transport-config.ts) for all options. |
| 99 | + |
| 100 | +**Output format**: |
| 101 | + |
| 102 | +``` |
| 103 | +🐞 10:30:00.000 - MyService :: Debug message { requestId: 'abc123' } |
| 104 | +ℹ️ 10:30:00.001 - MyService :: Info message |
| 105 | +⚠️ 10:30:00.002 - MyService :: Warning message |
| 106 | +🔥 10:30:00.003 - MyService :: Error occurred |
| 107 | +``` |
| 108 | + |
| 109 | +## Simple Lambda Logger |
| 110 | + |
| 111 | +For AWS Lambda functions, use the [`simpleLambdaLogger`](./src/node/simple-lambda-logger.function.ts) helper that automatically selects the appropriate transport: |
| 112 | + |
| 113 | +- **AWS Lambda environment**: Uses `ConsoleJsonLogTransport` (JSON output) |
| 114 | +- **Local development**: Uses `NodeConsoleLogTransport` (colored console output) |
| 115 | + |
| 116 | +```typescript |
| 117 | +import { simpleLambdaLogger } from '@shiftcode/logger/node' |
| 118 | +import { LogLevel } from '@shiftcode/logger' |
| 119 | + |
| 120 | +// Automatically detects environment and uses appropriate transport |
| 121 | +const logger = simpleLambdaLogger('MyLambdaHandler', LogLevel.DEBUG) |
| 122 | + |
| 123 | +export const handler = async (event: any) => { |
| 124 | + logger.info('Processing event', { eventType: event.type }) |
| 125 | + |
| 126 | + try { |
| 127 | + // ... your logic |
| 128 | + logger.debug('Operation completed', { result: 'success' }) |
| 129 | + } catch (error) { |
| 130 | + // Error is automatically formatted with stack trace |
| 131 | + logger.error('Failed to process event', error, { eventId: event.id }) |
| 132 | + throw error |
| 133 | + } |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +## Utilities |
| 138 | + |
| 139 | +### [createJsonLogObjectData](./src/utils/create-json-log-object-data.function.ts) |
| 140 | + |
| 141 | +Creates a structured JSON log object from log arguments. This function handles the parsing and organization of log message, error, and additional data into a standardized format. |
| 142 | + |
| 143 | +**Behavior**: |
| 144 | + |
| 145 | +- First string argument becomes the `message` field |
| 146 | +- First `Error` instance is extracted and formatted into the `error` field |
| 147 | +- If no message is provided but an error exists, the error's message is used |
| 148 | +- Remaining arguments are placed in the `data` field |
| 149 | + |
| 150 | +### [formatError](./src/utils/format-error.function.ts) |
| 151 | + |
| 152 | +Formats an Error object into a loggable structure with consistent attributes including name, location, message, stack trace, and recursively formatted cause chain. |
| 153 | + |
| 154 | +### [pushToRingBuffer](./src/utils/push-to-ring-buffer.function.ts) |
| 155 | + |
| 156 | +Pushes an item to a ring buffer array, automatically removing the oldest entry when the buffer exceeds the specified maximum size. Used for message buffering. |
| 157 | + |
| 158 | +### [stringToColor](./src/utils/string-to-color.function.ts) |
| 159 | + |
| 160 | +Generates a deterministic hex color code from a string. Useful for assigning consistent colors to logger instances based on their names. |
0 commit comments