logfmt: Key-Value Logger and Parser
logfmt is a Node.js library for working with the key-value logging convention popularized by Heroku. It provides functionalities for both serializing JavaScript objects into logfmt strings (e.g., `foo=bar a=14 baz="hello kitty"`) and parsing logfmt strings back into objects. The library also includes streaming capabilities for processing logfmt data from sources like `stdin` or HTTP requests, making it suitable for creating logplex drains or general structured log consumption/production. Currently at version 1.4.0, the package has not seen active development or releases since 2018, indicating an abandoned status. Its key differentiator is its direct support for the logfmt format, unlike general-purpose JSON loggers, making it specific to ecosystems leveraging this convention.
Common errors
-
TypeError: logfmt.stringify is not a function
cause Attempting to call `stringify` or other methods on an undefined `logfmt` object, or if the `logfmt` variable was reassigned.fixEnsure `const logfmt = require('logfmt');` is correctly placed and executed before calling any methods on `logfmt`. Verify no other code is inadvertently overwriting the `logfmt` variable. -
TypeError: Cannot read properties of undefined (reading 'pipe')
cause This typically occurs when attempting to `pipe` to a `logfmt.streamParser()` or `logfmt.streamStringify()` instance, but the stream object itself is undefined or not a valid stream.fixCheck that the stream being piped from (e.g., `process.stdin`, `req`, a `Readable` stream) is properly initialized and available. Ensure `logfmt.streamParser()` or `logfmt.streamStringify()` are correctly called without errors. -
SyntaxError: Unexpected token 'o' at JSON.parse (<anonymous>)
cause This error happens when a logfmt string is accidentally passed to `JSON.parse()`. Logfmt is a key-value format, not JSON.fixUse `logfmt.parse(yourLogfmtString)` to correctly parse logfmt strings into JavaScript objects. Reserve `JSON.parse()` for actual JSON strings. -
ReferenceError: logfmt is not defined
cause The `logfmt` variable was used without being declared or initialized, usually by omitting the `require` statement.fixAdd `const logfmt = require('logfmt');` at the top of your file to properly import the module.
Warnings
- breaking The `logfmt` package appears to be abandoned. The last commit on GitHub was in June 2018, and the last release was in February 2018. This means there will be no further bug fixes, security patches, or feature development. Using this library in new projects is strongly discouraged.
- gotcha The `logfmt.parse()` method does not automatically convert all numeric strings to numbers. It only converts `true` and `false` strings to booleans. Numbers are parsed as strings to avoid precision loss issues with 32-bit representations.
- gotcha The `logfmt` module is a singleton when imported via `require('logfmt')`. Any modifications to its properties (e.g., `logfmt.stringify = JSON.stringify`) will affect all parts of your application that use this global instance.
- gotcha The library primarily targets CommonJS environments and does not officially support ES Modules (ESM). While bundlers might transpile it, direct ESM `import` statements may behave unexpectedly or require specific configuration.
Install
-
npm install logfmt -
yarn add logfmt -
pnpm add logfmt
Imports
- logfmt
import logfmt from 'logfmt';
const logfmt = require('logfmt'); - logfmt.stringify
import { stringify } from 'logfmt';const logfmt = require('logfmt'); logfmt.stringify({ key: 'value' }); - logfmt.parse
const parse = require('logfmt').parse;const logfmt = require('logfmt'); logfmt.parse('key=value'); - logfmt.streamParser
const logfmt = require('logfmt'); process.stdin.pipe(logfmt.streamParser());
Quickstart
const logfmt = require('logfmt');
const through = require('through'); // often used for stream manipulation
// --- Non-streaming usage ---
const data = { status: 200, method: 'GET', path: '/api/items', duration_ms: 50 };
const logString = logfmt.stringify(data);
console.log('Stringified:', logString);
// Expected: Stringified: status=200 method=GET path=/api/items duration_ms=50
const parsedObject = logfmt.parse('status=200 method=GET path=/api/items duration_ms=50');
console.log('Parsed:', parsedObject);
// Expected: Parsed: { status: '200', method: 'GET', path: '/api/items', duration_ms: '50' }
// --- Streaming usage (parsing logfmt from a simulated input) ---
const { Readable } = require('stream');
const simulatedInput = new Readable({
read() {
this.push('metric=cpu_usage value=0.5 host=web-01\n');
this.push('metric=memory_free value=1024 host=db-01\n');
this.push(null); // No more data
}
});
console.log('\n--- Streaming Parse Output ---');
simulatedInput
.pipe(logfmt.streamParser())
.pipe(through(function(obj) {
console.log('Streamed Object:', obj);
}));
// Expected: Streamed Object: { metric: 'cpu_usage', value: '0.5', host: 'web-01' }
// Expected: Streamed Object: { metric: 'memory_free', value: '1024', host: 'db-01' }