pinojs / pino

🌲 super fast, all natural json logger
http://getpino.io
MIT License
14.07k stars 867 forks source link

[snippet] Windows. Encoding on Unicode output #1722

Open alexv-ds opened 1 year ago

alexv-ds commented 1 year ago

I faced the problem of outputting Cyrillic letters to the console via the pino logger. This has been discussed here -> #548. I present my solution. Perhaps someone will need it.

Tested on node v20.2.0

log.info('Привет мир'); //[08:34:59.796] INFO (11528): ╨Я╤А╨╕╨▓╨╡╤В ╨╝╨╕╤А

Using the ffi-napi module.

import ffi from 'ffi-napi';
if (os.platform() === 'win32') {
  const kernel = ffi.Library('Kernel32', {
    'SetConsoleOutputCP' : [ffi.types.bool, [ffi.types.uint]],
    'SetConsoleCP' : [ffi.types.bool, [ffi.types.uint]]
  });
  const CP_UTF8 = 65001;
  kernel.SetConsoleOutputCP(CP_UTF8);
  kernel.SetConsoleCP(CP_UTF8);
}

and result

log.info('Привет мир');  //[08:35:16.610] INFO (13792): Привет мир
mcollina commented 1 year ago

This is amazing! What are those two APIs? I have a feeling we might want to expose them on Node.js itself.

alexv-ds commented 1 year ago

@mcollina I do not understand the question😅, please reword it, english is not my native tongue.

mcollina commented 1 year ago

No worries, I did a bit a googling and found my answer!

Thanks!

Would you like to send a PR to add those to our docs? https://github.com/pinojs/pino/blob/master/docs/help.md would be a good page.

vitalygashkov commented 3 weeks ago

ffi-napi module didn't work for me, so I used koffi:

import koffi from 'koffi';

if (process.platform === 'win32') {
  const CP_UTF8 = 65001;
  const kernel32 = koffi.load('Kernel32');
  const setConsoleOutputCP = kernel32.func('SetConsoleOutputCP', 'bool', ['int']);
  const setConsoleCP = kernel32.func('SetConsoleCP', 'bool', ['int']);
  setConsoleOutputCP(CP_UTF8);
  setConsoleCP(CP_UTF8);
}
vitalygashkov commented 2 weeks ago

For those who don't want to carry several megabytes of modules from the koffi library into the project, you can use native Node.js streams. Here is an example with two streams - one outputs data to the console and the other writes logs to a file:

const pino = require('pino');
const pretty = require('pino-pretty');

const fileStream = createWriteStream('log.txt', { flags: 'a' });
const consoleStream = pretty({ colorize: true, destination: process.stdout });
const streams = [{ level: 'debug', stream: fileStream }, { level: 'info', stream: consoleStream }]
const logger = pino({ level: 'info' }, pino.multistream(streams));

But with this approach SonicBoom will not be used and accordingly the speed of pino will be lower.