How to best Log in Railway (Winston? etc...)
pezzullig
PROOP

a year ago

I am trying to improve my logging and I see that Railway uses Winston to automatically add serviceId and timestamp etc. I have decided to add extra customised fields and thus I am using Winston to add to it.

Here is my logger:

import { createLogger, format, transports } from 'winston';

// Define some custom colors for your custom tokens
const customColors = {
  user_id: 'magenta',
  user_email: 'magenta',
  route: 'cyan',
  method: 'cyan',
  // etc.
};

// Create a colorizer with addColors
const colorizer = format.colorize();
colorizer.addColors(customColors);

const colorLevel = (level) => {
  switch (level) {
    case 'info':
      // Green
      return `\x1b[32m${level}\x1b[0m`;
    case 'warn':
      // Yellow
      return `\x1b[33m${level}\x1b[0m`;
    case 'error':
      // Red
      return `\x1b[31m${level}\x1b[0m`;
    default:
      // No color for other levels
      return `\x1b[32m${level}\x1b[0m`;
  }
};

// The function that replicates your printf logic, but returns info
// (instead of a final string).
const mutateMessageFormat = format((info) => {
  const { level, message, timestamp, route, method, user_id, user_email } =
    info;

  // Colorize the level
  const coloredLevel = colorLevel(level);

  // Build your custom base string, with the colored level in brackets
  const base = `${timestamp} [${coloredLevel}]`;

  // Conditionally append user info if present
  const userInfo = user_id
    ? ` ${colorizer.colorize(
        'user_id',
        `user:${user_id}`
      )}${user_email ? colorizer.colorize('user_email', ` ${user_email}`) : ''}`
    : '';

  // Conditionally append request info if present
  const requestInfo =
    route && method
      ? ` (${colorizer.colorize('method', method)} ${colorizer.colorize(
          'route',
          route
        )})`
      : '';

  // Mutate the log message in place, combining your custom string logic
  info.message = `${base}${userInfo}${requestInfo} - ${message}`;

  // Return `info` so Winston passes it along the pipeline
  return info;
});

const getFormattedTimestamp = () => {
  const now = new Date();
  const utcTime = now.toLocaleString('en-US', {
    timeZone: 'UTC',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });
  const dubaiTime = now.toLocaleString('en-US', {
    timeZone: 'Asia/Dubai',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  });
  return `${utcTime} UTC (${dubaiTime} GST)`;
};

// Create a Winston logger that ultimately logs in JSON format
const logger = createLogger({
  level: 'info',
  format: format.combine(
    // Attach a timestamp
    format.timestamp({ format: getFormattedTimestamp }),
    // Mutate the message with your fancy string
    mutateMessageFormat(),
    // Finally, serialize EVERYTHING to JSON
    format.json()
  ),
  transports: [
    new transports.Console({
      stderrLevels: ['error', 'warn'],
    }),
  ],
});

export default logger;

Note to Railway: I have noticed however that I have to use the format.json() in order for the fields to be added. - i cant use printf()

Secondly I have noticed the performance of the search to be poor at large timescales (1+ days ). sometimes it doesn't even load.

I'm worried I am overridding Railway default Transports or some other Winston Config that I should do.

Can someone or the Railway Team confirm how best to use Winston with Railway and if my transports are missing something or if I need to add my own method of chunking log sizes or similar.

Solved

4 Replies

chandrika
EMPLOYEE

a year ago

Using Winston with format.json() seems sound to me, we have documentation on using structured logging with Railway which might be helpful: https://docs.railway.com/guides/logs#structured-logs

Regarding the poor search performance, could you please share a screen recording of the experience — trying to replicate it on my end


Status changed to Awaiting User Response Railway about 1 year ago


pezzullig
PROOP

a year ago


Status changed to Awaiting Railway Response Railway about 1 year ago


pezzullig
PROOP

a year ago

in fact in the network tab i get this error:

{errors: [{message: "Problem processing request", traceId: "313275324907175545"}], data: null}


chandrika
EMPLOYEE

a year ago

This is super helpful, thank you Giulio! I’ve raised it with the team and we’ll look into why it’s particularly slow here


Status changed to Awaiting User Response Railway about 1 year ago


Railway
BOT

7 months ago

This thread has been marked as solved automatically due to a lack of recent activity. Please re-open this thread or create a new one if you require further assistance. Thank you!

Status changed to Solved Railway 7 months ago


Loading...