Winston: рдЕрдиреБрд░реЛрдз: рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдореЗрдВ рдХрд╛рд░реНрдп

рдХреЛ рдирд┐рд░реНрдорд┐рдд 29 рдорд╛рд░реНрдЪ 2019  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: winstonjs/winston

рдпрд╣рд╛рдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рдорд╕реНрдпрд╛ рдХреБрдЫ рдЬрдЯрд┐рд▓ рд╣реИ рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рд╣рдо рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдорд╛рдВрдЧ рд░рд╣реЗ рд╣реИрдВ -- рд╣рдо рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рдХреЗ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЬреЗрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рдорд╛рдиреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП defaultMetadata рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рджреЗрдЦрдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

const logger = createLogger({
  defaultMeta: {
    // Function to be evaluated every time a log is written.
    timeWritten: () => { return `Date.now()`; }
  },
  // ...
});

рдкреВрд░реНрдг рдФрдЪрд┐рддреНрдп рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рджреЗрдЦреЗрдВред

рдХреГрдкрдпрд╛ рд╣рдореЗрдВ рдЕрдкрдиреЗ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдПрдВ:

  • _ winston рд╕рдВрд╕реНрдХрд░рдг?_

    • [ ] winston@2

    • [рдПрдХреНрд╕] winston@3

  • _ node -v рдЖрдЙрдЯрдкреБрдЯ:_ v10.15.2
  • _рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо?_ macOS (рдЕрдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ)
  • _рднрд╛рд╖рд╛?_ ES7 (рдЕрдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ)

рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реИ?

рд╡рд┐рдВрд╕реНрдЯрди рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХрдбреНрд░рд╛рдЗрд╡рд░ рд▓реЙрдЧрд┐рдВрдЧ рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдХреЗ рд▓реЗрдЦрдХ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рд▓реЙрдЧ-рдЕрдиреБрд░реЛрдз рд╕рд╣рд╕рдВрдмрдВрдз рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред async_hooks рдореЙрдбреНрдпреВрд▓ рд╣рдореЗрдВ рдЕрдиреБрд░реЛрдз-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЬрд╛рдирдХрд╛рд░реА рдЬреИрд╕реЗ рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рджреЗрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Transport рдХреА рдУрд░ рд╕реЗ рдЗрд╕реЗ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рд╕рд╛рдзрди рдирд╣реАрдВ рд╣реИред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рджреНрд╡рд╛рд░рд╛ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдирд┐рдореНрди рдХреЛрдб рдЗрд╕ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рддрдм рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рдЬрдм ~ 100 рдЕрдиреБрд░реЛрдз рддреНрд╡рд░рд┐рдд рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░ рдореЗрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:

const ah = require('async_hooks');
const express = require('express');
const { createLogger } = require('winston');
const TransportStream = require('winston-transport');

// Activate async hooks.
let requestIdHighWater = 0;
const requestIdTable = {};
ah.createHook({
  init: (child, resource, parent) => {
    requestIdTable[child] = requestIdTable[parent];
  }
}).enable();

// OUR CODE

class MyTransport extends TransportStream {
  log(info, next) {
    // From the transport, the request ID is not reliable.
    const actualRequestId = requestIdTable[ah.executionAsyncId()];
    console.log(`Expected: ${info.expectedRequestId}, Actual: ${actualRequestId}`);
    setImmediate(next);
  }
}

// OUR USER'S CODE

const logger = createLogger({
  transports: [new MyTransport()]
});

const app = express();

app.get('/', async (req, res) => {
  // Store a request ID.
  const requestId = requestIdHighWater++;
  requestIdTable[ah.executionAsyncId()] = requestId;
  logger.info('hello', { expectedRequestId: requestId });
  res.sendStatus(200);
});

app.listen(3000);

"рдЕрдкреЗрдХреНрд╖рд┐рдд" рдФрд░ "рд╡рд╛рд╕реНрддрд╡рд┐рдХ" рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдореЗрдВ рдмреЗрдореЗрд▓ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред рдпрджрд┐ рд╣рдо MyTransport рдХреЗ рд▓реЗрдЦрдХ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд░реНрддрдорд╛рди рдирд┐рд╖реНрдкрд╛рджрди рдЖрдИрдбреА ("рд╡рд╛рд╕реНрддрд╡рд┐рдХ") рд╕реЗ рдкрд░рд╛рдорд░реНрд╢ рдХрд░рдХреЗ рд╕рд╣реА рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдореЗрдВ рдореЗрдЯрд╛рдбреЗрдЯрд╛ ("рдЕрдкреЗрдХреНрд╖рд┐рдд") рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд╣реА рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╡рд┐рдВрд╕реНрдЯрди 3 рдмреИрдЪ рд▓реЙрдЧ рдХрд░рддрд╛ рд╣реИ ( readable-stream рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рдЬрдм рдХреЛрдИ рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдЕрдкрдиреЗ log рдХреЙрд▓рдмреИрдХ рдХреЗ рдЖрд╣реНрд╡рд╛рди рдХреЛ рд╕реНрдердЧрд┐рдд рдХрд░ рджреЗрддрд╛ рд╣реИред

рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЕрдкрдиреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдкрд░ рднрд░реЛрд╕рд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ; рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╣реЛред рдЖрдЦрд┐рд░рдХрд╛рд░, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╢рд╛рдпрдж рдХреЗрд╡рд▓ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ

app.get('/', async (req, res) => {
  logger.info('hello');
  res.sendStatus(200);
});

рдФрд░ рд╣рдорд╛рд░реЗ рдКрдкрд░ рд╡рд┐рд╢реНрд░рд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджреЛред

рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЖрдк рдХреНрдпрд╛ рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ?

рдЕрдкреЗрдХреНрд╖рд┐рдд рдФрд░ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА (рд▓рд┐рдВрдХ рдХрд┐рдП рдЧрдП рдЖрдЙрдЯрдкреБрдЯ рд╕реЗ) рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред

рдЕрдиреНрдп рд╕реВрдЪрдирд╛

рдХреЛрдб рдХреЛ рдареАрдХ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ рддрд╛рдХрд┐ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдореЗрд▓ рдЦрд╛ рд╕рдХреЗрдВ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ defaultMetadata рдкрд░ рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рд▓реЙрдЧрд░ рдХреЛ рдХреЙрд▓ рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдЗрд╕ рддрд░рд╣, рдХреЛрдб рдЗрд╕ рдореЗрдВ рдмрджрд▓ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрд┐рд╕реА рднреА рдЬрд╛рдЧрд░реВрдХрддрд╛ рдХреЗ рдмрд┐рдирд╛ рдЕрдкрдирд╛ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЫреЛрдЯреЗ рдЪреЗрддрд╛рд╡рдиреА рдХреЗ рд╕рд╛рде рдХрд┐ рд╡реЗ defaultMetadata рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдердВрдХ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ (рд╢рд╛рдпрдж рд╣рдорд╛рд░рд╛ рдореЙрдбреНрдпреВрд▓ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ рдЙрдиреНрд╣реЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП)ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдореБрдЭреЗ рдПрдХ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдорд┐рд▓рд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рддрдм рддрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ - рдЧреЗрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

const logger = createLogger({
  defaultMeta: {
    get timeWritten () { return `Date.now()`; }
  },
  // ...
});

UPD: @mooski . рджреНрд╡рд╛рд░рд╛ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдмрдЧ рдХреЛ рдареАрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛

рд╕рднреА 3 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдкрд░ рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ рд╣реЛрдЧрд╛

рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдЗрд╕реЗ redux thunks рдХреЗ рд╕рдорд╛рди рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред defaultMetadata рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди-рдореВрд▓реНрдпрд╡рд╛рди рд╕рдВрдкрддреНрддрд┐ рд╣реЛрдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдпрд╣ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ defaultMetadata рд╕реНрд╡рдпрдВ рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рдердВрдХ рдХреА рддрд░рд╣, winston рдРрд╕реЗ рдорд╛рдорд▓реЗ рдореЗрдВ defaultMetadata рдХрд╛ рдЖрд╣реНрд╡рд╛рди рдХрд░рдХреЗ рд▓реМрдЯрд╛рдП рдЧрдП рдореВрд▓реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ:

const logger = createLogger({
  defaultMeta: () => {
    // Function to be evaluated every time a log is written.
    return {
       timeWritten: Date.now();
       // ..
    }
  }
  // ...
});

рдореБрдЭреЗ рдПрдХ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдорд┐рд▓рд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рддрдм рддрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ - рдЧреЗрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

const logger = createLogger({
  defaultMeta: {
    get timeWritten () { return `Date.now()`; }
  },
  // ...
});

UPD: @mooski . рджреНрд╡рд╛рд░рд╛ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдмрдЧ рдХреЛ рдареАрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛

~ рдорд╣рд╛рди рд╕рдорд╛рдзрд╛рди @Alexsey - рдЗрд╕ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рднреА рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдмрд╕ рдЗрд╕ рдмрд╛рдд рд╕реЗ рдЕрд╡рдЧрдд рд░рд╣реЗрдВ рдХрд┐ timeWritten рдХреЗ рдмрд╛рдж рдХреЛрд▓рди рд╡рд╣рд╛рдВ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред~

рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ: @Alexsey рджреНрд╡рд╛рд░рд╛ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

amiram picture amiram  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

sinai-doron picture sinai-doron  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

KingRial picture KingRial  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Tonacatecuhtli picture Tonacatecuhtli  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

pocesar picture pocesar  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ