/// import { IncomingMessage, RequestListener, ServerResponse } from 'http'; import { Socket } from 'net'; import pino from 'pino'; import { Writable } from 'stream'; import { err, req, res } from 'pino-std-serializers'; import pinoHttp, { AutoLoggingOptions, CustomAttributeKeys, GenReqId, HttpLogger, Options, ReqId, startTime, StdSerializers, StdSerializedResults } from '.'; interface CustomRequest extends IncomingMessage { context: number; } interface CustomResponse extends ServerResponse { context: number; } const logger = pino(); pinoHttp(); pinoHttp({ logger }); pinoHttp({ logger }).logger = logger; pinoHttp({ logger }); // #genReqId pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => req.statusCode || 200 }); pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => res.statusCode || 200 }); pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => 'foo' }); pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => Buffer.allocUnsafe(16) }); pinoHttp({ genReqId: (req: CustomRequest, res: CustomResponse) => Buffer.allocUnsafe(16) }); // #useLevel pinoHttp({ useLevel: 'error' }); // #transport pinoHttp({ transport: { target: 'pino-pretty', options: { colorize: true } } }); // #autologging pinoHttp({ autoLogging: false }); pinoHttp({ autoLogging: { ignore: (req: IncomingMessage) => req.headers['user-agent'] === 'ELB-HealthChecker/2.0' } }); pinoHttp({ autoLogging: { ignore: (req: CustomRequest) => req.headers['user-agent'] === 'ELB-HealthChecker/2.0' } }); // #customSuccessMessage pinoHttp({ customSuccessMessage: (req: IncomingMessage, res: ServerResponse) => 'Success' }); pinoHttp({ customSuccessMessage: (req: CustomRequest, res: CustomResponse) => 'Success' }); // #customErrorMessage pinoHttp({ customErrorMessage: (req: IncomingMessage, res: ServerResponse, error: Error) => `Error - ${error}` }); pinoHttp({ customErrorMessage: (req: CustomRequest, res: CustomResponse, error: Error) => `Error - ${error}` }); // #customAttributeKeys pinoHttp({ customAttributeKeys: { req: 'req' } }); pinoHttp({ customAttributeKeys: { res: 'res' } }); pinoHttp({ customAttributeKeys: { err: 'err' } }); pinoHttp({ customAttributeKeys: { responseTime: 'responseTime' } }); pinoHttp({ customAttributeKeys: { req: 'req', res: 'res', err: 'err', responseTime: 'responseTime' } }); // #customLogLevel pinoHttp({ customLogLevel: (req: IncomingMessage, res: ServerResponse, error: Error | undefined) => error ? 'error' : 'info' }); pinoHttp({ customLogLevel: (req: CustomRequest, res: CustomResponse, error: Error | undefined) => error ? 'error' : 'info' }); // #customProps pinoHttp({ customProps: (req: IncomingMessage, res: ServerResponse) => ({ key1: 'value1', 'x-key-2': 'value2' }) }); pinoHttp({ customProps: (req: CustomRequest, res: CustomResponse) => ({ key1: 'value1', 'x-key-2': 'value2' }) }); // #wrapSerializers pinoHttp({ wrapSerializers: false }); // streams pinoHttp(new Writable()); // #quietReqLogger + #customAttributeKeys pinoHttp({ quietReqLogger: true, customAttributeKeys: { reqId: 'reqId' }}); const rand = () => { let rtn = true; if (Math.random() < 0.5) rtn = false; return rtn; } const canBeUndefined = (input: T) => { if (rand()) return input; return undefined; } const rtnBool = () => { let rtn = true; if (rand()) rtn = false; return rtn; } const rtnLevel = () => { let rtn: pino.LevelWithSilent = 'debug'; if (rand()) { rtn = 'error'; } else if (rand()) { rtn = 'fatal'; } else if (rand()) { rtn = 'info'; } else if (rand()) { rtn = 'trace'; } else if (rand()) { rtn = 'warn'; } else if (rand()) { rtn = 'silent'; } return rtn; } const genReqId: GenReqId = () => { let rtn: ReqId = 123; if (rand()){ rtn = 'str'; } else { rtn = ({} as object); } return rtn; } const autoLoggingOptions = (() => { let rtn: AutoLoggingOptions | boolean = true; if (rand()) { rtn = { ignore: canBeUndefined(() => true), }; } else if (rand()) { rtn = false; } return rtn; })(); const customAttributeKeys: CustomAttributeKeys = { req: canBeUndefined('req'), res: canBeUndefined('res'), err: canBeUndefined('err'), reqId: canBeUndefined('reqId'), responseTime: canBeUndefined('responseTime'), } const options: Options = { logger: canBeUndefined(logger), genReqId: canBeUndefined(genReqId), useLevel: canBeUndefined(rtnLevel()), stream: canBeUndefined({ write: (msg: string) => { return } }), autoLogging: canBeUndefined(autoLoggingOptions), customLogLevel: canBeUndefined((req: IncomingMessage, res: ServerResponse, _error: Error | undefined) => rtnLevel()), customReceivedMessage: canBeUndefined((req, res) => { res.setHeader('x-custom-header-123', 'custom-header-value'); return `Received HTTP ${req.httpVersion} ${req.method}`; }), customSuccessMessage: canBeUndefined((req: IncomingMessage, res: ServerResponse) => 'successMessage'), customErrorMessage: canBeUndefined((req: IncomingMessage, res: ServerResponse, error: Error) => 'errorMessage'), customAttributeKeys: canBeUndefined(customAttributeKeys), wrapSerializers: canBeUndefined(rtnBool()), customProps: canBeUndefined((req: IncomingMessage, res: ServerResponse) => ({} as object)), quietReqLogger: canBeUndefined(rtnBool()), quietResLogger: canBeUndefined(rtnBool()), } // can't pass 'useLevel' and 'customLogLevel' together delete options.customLogLevel; const ph: HttpLogger = pinoHttp(options); const stdSerializers: StdSerializers = { err: err, req: req, res: res } const stdSerializedResults: StdSerializedResults = { err: { type: 'type', message: 'message', stack: 'stack', raw: new Error(), 'str': {}, 123: {}, }, req: { params: {}, query: {}, id: canBeUndefined('id'), method: 'GET', url: 'http://0.0.0.0', headers: { header: 'header' }, remoteAddress: '0.0.0.0:80', remotePort: 80, raw: new IncomingMessage(new Socket()), }, res: { statusCode: 200, headers: { header: 'header' }, raw: new ServerResponse(new IncomingMessage(new Socket())), }, }; const httpServerListener: RequestListener = (request, response) => { // req.log and req.id should be available request.log.info(`Request received with request ID ${request.id}`); request.allLogs[0].info("Request Received"); // res[startTime] should be available response[startTime] = Date.now(); // res.log and res.allLogs should be available response.log.info("Logging works on response"); request.allLogs[0].info("allLogs available on response"); response.end("Hello world"); }; // custom levels added in the options should be available // on the logger returned by pino-http pinoHttp({ customLevels: { bark: 25, } }).logger.bark("arf arf"); // customLevels in parent pino instance should be not cause // TypeScript errors const customLogger = pino({ customLevels: { bark: 25, } }); pinoHttp({ logger: customLogger }).logger.bark("arf arf"); pinoHttp({ logger: customLogger, useLevel: 'bark' }) pinoHttp({ logger: customLogger, customLogLevel: () => 'bark' })