Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
The logform npm package is a module designed for formatting messages in logging systems, primarily used with the popular Winston logger. It provides a way to define how log messages should be formatted before they are written to a console, file, or any other transport.
Simple message formatting
This feature allows users to create custom message formats using the printf function from logform. It enables the inclusion of timestamp, label, level, and message in the log output.
const { format } = require('logform');
const { printf } = format;
const myFormat = printf(({ level, message, label, timestamp }) => {
return `${timestamp} [${label}] ${level}: ${message}`;
});
// Use this format in a Winston logger
Colorizing the output
This feature provides an easy way to add color to log messages based on the log level, enhancing readability especially when viewing logs directly from consoles.
const { format } = require('logform');
const { colorize } = format;
const colorizedFormat = colorize();
// This format can be used to add colors to different levels of log messages when used with Winston logger
Combining multiple formats
This feature allows the combination of multiple formatting methods such as adding labels, timestamps, and custom printf templates to create a highly customized log output.
const { format } = require('logform');
const { combine, timestamp, label, printf } = format;
const combinedFormats = combine(
label({ label: 'My App' }),
timestamp(),
printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`)
);
// This combined format can be used in a Winston logger to provide a rich structured output
Winston is a multi-transport async logging library for Node.js. While logform is primarily used as a formatting tool within Winston, Winston itself provides more comprehensive logging solutions including transports management, which logform does not handle.
Bunyan is another logging library that focuses on JSON logging. Unlike logform, which is used for formatting log messages, Bunyan handles both the logging and formatting but emphasizes a JSON structure for output, making it ideal for machine parsing.
Pino is a very low overhead Node.js logger, similar to Bunyan but focuses on performance. It includes its own set of formatting capabilities but is generally used for its performance benefits over extensive formatting options.
A mutable object-based log format designed for chaining & objectMode streams.
const { format } = require('logform');
const alignedWithColorsAndTime = format.combine(
format.colorize(),
format.timestamp(),
format.align(),
format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`)
);
info
ObjectsThe info
parameter provided to a given format represents a single log message. The object itself is mutable. Every info
must have at least the level
and message
properties:
{
level: 'info', // Level of the logging message
message: 'Hey! Log something?' // Descriptive message being logged.
}
logform
itself exposes several additional properties:
splat
: string interpolation splat for %d %s
-style messages.timestamp
: timestamp the message was received.label
: custom label associated with each message.As a consumer you may add whatever properties you wish – internal state is maintained by Symbol
properties:
Symbol.for('level')
(READ-ONLY): equal to level
property. Is treated as immutable by all code.Symbol.for('message'):
complete string message set by "finalizing formats": json
, logstash
, printf
, prettyPrint
, and simple
.Formats are prototypal objects (i.e. class instances) that define a single method: transform(info, opts)
and return the mutated info
info
: an object representing the log message.opts
: setting specific to the current instance of the format.They are expected to return one of two things:
info
Object representing the modified info
argument. Object references need not be preserved if immutability is preferred. All current built-in formats consider info
mutable, but [immutablejs] is being considered for future releases.info
argument should be ignored by the caller. (See: Filtering info
Objects) below.logform.format
is designed to be as simple as possible. To define a new format simple pass it a transform(info, opts)
function to get a new Format
.
The named Format
returned can be used to create as many copies of the given Format
as desired:
const { format } = require('logform');
const volume = format((info, opts) => {
if (opts.yell) {
info.message = info.message.toUpperCase();
} else if (opts.whisper) {
info.message = info.message.toLowerCase();
}
return info;
});
// `volume` is now a function that returns instances of the format.
const scream = volume({ yell: true });
console.dir(scream.transform({
level: 'info',
message: `sorry for making you YELL in your head!`
}, scream.options));
// {
// level: 'info'
// message: 'SORRY FOR MAKING YOU YELL IN YOUR HEAD!'
// }
// `volume` can be used multiple times to create different formats.
const whisper = volume({ whisper: true });
console.dir(whisper.transform({
level: 'info',
message: `WHY ARE THEY MAKING US YELL SO MUCH!`
}), whisper.options);
// {
// level: 'info'
// message: 'why are they making us yell so much!'
// }
Any number of formats may be combined into a single format using format.combine
. Since format.combine
takes no opts
, as a convenience it returns pre-created instance of the combined format.
const { format } = require('logform');
const { combine, timestamp, label } = format;
const labelTimestamp = combine(
label({ label: 'right meow!' }),
timestamp()
);
const info = labelTimestamp.transform({
level: 'info',
message: 'What time is the testing at?'
});
console.dir(info);
// { level: 'info',
// message: 'What time is the testing at?',
// label: 'right meow!',
// timestamp: '2017-09-30T03:57:26.875Z' }
info
ObjectsIf you wish to filter out a given info
Object completely then simply return a falsey value.
const ignorePrivate = format((info, opts) => {
if (info.private) { return false; }
return info;
});
console.dir(ignorePrivate.transform({
level: 'error',
message: 'Public error to share'
}));
// { level: 'error', message: 'Public error to share' }
console.dir(ignorePrivate.transform({
level: 'error',
private: true,
message: 'This is super secret - hide it.'
}));
// false
Use of format.combine
will respect any falsey values return and stop evaluation of later formats in the series. For example:
const { format } = require('logform');
const { combine, timestamp, label } = format;
const willNeverThrow = format.combine(
format(info => { return false })(), // Ignores everything
format(info => { throw new Error('Never reached') })()
);
console.dir(willNeverThrow.transform({
level: 'info',
message: 'wow such testing'
}))
The align
format adds a \t
delimiter before the message to align it in the same place.
const { format } = require('logform');
const alignFormat = format.align();
const info = alignFormat.transform({
level: 'info',
message: 'my message'
});
console.log(info);
// { level: 'info', message: '\tmy message' }
This was previously exposed as { align: true }
in winston < 3.0.0
.
The cli
format is a combination of the colorize
and the padLevels
formats. It turns a log info
object into the same format previously available in winston.cli()
in winston < 3.0.0
.
const { format } = require('logform');
const LEVEL = Symbol.for('level');
const cliFormat = format.cli({ colors: { info: 'blue' }});
const info = cliFormat.transform({
[LEVEL]: 'info',
level: 'info',
message: 'my message'
}, { all: true });
console.log(info);
// { level: '\u001b[34minfo\u001b[39m',
// message: '\u001b[34m my message\u001b[39m',
// [Symbol(level)]: 'info',
// [Symbol(message)]:
// '\u001b[34minfo\u001b[39m:\u001b[34m my message\u001b[39m' }
The colorize
format adds different colors depending on the log level to the message and/or level.
It accepts the following options:
true
the color will be applied to the level
.true
the color will be applied to the message
and level
.true
the color will be applied to the message
.{ info: 'blue', error: 'red' }
const { format } = require('logform');
const LEVEL = Symbol.for('level');
const colorizeFormat = format.colorize({ colors: { info: 'blue' }});
const info = colorizeFormat.transform({
[LEVEL]: 'info',
level: 'info',
message: 'my message'
}, { all: true });
console.log(info);
// { level: '\u001b[34minfo\u001b[39m',
// message: '\u001b[34mmy message\u001b[39m',
// [Symbol(level)]: 'info' }
This was previously exposed as { colorize: true }
to transports in winston < 3.0.0
.
The combine
Format allows to combine multiple formats:
const { format } = require('logform');
const { combine, timestamp, json } = format;
const jsonWithTimestamp = combine(
timestamp(),
json()
);
const info = jsonWithTimestamp.transform({
level: 'info',
message: 'my message'
});
console.log(info);
// { level: 'info',
// message: 'my message',
// timestamp: '2018-10-02T15:03:14.230Z',
// [Symbol(message)]:
// '{"level":"info","message":"my message","timestamp":"2018-10-02T15:03:14.230Z"}' }
The json
format uses fast-safe-stringify
to finalize the message.
It accepts the following options:
info
is stringified.const { format } = require('logform');
const jsonFormat = format.json();
const info = jsonFormat.transform({
level: 'info',
message: 'my message',
});
console.log(info);
// { level: 'info',
// message: 'my message',
// [Symbol(message)]: '{"level":"info","message":"my message"}' }
This was previously exposed as { json: true }
to transports in winston < 3.0.0
.
The label
format adds the specified label
before the message or adds it to the info
object.
It accepts the following options:
true
the label
will be added to info.message
. If set to false
the label
will be added as info.label
.const { format } = require('logform');
const labelFormat = format.label();
const info = labelFormat.transform({
level: 'info',
message: 'my message'
}, { label: 'my label', message: true });
console.log(info);
// { level: 'info', message: '[my label] my message' }
This was previously exposed as { label: 'my label' }
to transports in winston < 3.0.0
.
The logstash
Format turns a log info
object into pure JSON with the appropriate logstash options.
const { format } = require('logform');
const { logstash, combine, timestamp } = format;
const logstashFormat = combine(
timestamp(),
logstash()
);
const info = logstashFormat.transform({
level: 'info',
message: 'my message'
});
console.log(info);
// { level: 'info',
// [Symbol(message)]:
// '{"@message":"my message","@timestamp":"2018-10-02T11:04:52.915Z","@fields":{"level":"info"}}' }
This was previously exposed as { logstash: true }
to transports in winston < 3.0.0
.
The metadata
format adds a metadata object to collect extraneous data, similar to the metadata object in winston 2.x.
It accepts the following options:
metadata
.const { format } = require('logform');
const metadataFormat = format.metadata();
const info = metadataFormat.transform({
level: 'info',
message: 'my message',
meta: 42
});
console.log(info);
// { level: 'info', message: 'my message', metadata: { meta: 42 } }
The padLevels
format pads levels to be the same length.
const { format } = require('logform');
const LEVEL = Symbol.for('level');
const padLevelsFormat = format.padLevels();
const info = padLevelsFormat.transform({
[LEVEL]: 'info',
message: 'my message'
});
console.log(info);
// { message: ' my message', [Symbol(level)]: 'info' }
This was previously exposed as { padLevels: true }
to transports in winston < 3.0.0
.
The prettyPrint
format finalizes the message using util.inspect
.
It accepts the following options:
number
that specifies the maximum depth of the info
object being stringified by util.inspect
. Defaults to 2
.true
. Defaults to false
.The prettyPrint
format should not be used in production because it may impact performance negatively and block the event loop.
This was previously exposed as { prettyPrint: true }
to transports in winston < 3.0.0
.
const { format } = require('logform');
const prettyPrintFormat = format.prettyPrint();
const info = prettyPrintFormat.transform({
level: 'info',
message: 'my message'
});
console.log(info);
// { level: 'info',
// message: 'my message',
// [Symbol(message)]: '{ level: \'info\', message: \'my message\' }' }
The printf
format allows to create a custom logging format:
const { format } = require('logform');
const myFormat = format.printf((info) => {
return `${info.level} ${info.message}`;
})
const info = myFormat.transform({
level: 'info',
message: 'my message'
});
console.log(info);
// { level: 'info',
// message: 'my message',
// [Symbol(message)]: 'info my message' }
The simple
format finalizes the info
object using the format: level: message stringifiedRest
.
const { format } = require('logform');
const MESSAGE = Symbol.for('message');
const simpleFormat = format.simple();
const info = simpleFormat.transform({
level: 'info',
message: 'my message',
number: 123
});
console.log(info[MESSAGE]);
// info: my message {number:123}
The splat
format transforms the message by using util.format
to complete any info.message
provided it has string interpolation tokens.
const { format } = require('logform');
const splatFormat = format.splat();
const info = splatFormat.transform({
level: 'info',
message: 'my message %s',
splat: ['test']
});
console.log(info);
// { level: 'info', message: 'my message test', splat: [ 'test' ] }
Any additional splat parameters beyond those needed for the %
tokens
(aka "metas") are assumed to be objects. Their enumerable properties are
merged into the info
.
const { format } = require('logform');
const splatFormat = format.splat();
const info = splatFormat.transform({
level: 'info',
message: 'my message %s',
splat: ['test', { thisIsMeta: true }]
});
console.log(info);
// { level: 'info',
// message: 'my message test',
// thisIsMeta: true,
// splat: [ 'test' ] }
This was previously exposed implicitly in winston < 3.0.0
.
The timestamp
format adds a timestamp to the info.
It accepts the following options:
new Date().toISOString()
will be used.info
object.const { format } = require('logform');
const timestampFormat = format.timestamp();
const info = timestampFormat.transform({
level: 'info',
message: 'my message'
});
console.log(info);
// { level: 'info',
// message: 'my message',
// timestamp: '2018-10-02T11:47:02.682Z' }
It was previously available in winston < 3.0.0
as { timestamp: true }
and { timestamp: function:String }
.
The uncolorize
format strips colors from info
objects.
It accepts the following options:
info.level
if set to false
.info.message
if set to false
.info[MESSAGE]
if set to false
.This was previously exposed as { stripColors: true }
to transports in winston < 3.0.0
.
Tests are written with mocha
, assume
, and nyc
. They can be run with npm
:
npm test
2.0.0
2018/12/23
splat
behavior` below.README.md
splat
behaviorPreviously splat
would have added a meta
property for any additional
info[SPLAT]
beyond the expected number of tokens.
As of logform@2.0.0
, format.splat
assumes additional splat paramters
(aka "metas") are objects and merges enumerable properties into the info
.
e.g.
const { format } = require('logform');
const { splat } = format;
const { MESSAGE, LEVEL, SPLAT } = require('triple-beam');
console.log(
// Expects two tokens, but three splat parameters provided.
splat().transform({
level: 'info',
message: 'Let us %s for %j',
[LEVEL]: 'info',
[MESSAGE]: 'Let us %s for %j',
[SPLAT]: ['objects', { label: 'sure' }, { thisIsMeta: 'wut' }]
})
);
// logform@1.x behavior:
// Added "meta" property.
//
// { level: 'info',
// message: 'Let us objects for {"label":"sure"}',
// meta: { thisIsMeta: 'wut' },
// [Symbol(level)]: 'info',
// [Symbol(message)]: 'Let us %s for %j',
// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] }
// logform@2.x behavior:
// Enumerable properties assigned into `info`.
//
// { level: 'info',
// message: 'Let us objects for {"label":"sure"}',
// thisIsMeta: 'wut',
// [Symbol(level)]: 'info',
// [Symbol(message)]: 'Let us %s for %j',
// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] }
The reason for this change is to be consistent with how winston
itself
handles meta
objects in its variable-arity conventions.
BE ADVISED previous "metas" that were not objects will very likely lead to odd behavior. e.g.
const { format } = require('logform');
const { splat } = format;
const { MESSAGE, LEVEL, SPLAT } = require('triple-beam');
console.log(
// Expects two tokens, but three splat parameters provided.
splat().transform({
level: 'info',
message: 'Let us %s for %j',
[LEVEL]: 'info',
[MESSAGE]: 'Let us %s for %j',
// !!NOTICE!! Additional parameters are a string and an Array
[SPLAT]: ['objects', { label: 'sure' }, 'lol', ['ok', 'why']]
})
);
// logform@1.x behavior:
// Added "meta" property.
//
// { level: 'info',
// message: 'Let us objects for {"label":"sure"}',
// meta: ['lol', ['ok', 'why']],
// [Symbol(level)]: 'info',
// [Symbol(message)]: 'Let us %s for %j',
// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] }
// logform@2.x behavior: Enumerable properties assigned into `info`.
// **Strings and Arrays only have NUMERIC enumerable properties!**
//
// { '0': 'ok',
// '1': 'why',
// '2': 'l',
// level: 'info',
// message: 'Let us objects for {"label":"sure"}',
// [Symbol(level)]: 'info',
// [Symbol(message)]: 'Let us %s for %j',
// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] }
FAQs
An mutable object-based log format designed for chaining & objectMode streams.
The npm package logform receives a total of 1,907,287 weekly downloads. As such, logform popularity was classified as popular.
We found that logform demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.