javascripttypescriptwinstonnuxt3.js

Add Winston Logging to Nuxt3


Winston is a logging framework that we want to use in our Nuxt3 application, but the Winston package from Nuxt is still only available for Nuxt2. There is sparse documentation on getting this particular combination of tools working.

I tried pulling in the Nuxt Winston package anyway (https://www.npmjs.com/package/nuxt-winston-log), but that did not work as expected.

Note that this is only for logging in Nuxt's SSR functionality ("server-side rendering"). I'm not trying to get Winston to log from the client side.


Solution

  • So in this case, we just want to use Winston directly:

    Step 1

    Run yarn add winston

    Step 2

    Create a server-side plugin. Prefix the file with 00. since plugins are loaded in alphabetical order, and you'll likely want your logging available in your other plugins. Suffix with .server.ts so that this only tries to run on the server side; Winston isn't meant for use on client side. Filename: plugins/00.logging.server.ts

    import { defineNuxtPlugin } from "#app";
    import winston from "winston";
    
    export default defineNuxtPlugin(() => {
      const logger = winston.createLogger({
        level: 'info',
        format: winston.format.combine(winston.format.printf((event) => {
          return `${JSON.stringify({ ...event, timestamp: new Date().toISOString() }, null, 4)}\n`;
        })),
        defaultMeta: { service: 'myappname' },
        transports: [
          new winston.transports.Console()
        ],
      });
    
      return {
        provide: {
          logger
        }
      }
    });
    

    Step 3 (Optional)

    For ease of use and so that a single logging function can be called from both the frontend and the backend, build some composables. Filename: composables/logging.ts

    export function logServerError(err: any, message?: string) {
      const nuxtApp = useNuxtApp();
      if (process?.server && nuxtApp.$logger) {
        nuxtApp.$logger.log("error", message, err);
      } else {
        console.error("We Have Encountered an ERROR: ", err);
      }
    }
    
    export function logServerWarn(message: string) {
      const nuxtApp = useNuxtApp();
      if (process?.server && nuxtApp.$logger) {
        nuxtApp.$logger.log("warn", message);
      } else {
        console.warn(message);
      }
    }
    
    export function logServerInfo(message: string) {
      const nuxtApp = useNuxtApp();
      if (process?.server && nuxtApp.$logger) {
        nuxtApp.$logger.log("info", message);
      } else {
        console.info(message);
      }
    }
    

    Step 4 (If you did Step 3)

    Use the logger. Filename: plugins/50.myplugin.js

    export default defineNuxtPlugin(async (nuxtApp) => {
    
      // do stuff to setup my app
    
      // do more stuff
    
      logServerInfo("Plugin operations complete");
    });
    

    Notes