Creates a new Logger instance with the specified prefix and optional initial log level.
A string that will be included in all log messages for this instance
Optional
initialLogLevel: LogLevelOptional log level to set at initialization. If provided,
the logger will use this fixed level and ignore environment
variables. If not provided, the logger will automatically
sync with environment variables (process.env.LOG_LEVEL
or
window.LOG_LEVEL
) and update its level when they change.
Private
Static
getRetrieves the log level from environment variables. Checks the following in order:
window.LOG_LEVEL
(Browser)process.env.LOG_LEVEL
(Node.js)
Returns LogLevel.INFO if no valid log level is found or if any errors occur.The environment-specified log level or LogLevel.INFO if not set
// Dynamic logger that syncs with environment
const appLogger = new Logger('App');
appLogger.getEnvLogLevel(); // Returns LogLevel.INFO
appLogger.debug("This will not be logged");
window.LOG_LEVEL = "DEBUG";
appLogger.getEnvLogLevel(); // Returns LogLevel.DEBUG
appLogger.debug("This will be logged");
Sets a fixed minimum log level for this logger instance. This disables automatic
environment variable syncing - the logger will maintain this level regardless
of environment changes until setLogLevel
is called again.
The new minimum log level to fix this logger instance at
Gets the current minimum log level for this logger instance. Note that if this logger is syncing with environment variables, this value may change between calls as the environment changes.
The current log level
const logger = new Logger('MyApp', LogLevel.WARN);
logger.getLogLevel(); // Returns: LogLevel.WARN
// With environment sync
const envLogger = new Logger('MyApp');
envLogger.getLogLevel(); // Returns: LogLevel.INFO (default)
window.LOG_LEVEL = 'DEBUG';
envLogger.debug('trigger check');
envLogger.getLogLevel(); // Returns: LogLevel.DEBUG
// After setting fixed level
envLogger.setLogLevel(LogLevel.ERROR);
envLogger.getLogLevel(); // Returns: LogLevel.ERROR (now fixed)
Private
formatFormats a log message with timestamp, level, and prefix.
The log level for the message
The message to format
The formatted message string
// Internal method usage:
this.formatMessage(LogLevel.INFO, "User logged in");
// Returns: "[2024-01-01T00:00:00.000Z] [INFO] [MyApp] User logged in"
this.formatMessage(LogLevel.ERROR, "Database connection failed");
// Returns: "[2024-01-01T00:00:00.000Z] [ERROR] [MyApp] Database connection failed"
Private
shouldDetermines if a message at the given level should be logged based on the current log level. If environment syncing is enabled, checks for environment changes before making the determination.
The level of the message being logged
true if the message should be logged, false otherwise
// Internal method usage:
const logger = new Logger('MyApp', LogLevel.INFO);
logger.shouldLog(LogLevel.DEBUG); // Returns: false
logger.shouldLog(LogLevel.INFO); // Returns: true
logger.shouldLog(LogLevel.WARN); // Returns: true
logger.shouldLog(LogLevel.ERROR); // Returns: true
// With environment sync:
const envLogger = new Logger('MyApp');
window.LOG_LEVEL = 'DEBUG';
envLogger.shouldLog(LogLevel.DEBUG); // Updates level and returns true
Logs a debug message if the current log level is DEBUG
or lower.
If environment syncing is enabled, checks environment variables before logging.
The message to log
Additional arguments to pass to console.debug
Logs an info message if the current log level is INFO
or lower.
If environment syncing is enabled, checks environment variables before logging.
The message to log
Additional arguments to pass to console.info
Logs a warning message if the current log level is WARN
or lower.
If environment syncing is enabled, checks environment variables before logging.
The message to log
Additional arguments to pass to console.warn
Logs an error message if the current log level is ERROR
or lower.
If environment syncing is enabled, checks environment variables before logging.
The message to log
Additional arguments to pass to console.error
const logger = new Logger('MyApp');
// Basic error
logger.error('Failed to connect to database');
// Output: [2024-01-01T00:00:00.000Z] [ERROR] [MyApp] Failed to connect to database
// Error with additional details
try {
throw new Error('Connection timeout');
} catch (err) {
logger.error('Database error:', err);
// Output: [2024-01-01T00:00:00.000Z] [ERROR] [MyApp] Database error: Error: Connection timeout
}
// Multiple arguments
logger.error('Operation failed', { code: 500, reason: 'Timeout' }, 'at endpoint: /api/data');
General purpose logging method. Uses INFO
level.
If environment syncing is enabled, checks environment variables before logging.
The message to log
Additional arguments to pass to console.log
const logger = new Logger('MyApp');
// Basic logging
logger.log('Application started');
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] Application started
// Logging with additional data
logger.log('User settings', { theme: 'dark', notifications: true });
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] User settings { theme: 'dark', notifications: true }
// Multiple arguments
logger.log('Process completed', 'Duration:', 1234, 'ms');
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] Process completed Duration: 1234 ms
Displays an interactive listing of the properties of an object. Uses DEBUG level.
The object to inspect
Optional
options: { depth?: number; colors?: boolean }Optional console.dir
options
const logger = new Logger('MyApp', LogLevel.DEBUG);
// Basic object inspection
const user = { id: 1, name: 'John', settings: { theme: 'dark' } };
logger.dir(user);
// With custom options
logger.dir(user, { depth: 1, colors: true });
// Complex object
const response = await fetch('/api/data');
const data = await response.json();
logger.dir(data, { depth: null }); // Show all levels
Logs the number of times this method has been called with a given label.
Uses INFO
level.
The counter label
const logger = new Logger('MyApp');
// Count API calls
logger.count('api-requests');
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] api-requests: 1
logger.count('api-requests');
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] api-requests: 2
// Using default label
logger.count();
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] default: 1
// Multiple counters
logger.count('errors');
logger.count('api-requests');
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] errors: 1
// Output: [2024-01-01T00:00:00.000Z] [INFO] [MyApp] api-requests: 3
Resets the counter for a given label.
The counter label to reset
const logger = new Logger('MyApp');
// Count and reset
logger.count('api-requests'); // Output: api-requests: 1
logger.count('api-requests'); // Output: api-requests: 2
logger.countReset('api-requests');
logger.count('api-requests'); // Output: api-requests: 1
// Reset default counter
logger.count(); // Output: default: 1
logger.countReset();
logger.count(); // Output: default: 1
// Reset non-existent counter (silent operation)
logger.countReset('unknown');
Creates a new inline group in the console output.
Subsequent console messages will be indented.
Uses INFO
level.
Optional
label: stringThe group label
const logger = new Logger('MyApp');
// Basic grouping
logger.group('User Authentication');
logger.log('Checking credentials...');
logger.log('User authenticated');
logger.groupEnd();
// Nested groups
logger.group('API Response');
logger.log('Status: 200');
logger.group('Response Body');
logger.log('Data loaded');
logger.groupEnd();
logger.log('Request completed');
logger.groupEnd();
// Group without label
logger.group();
logger.log('Grouped message');
logger.groupEnd();
Creates a new inline group in the console output, but starts collapsed.
Subsequent console messages will be indented.
Uses INFO
level.
Optional
label: stringThe group label
const logger = new Logger('MyApp');
// Collapsed debug information
logger.groupCollapsed('Debug Details');
logger.log('Environment:', process.env.NODE_ENV);
logger.log('Platform:', process.platform);
logger.log('Memory Usage:', process.memoryUsage());
logger.groupEnd();
// Nested collapsed groups
logger.groupCollapsed('Request Details');
logger.log('URL:', request.url);
logger.groupCollapsed('Headers');
logger.log(request.headers);
logger.groupEnd();
logger.log('Body:', request.body);
logger.groupEnd();
Exits the current inline group in the console.
Outputs a stack trace to the console.
Uses DEBUG
level.
Optional
message: stringOptional message to include
const logger = new Logger('MyApp', LogLevel.DEBUG);
// Basic trace
logger.trace();
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [MyApp]
// at Function.method (/path/to/file.ts:10:10)
// at Object.<anonymous> (/path/to/file.ts:5:5)
// Trace with message
logger.trace('User authentication failed');
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [MyApp] User authentication failed
// at Function.authenticate (/path/to/auth.ts:15:10)
// at Object.<anonymous> (/path/to/handler.ts:8:5)
// In error handling
try {
throw new Error('Something went wrong');
} catch (error) {
logger.trace('Error caught:');
}
Displays tabular data as a table.
Uses INFO
level.
Data to display in table format
Optional
properties: readonly string[]Optional array of property names to display
const logger = new Logger('MyApp');
// Simple array of objects
const users = [
{ id: 1, name: 'John', role: 'admin' },
{ id: 2, name: 'Jane', role: 'user' }
];
logger.table(users);
// Specify columns to display
logger.table(users, ['name', 'role']);
// Array of arrays
const matrix = [
[1, 2, 3],
[4, 5, 6]
];
logger.table(matrix);
// Object with nested data
const data = {
users: { count: 2, active: 1 },
posts: { count: 10, draft: 3 }
};
logger.table(data);
Clears the console if possible.
Creates a new timing with the specified label.
Uses DEBUG
level for output.
The timer label
const logger = new Logger('Performance');
// Start a named timer
logger.time('database-query');
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [Performance] Timer 'database-query' started
// Start default timer
logger.time();
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [Performance] Timer 'default' started
// Attempting to start an existing timer
logger.time('database-query');
// Output: [2024-01-01T00:00:00.000Z] [WARN] [Performance] Timer 'database-query' already exists
Stops a timer and logs the elapsed time.
Uses DEBUG
level for output.
The timer label
const logger = new Logger('Performance');
// Basic timer usage
logger.time('operation');
await someAsyncOperation();
logger.timeEnd('operation');
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [Performance] Timer 'operation': 1234.56ms
// Attempting to end non-existent timer
logger.timeEnd('invalid-timer');
// Output: [2024-01-01T00:00:00.000Z] [WARN] [Performance] Timer 'invalid-timer' does not exist
// Using default timer
logger.time();
await someAsyncOperation();
logger.timeEnd();
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [Performance] Timer 'default': 1234.56ms
Logs the current value of a timer without stopping it.
Uses DEBUG
level for output.
The timer label
Additional data to log with the timer
const logger = new Logger('Performance');
// Log progress during a long operation
logger.time('long-task');
for (const item of items) {
await processItem(item);
logger.timeLog('long-task', { processedItem: item.id });
// Output: [2024-01-01T00:00:00.000Z] [DEBUG] [Performance] Timer 'long-task': 1234.56ms { processedItem: 123 }
}
logger.timeEnd('long-task');
// Attempting to log non-existent timer
logger.timeLog('invalid-timer');
// Output: [2024-01-01T00:00:00.000Z] [WARN] [Performance] Timer 'invalid-timer' does not exist
Adds a timestamp marker to the timeline in browser devtools. In non-browser environments, logs a timestamp message. Uses DEBUG level.
Optional
label: stringOptional label for the timestamp
const logger = new Logger('Timeline');
// Add labeled timestamp
logger.timeStamp('User Clicked Button');
// In Browser DevTools: Adds timeline marker 'User Clicked Button'
// In Console: [2024-01-01T00:00:00.000Z] [DEBUG] [Timeline] Timestamp 'User Clicked Button': 2024-01-01T00:00:00.000Z
// Add unlabeled timestamp
logger.timeStamp();
// In Browser DevTools: Adds timeline marker
// In Console: [2024-01-01T00:00:00.000Z] [DEBUG] [Timeline] Timestamp: 2024-01-01T00:00:00.000Z
// Useful for marking significant events in application flow
async function handleUserAction() {
logger.timeStamp('Action Started');
await processAction();
logger.timeStamp('Action Completed');
}
Private
Static
Readonly
logMaps log levels to their priority values for comparison. Higher numbers indicate higher priority levels. Used internally to determine if a message should be logged based on the current log level.
Priority: DEBUG=0, INFO=1, WARN=2, ERROR=3
Private
countersStores named counters for the count()
and countReset()
methods.
Keys are counter labels, values are the current count.
Private
timersStores active timers for the time()
, timeEnd()
, and timeLog()
methods.
Keys are timer labels, values are the start timestamps in milliseconds.
Private
groupTracks the current nesting level for the group()
and groupCollapsed()
methods.
Incremented by group/groupCollapsed, decremented by groupEnd.
Used to determine the indentation level of log messages.
Private
Readonly
groupThe indentation string used for each group level. Each nested group will add this string to the message prefix. Default is two spaces per level of nesting.
Private
prefixThe identifier prefix that will be included in all log messages from this instance. Used to distinguish logs from different parts of the application.
Private
currentThe current minimum log level for this logger instance.
Messages with a level lower than this will not be logged.
Can be changed at runtime using setLogLevel()
.
Private
useControls whether this logger instance should automatically sync its log level with environment variables. When true, the logger checks environment variables before each log operation to detect changes. When false, the logger maintains a fixed log level regardless of environment changes.
A flexible logging utility that supports different log levels and prefixed output.
Remarks
Works in both Node.js and browser environments. Each logger instance can either maintain its own fixed log level or automatically sync with environment variables. Instances of Logger should be mostly accurate substitutions for the console object as it includes all of the main methods of the console object, as well as some of the less commonly used methods methods (table, timer, group, etc).
Features:
process.env.LOG_LEVEL
orwindow.LOG_LEVEL
)Example