pino-pretty icon indicating copy to clipboard operation
pino-pretty copied to clipboard

Programmatic Integration - Production Mode

Open laurenzhonauer opened this issue 2 years ago • 4 comments

Description

In the Readme under Programmatic Integration it is stated that pino-pretty should be added as dev-dependency and then be configured as following:

const pino = require('pino')
const logger = pino({
  transport: {
    target: 'pino-pretty'
  },
})

logger.info('hi')

If one would follow those steps exactly, they would get following error in Production.

Error: Cannot find module 'pino-pretty'
Require stack:
- /workspace/.next/server/chunks/617.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.mod._resolveFilename (/workspace/node_modules/next/dist/build/webpack/require-hook.js:171:28)
    at Function.resolve (node:internal/modules/cjs/helpers:100:19)
    at fixTarget (/workspace/node_modules/pino/lib/transport.js:128:30)
    at transport (/workspace/node_modules/pino/lib/transport.js:111:22)
    at normalizeArgs (/workspace/node_modules/pino/lib/tools.js:409:16)
    at pino (/workspace/node_modules/pino/pino.js:84:28)
    at Object.4724 (/workspace/.next/server/chunks/617.js:114:59)
    at __webpack_require__ (/workspace/.next/server/webpack-api-runtime.js:25:42)
    at Object.73 (/workspace/.next/server/chunks/617.js:17:65) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/workspace/.next/server/chunks/617.js'
  ]
}

Steps to reproduce

  1. Create some node program that can use pino
  2. Follow the programmatic integration guide
  3. set NODE_ENV to production (in Linux: export NODE_ENV=production)
  4. run npm ci
  5. run npm start

Expected Result

Pino should print un-prettified messages

Actual Result

Error is thrown due to missing pino-pretty (Because it is only a dev dependency)

Proposal

I guess the Documentation just needs to say that the transport option should only be added after a NODE_ENV check. Maybe its enough to just add that to the Readme. If you accept that i can create a pr myself :)

laurenzhonauer avatar Jan 11 '22 10:01 laurenzhonauer

Don't use NODE_ENV, it's an antipattern that results in production issues and it makes it harder to debug things. We do not recommend that for this reason. The best way to handle this is to use dotenv and have PINO_PRETTY env to trigger this on and off.

mcollina avatar Jan 11 '22 10:01 mcollina

Yes I agree with you. But I think this is not mentioned in the documentation.

So if you create blank node program, add pino and follow the programmatic integration documentation for pino-pretty, you will get the error automatically. With blank programm i mean, no extra dependencies, so no dotenv (I assume you mean this).

Also I would argue that the majority of people are not using dotenv and are relying on NODE_ENV - antipattern or not. (For example Next.js relies on NODE_ENV out of the box)

Anyway, could you provide a piece of example code that connects the dots between pino-pretty and dotenv. That would be very helpful :)

laurenzhonauer avatar Jan 11 '22 11:01 laurenzhonauer

Unfortuantely I do not have much time. Some piece of docs around this would be great, feel free to send a PR but do not mention NODE_ENV.

mcollina avatar Jan 11 '22 12:01 mcollina

Fair enough, in that case even bigger thanks for taking the time to look over the issue.

I will try to find some time to create a pr for this.

In case anyone stumbles upon this, before a pr is open - Feel free ^^

laurenzhonauer avatar Jan 11 '22 14:01 laurenzhonauer

Thanks @laurenzhonauer for the info - if I had not stumbled upon this probably wouldn't have been able to fix my own issue

etiennejcharles avatar Apr 18 '23 12:04 etiennejcharles

just for anyone reading:

import pino from "pino";

import { env } from "@/env.mjs";

const levelFormatter = (_: unknown, number: number): { severity: string } => {
  let severity;
  switch (number) {
    case 10:
    case 20: {
      severity = "DEBUG";
      break;
    }

    case 30: {
      severity = "INFO";
      break;
    }

    case 40: {
      severity = "WARNING";
      break;
    }

    case 50: {
      severity = "ERROR";
      break;
    }

    case 60: {
      severity = "CRITICAL";
      break;
    }

    default: {
      severity = "DEFAULT";
      break;
    }
  }

  return { severity };
};

const timestampFunction = (): string =>
  `,"timestamp":"${new Date().toISOString()}"`;

const prodOptions: pino.LoggerOptions = {
  base: undefined,
  formatters: {
    level: levelFormatter,
  },
  messageKey: "message",
  timestamp: timestampFunction,
};

const getDevStream = (): pino.DestinationStream => {
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
  const pretty = require("pino-pretty");

  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
  return pretty({
    levelFirst: true,
    colorize: true,
    ignore: "time,hostname,pid",
  }) as pino.DestinationStream;
};

export const logger =
  env.NODE_ENV === "production"
    ? pino(prodOptions)
    : pino({ level: "debug" }, getDevStream());

sinisastanic avatar Oct 25 '23 16:10 sinisastanic