loglevel-plugin-prefix
loglevel-plugin-prefix is a small plugin that prepends timestamps, severity labels, and logger names to messages produced by loglevel. It wraps each logger's methodFactory, supports a token template or a custom formatting function, and works with the root logger as well as named loggers. It is a presentation add-on, not a logging backend: loglevel still controls levels and output, and the plugin does not add JSON records, transports, log rotation, persistence, redaction, or remote delivery.
Reasonable glue for an existing loglevel browser stack that wants readable prefixes. Do not treat its high transitive download count as a sign of current development, and wrap the call when TypeScript accuracy or structured production logs matter.
Use it if
- Your browser application already uses loglevel and you want consistent human-readable prefixes without replacing the logger
- You need separate prefixes for loglevel named loggers such as API, auth, or rendering channels
- You want a tiny synchronous formatter with configurable level, name, and timestamp functions
- You support an older script-tag integration where both loglevel and the prefix plugin are loaded as browser globals
- You need structured JSON, child bindings, redaction, serializers, or log transports; this plugin only prepends a string to loglevel arguments
- You are choosing a logger for a new Node service; Pino or Winston provides a maintained logging system instead of an add-on last released in June 2018
- You require a clearly stable API; the README calls the plugin unstable and promises backward compatibility only for patch releases
- You rely on exact TypeScript types; the bundled declaration says the format callback receives a Date for timestamp, while the implementation and README pass the string returned by timestampFormatter
- You need predictable configuration across independently loaded modules; the repository has an unresolved issue reporting that option inheritance does not work across modules
Setup reality
Install both loglevel and loglevel-plugin-prefix because the plugin package declares no runtime or peer dependency on loglevel. In CommonJS, require both, call prefix.reg(log) once with the root logger, then call prefix.apply(logger, options) for each root or named logger you want to format. Reversing that order currently logs a warning rather than throwing, even though the README has long said a later release would turn it into an error. Applying to the root establishes options inherited by named loggers, but per-name configuration is stored in module-level state, and an open issue reports surprising inheritance when modules load separate instances. Applying a configuration calls setLevel again so loglevel rebuilds its methods. The default output includes local time and uppercase severity but not the logger name. A custom template uses only the first occurrence of %t, %l, and %n because the implementation uses single String.replace calls. If format and template are both supplied, template wins and clears the inherited format function. Non-string first arguments receive the prefix as a separate leading argument, which matters for console inspection and any custom methodFactory. TypeScript users get bundled declarations, but the format callback's timestamp type is wrong: runtime passes a formatted string, not the declared Date. Test your wrapper instead of trusting that annotation. There are no native builds, credentials, files, or asynchronous startup steps.
Patterns
Add the default prefix to the root loggerregister-default-prefix
const log = require('loglevel');
const prefix = require('loglevel-plugin-prefix');
prefix.reg(log);
prefix.apply(log);
log.setLevel('info');
log.info('server connected');Call reg with the root loglevel object before apply. The default template prints local HH:MM:SS and an uppercase level.
Use timestamp, level, and logger-name tokensconfigure-template
prefix.apply(log, {
template: '[%t] %l %n:',
});
log.getLogger('api').warn('slow response');The supported tokens are %t, %l, and %n. Only the first occurrence of each token is replaced by version 0.8.4.
Format timestamps as ISO stringsformat-iso-time
prefix.apply(log, {
template: '[%t] %l:',
timestampFormatter(date) {
return date.toISOString();
},
});timestampFormatter receives a Date and its return value is passed into the template or custom format callback.
Build the entire prefix with a functioncustom-format-function
prefix.apply(log, {
format(level, name, timestamp) {
return `${timestamp} ${level} [${name}]`;
},
});At runtime timestamp is the formatted string, despite the bundled TypeScript declaration typing this argument as Date.
Give one named logger its own prefixprefix-named-logger
const authLog = log.getLogger('auth');
prefix.apply(authLog, {
template: '%l (%n):',
});
authLog.error('token expired');Register the root loglevel object once. Apply accepts a root or named logger, but reg does not accept an arbitrary named logger.
Let named loggers inherit root formattinginherit-root-options
prefix.apply(log, {
template: '[%t] %l %n:',
nameFormatter: (name) => name || 'app',
});
const cacheLog = log.getLogger('cache');
cacheLog.info('hit');Named loggers without their own configuration inherit root options, provided the application is using the same plugin module instance.
Change formatting after initial setupreconfigure-prefix
prefix.apply(log, { template: '%l:' });
log.info('plain prefix');
prefix.apply(log, {
template: '[%t] %l:',
});
log.info('timestamp restored');A second apply updates configuration and asks loglevel to rebuild methods; it does not stack a second prefix wrapper.
Keep console substitution arguments workingpreserve-printf-placeholders
prefix.apply(log, { template: '%l:' });
log.info('processed %d records in %d ms', count, elapsedMs);When the first argument is a string, the plugin prepends to that same string so console-style substitution placeholders remain aligned.
Log an object with a separate prefix argumentlog-object-value
prefix.apply(log, { template: '%l %n:' });
log.getLogger('state').debug({ userId: 42, active: true });For a non-string first argument, the plugin inserts the prefix as a new first argument. Console output and custom sinks may display it separately.
Use the plugin from script tagsload-browser-globals
<script src="https://unpkg.com/loglevel/dist/loglevel.min.js"></script>
<script src="https://unpkg.com/loglevel-plugin-prefix@0.8.4/dist/loglevel-plugin-prefix.min.js"></script>
<script>
prefix.reg(log);
prefix.apply(log, { template: '[%t] %l:' });
log.warn('prefixed in the browser');
</script>Pin the plugin version in a production page. The globals are log and prefix; noConflict is available when those names collide.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| loglevel | npm | Keep only loglevel and wrap its methodFactory yourself when one simple prefix convention is enough |
| pino | npm | Choose it for fast structured Node logging, child bindings, redaction, and machine-readable production output |
| winston | npm | Choose it when a Node application needs multiple transports and a larger formatting pipeline |
| debug | npm | Choose it for namespaced diagnostic output that users enable selectively with the DEBUG setting |