Logging best practices from nodejs
notoriouslisp
PROOP

19 days ago

I can search and view my logs well enough but was wondering what the best practice is for logging to the console so that logged json objects can be viewed in the key-value table when viewing a single log. Right now, each line of my log is its own separate log which is not ideal. And none of my logged objects show up in the key-value table.

Any guidance would be greatly appreciated! I've experimented with logging javascript objects directly to the console and also calling JSON.stringify(metadata) but neither seems to work better or worse.

$10 Bounty

2 Replies

Railway
BOT

19 days ago

Hey there! We've found the following might help you get unblocked faster:

If you find the answer from one of these, please let us know by solving the thread!


noahd
EMPLOYEE

19 days ago

This thread has been marked as public for community involvement, as it does not contain any sensitive or personal information. Any further activity in this thread will be visible to everyone.

Status changed to Open noahd 19 days ago


I typically use a library called Winston. It has something called a structured log transport that allows you to output logs as json so railway can understand the log level as well as all the attributes and give you the table view / query-able nature you're looking for in the log explorer.

After doing some research myself, I think your best options are either to use Pino or Winston. Node.js doesn't seem to have a comprehensive "structured logging" in the standard library. Pino is the newer player in the space and is higher performance, but Winston has been around longer / has more examples out there.

Code examples of Pino vs Winston

Pino code example

here's a super basic example of a logging setup in Pino

import pino from 'pino';

const logger = pino({
  level: 'trace', // minimum level to log
  timestamp: pino.stdTimeFunctions.isoTime,
});

// Standard levels (in order): trace, debug, info, warn, error, fatal
logger.trace({ detail: 'verbose' }, 'Trace message');
logger.debug({ requestId: 'abc-123' }, 'Debug message');
logger.info({ userId: 42, action: 'login' }, 'User logged in');
logger.warn({ latencyMs: 2500 }, 'Slow query detected');
logger.error({ err: new Error('Connection failed'), host: 'db-01' }, 'Database error');
logger.fatal({ exitCode: 1 }, 'Unrecoverable error, shutting down');

Winston code example

here's an example of the same thing in Winston:

import winston from 'winston';

const logger = winston.createLogger({
  level: 'silly', // minimum level to log
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  transports: [new winston.transports.Console()],
});

// Standard levels (in order): silly, debug, verbose, info, warn, error
logger.silly('Silly message', { detail: 'verbose' });
logger.debug('Debug message', { requestId: 'abc-123' });
logger.verbose('Verbose message', { extra: 'context' });
logger.info('User logged in', { userId: 42, action: 'login' });
logger.warn('Slow query detected', { latencyMs: 2500 });
logger.error('Database error', { err: new Error('Connection failed'), host: 'db-01' });

Loading...