рдпрд╣рд╛рдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рдорд╕реНрдпрд╛ рдХреБрдЫ рдЬрдЯрд┐рд▓ рд╣реИ рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рд╣рдо рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдорд╛рдВрдЧ рд░рд╣реЗ рд╣реИрдВ -- рд╣рдо рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рдХреЗ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЬреЗрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рдорд╛рдиреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 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рд╡рд┐рдВрд╕реНрдЯрди рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХрдбреНрд░рд╛рдЗрд╡рд░ рд▓реЙрдЧрд┐рдВрдЧ рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдХреЗ рд▓реЗрдЦрдХ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рд▓реЙрдЧ-рдЕрдиреБрд░реЛрдз рд╕рд╣рд╕рдВрдмрдВрдз рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред 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
рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдердВрдХ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ (рд╢рд╛рдпрдж рд╣рдорд╛рд░рд╛ рдореЙрдбреНрдпреВрд▓ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ рдЙрдиреНрд╣реЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП)ред
рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдкрд░ рдлрд╝реАрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ рд╣реЛрдЧрд╛
рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдЗрд╕реЗ 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 рджреНрд╡рд╛рд░рд╛ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдореБрдЭреЗ рдПрдХ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдорд┐рд▓рд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рддрдм рддрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ - рдЧреЗрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
UPD: @mooski . рджреНрд╡рд╛рд░рд╛ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдмрдЧ рдХреЛ рдареАрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛