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.
2 Replies
19 days ago
Hey there! We've found the following might help you get unblocked faster:
📚 Deploy Node.js & Express API with Autoscaling, Secrets, and Zero Downtime
🧵 MCP service not executing updated server.js code after successful redeploy
If you find the answer from one of these, please let us know by solving the thread!
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
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' });