pinojs / pino-pretty

🌲Basic prettifier for Pino log lines
MIT License
1.25k stars 147 forks source link

Doesn't seem to work with pinoms #383

Closed webhype closed 1 year ago

webhype commented 1 year ago

The following code fails the 2nd test ... it creates a file of zero-byte size always:

import childProcess from "child_process";
import fs from "fs-extra";
import os from "os";
import path from "path";
import stream from "stream";
import pino from "pino";
import pinoms from "pino-multi-stream";
import util from "util";

const setTimeoutPromise = util.promisify(setTimeout);

const logThrough = new stream.PassThrough();

const TEE_PATH = path.join(process.cwd(), "node_modules", "pino-tee", "tee.js");
const LOG_DIR = ".";

class MyLogger {
    logger: pino.Logger;
    constructor(
        {viaTee, viaPretty, pathName}:
        {viaTee: boolean, viaPretty: boolean, pathName: string}
    ) {
        const level: pino.LevelWithSilent = "trace";

        const streams = [];

        if (viaPretty) {
            streams.push({
                level,
                stream: pinoms.prettyStream({   // ONLY CONSOLE OUTPUT SENT THROUGH THIS
                    prettifier: (opts: {[key: string]: any}) => { return (inputData: {
                        [key: string]: string | number;
                    }) => String(inputData.msg) + ":::"; }, // if left out, uses standard prettifier
                    dest: viaTee
                        ? logThrough
                        : fs.createWriteStream(pathName),
                }),
            });
        } else {
            streams.push({
                level,
                stream: logThrough,
            })
        }
        this.logger = pinoms({streams});
        this.logger.level = "trace";

        if (viaTee) {
            const child = childProcess.spawn(process.execPath, [    // node command
                TEE_PATH,
                "trace", pathName,
            ], {
                cwd: process.cwd(),
                env: process.env
            });
            logThrough.pipe(child.stdin);   // now pipe ugly output to tee's stdin
            child.stdout.resume();  // See https://github.com/nodejs/node/issues/42630
        }
    }
}

(async () => {
    // This works as expected
    console.log("Test1: SUCCEEDS!");
    const myLogger1 = new MyLogger({
        viaTee: false,
        viaPretty: true,
        pathName: path.join(LOG_DIR, "test-1-writestream-pretty.log")
    });
    myLogger1.logger.trace({msg: "Test1: Written via fs.createWriteStream()" + os.EOL});

    // This fails: file has zero bytes when streaming through prettifier, then tee
    const pathName = path.join(LOG_DIR, "test-2-tee-pretty-ZERO-BYTES.log");
    console.log(`Test2: FAILS! Writes 0 bytes to ${pathName}`);
    const myLogger2 = new MyLogger({
        viaTee: true,
        viaPretty: true,
        pathName
    });
    myLogger2.logger.trace({msg: "Test2: Written via tee" + os.EOL});

    // This works as expected
    console.log("Test3: SUCCEEDS!");
    const myLogger3 = new MyLogger({
        viaTee: true,
        viaPretty: false,
        pathName: path.join(LOG_DIR, "test-3-tee-notpretty.log")
    });
    myLogger3.logger.trace({msg: "Test3: Written via tee works, but not pretty" + os.EOL});

    // Wait for buffers to flush
    await setTimeoutPromise(5000);
    process.exit(0);
})();

Perhaps this is a pinoms issue instead but that repo is archived so not sure where the correct place would be to open this issue. Would also appreciate a workaround if known. Thanks!

jsumners commented 1 year ago

pino-multi-stream is no longer supported. That functionality is now built in to pino -- https://getpino.io/#/docs/api?id=pino-multistream

webhype commented 1 year ago

Thank you, that's great news. You still have references to pino-multi-stream strewn in some .md pages, just FYI. Also, my code can't possibly work because my prettifier destroys the jsonl formatting so there's nothing for pino-tee to parse, and it fails quietly. 😃 Thanks for the response!