Comparing version 8.3.1 to 8.5.1
@@ -14,2 +14,7 @@ import { expectType } from 'tsd'; | ||
expectType<HttpLogger>(pinoHttp({ logger })); | ||
expectType<HttpLogger>(pinoHttp({ | ||
customSuccessMessage(req, res, responseTime) { | ||
return `${responseTime}` | ||
} | ||
})); | ||
expectType<HttpLogger>(pinoHttpNamed()); | ||
@@ -16,0 +21,0 @@ expectType<HttpLogger>(pinoHttpStar.default()); |
@@ -15,37 +15,37 @@ // Project: https://github.com/pinojs/pino-http#readme | ||
declare function PinoHttp(opts?: Options, stream?: pino.DestinationStream): HttpLogger; | ||
declare function PinoHttp<IM = IncomingMessage, SR = ServerResponse, Opts = Options<IM, SR>>(opts?: Opts, stream?: pino.DestinationStream): HttpLogger<IM, SR, Opts>; | ||
declare function PinoHttp(stream?: pino.DestinationStream): HttpLogger; | ||
declare function PinoHttp<IM = IncomingMessage, SR = ServerResponse>(stream?: pino.DestinationStream): HttpLogger<IM, SR>; | ||
export interface HttpLogger { | ||
(req: IncomingMessage, res: ServerResponse, next?: () => void): void; | ||
logger: pino.Logger; | ||
export interface HttpLogger<IM = IncomingMessage, SR = ServerResponse, Opts = Options<IM, SR>> { | ||
(req: IM, res: SR, next?: () => void): void; | ||
logger: pino.Logger<Opts>; | ||
} | ||
export type ReqId = number | string | object; | ||
export interface Options extends pino.LoggerOptions { | ||
export interface Options<IM = IncomingMessage, SR = ServerResponse> extends pino.LoggerOptions { | ||
logger?: pino.Logger | undefined; | ||
genReqId?: GenReqId | undefined; | ||
genReqId?: GenReqId<IM, SR> | undefined; | ||
useLevel?: pino.LevelWithSilent | undefined; | ||
stream?: pino.DestinationStream | undefined; | ||
autoLogging?: boolean | AutoLoggingOptions | undefined; | ||
customLogLevel?: ((req: IncomingMessage, res: ServerResponse, error?: Error) => pino.LevelWithSilent) | undefined; | ||
customReceivedMessage?: ((req: IncomingMessage, res: ServerResponse) => string) | undefined; | ||
customSuccessMessage?: ((req: IncomingMessage, res: ServerResponse) => string) | undefined; | ||
customErrorMessage?: ((req: IncomingMessage, res: ServerResponse, error: Error) => string) | undefined; | ||
customReceivedObject?: ((req: IncomingMessage, res: ServerResponse, val?: any) => any) | undefined; | ||
customSuccessObject?: ((req: IncomingMessage, res: ServerResponse, val: any) => any) | undefined; | ||
customErrorObject?: ((req: IncomingMessage, res: ServerResponse, error: Error, val: any) => any) | undefined; | ||
autoLogging?: boolean | AutoLoggingOptions<IM> | undefined; | ||
customLogLevel?: ((req: IM, res: SR, error?: Error) => pino.LevelWithSilent) | undefined; | ||
customReceivedMessage?: ((req: IM, res: SR) => string) | undefined; | ||
customSuccessMessage?: ((req: IM, res: SR, responseTime: number) => string) | undefined; | ||
customErrorMessage?: ((req: IM, res: SR, error: Error) => string) | undefined; | ||
customReceivedObject?: ((req: IM, res: SR, val?: any) => any) | undefined; | ||
customSuccessObject?: ((req: IM, res: SR, val: any) => any) | undefined; | ||
customErrorObject?: ((req: IM, res: SR, error: Error, val: any) => any) | undefined; | ||
customAttributeKeys?: CustomAttributeKeys | undefined; | ||
wrapSerializers?: boolean | undefined; | ||
customProps?: ((req: IncomingMessage, res: ServerResponse) => object) | undefined; | ||
customProps?: ((req: IM, res: SR) => object) | undefined; | ||
quietReqLogger?: boolean | undefined; | ||
} | ||
export interface GenReqId { | ||
(req: IncomingMessage, res: ServerResponse): ReqId; | ||
export interface GenReqId<IM = IncomingMessage, SR = ServerResponse> { | ||
(req: IM, res: SR): ReqId; | ||
} | ||
export interface AutoLoggingOptions { | ||
ignore?: ((req: IncomingMessage) => boolean); | ||
export interface AutoLoggingOptions<IM = IncomingMessage> { | ||
ignore?: ((req: IM) => boolean); | ||
} | ||
@@ -93,3 +93,5 @@ | ||
[startTime]: number; | ||
log: pino.Logger; | ||
allLogs: pino.Logger[]; | ||
} | ||
} |
@@ -11,2 +11,10 @@ | ||
interface CustomRequest extends IncomingMessage { | ||
context: number; | ||
} | ||
interface CustomResponse extends ServerResponse { | ||
context: number; | ||
} | ||
const logger = pino(); | ||
@@ -17,2 +25,5 @@ | ||
pinoHttp({ logger }).logger = logger; | ||
pinoHttp<CustomRequest, CustomResponse>({ logger }); | ||
// #genReqId | ||
pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => req.statusCode || 200 }); | ||
@@ -22,8 +33,24 @@ pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => res.statusCode || 200 }); | ||
pinoHttp({ genReqId: (req: IncomingMessage, res: ServerResponse) => Buffer.allocUnsafe(16) }); | ||
pinoHttp<CustomRequest, CustomResponse>({ 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<CustomRequest>({ autoLogging: { ignore: (req: CustomRequest) => req.headers['user-agent'] === 'ELB-HealthChecker/2.0' } }); | ||
// #customSuccessMessage | ||
pinoHttp({ customSuccessMessage: (req: IncomingMessage, res: ServerResponse) => 'Success' }); | ||
pinoHttp<CustomRequest, CustomResponse>({ customSuccessMessage: (req: CustomRequest, res: CustomResponse) => 'Success' }); | ||
// #customErrorMessage | ||
pinoHttp({ customErrorMessage: (req: IncomingMessage, res: ServerResponse, error: Error) => `Error - ${error}` }); | ||
pinoHttp<CustomRequest, CustomResponse>({ customErrorMessage: (req: CustomRequest, res: CustomResponse, error: Error) => `Error - ${error}` }); | ||
// #customAttributeKeys | ||
pinoHttp({ customAttributeKeys: { req: 'req' } }); | ||
@@ -34,6 +61,18 @@ pinoHttp({ customAttributeKeys: { res: 'res' } }); | ||
pinoHttp({ customAttributeKeys: { req: 'req', res: 'res', err: 'err', responseTime: 'responseTime' } }); | ||
// #customLogLevel | ||
pinoHttp({ customLogLevel: (req: IncomingMessage, res: ServerResponse, error: Error | undefined) => error ? 'error' : 'info' }); | ||
pinoHttp<CustomRequest, CustomResponse>({ 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<CustomRequest, CustomResponse>({ 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' }}); | ||
@@ -145,2 +184,4 @@ | ||
req: { | ||
params: {}, | ||
query: {}, | ||
id: canBeUndefined('id'), | ||
@@ -167,3 +208,14 @@ method: 'GET', | ||
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"); |
'use strict' | ||
const pino = require('pino') | ||
const { pino, symbols: { stringifySym, chindingsSym } } = require('pino') | ||
const serializers = require('pino-std-serializers') | ||
@@ -97,3 +97,4 @@ const getCallerFile = require('get-caller-file') | ||
const responseTime = Date.now() - res[startTime] | ||
const level = getLogLevelFromCustomLogLevel(customLogLevel, useLevel, res, err) | ||
const req = res[reqObject] | ||
const level = getLogLevelFromCustomLogLevel(customLogLevel, useLevel, res, err, req) | ||
@@ -104,7 +105,9 @@ if (level === 'silent') { | ||
const req = res[reqObject] | ||
const customPropBindings = (typeof customProps === 'function') ? customProps(req, res) : customProps | ||
if (customPropBindings) { | ||
log = logger.child(customPropBindings) | ||
const customPropBindingStr = logger[stringifySym](customPropBindings).replace(/[{}]/g, '') | ||
const customPropBindingsStr = logger[chindingsSym] | ||
if (!customPropBindingsStr.includes(customPropBindingStr)) { | ||
log = logger.child(customPropBindings) | ||
} | ||
} | ||
@@ -111,0 +114,0 @@ |
{ | ||
"name": "pino-http", | ||
"version": "8.3.1", | ||
"version": "8.5.1", | ||
"description": "High-speed HTTP logger for Node.js", | ||
@@ -8,3 +8,2 @@ "main": "logger.js", | ||
"dependencies": { | ||
"fast-url-parser": "^1.1.3", | ||
"get-caller-file": "^2.0.5", | ||
@@ -16,3 +15,3 @@ "pino": "^8.0.0", | ||
"devDependencies": { | ||
"@types/node": "^18.0.0", | ||
"@types/node": "^20.1.0", | ||
"autocannon": "^7.3.0", | ||
@@ -22,3 +21,3 @@ "coveralls": "^3.0.0", | ||
"pino-http-print": "^3.1.0", | ||
"pino-pretty": "^9.0.0", | ||
"pino-pretty": "^10.0.0", | ||
"pre-commit": "^1.1.2", | ||
@@ -29,4 +28,4 @@ "split2": "^4.0.0", | ||
"ts-node": "^10.3.0", | ||
"tsd": "^0.24.1", | ||
"typescript": "^4.4.4" | ||
"tsd": "^0.29.0", | ||
"typescript": "^5.0.2" | ||
}, | ||
@@ -33,0 +32,0 @@ "scripts": { |
@@ -1,2 +0,2 @@ | ||
# pino-http [![Build Status](https://img.shields.io/github/workflow/status/pinojs/pino-http/CI)](https://github.com/pinojs/pino-http/actions) | ||
# pino-http [![Build Status](https://img.shields.io/github/actions/workflow/status/pinojs/pino-http/ci.yml?branch=master)](https://github.com/pinojs/pino-http/actions) | ||
@@ -118,2 +118,19 @@ High-speed HTTP logger for Node.js | ||
##### Use as Express middleware | ||
```js | ||
const express = require('express') | ||
const logger = require('pino-http') | ||
const app = express() | ||
app.use(logger()) | ||
function handle (req, res) { | ||
req.log.info('something else') | ||
res.end('hello world') | ||
} | ||
app.listen(3000) | ||
``` | ||
##### Logger options | ||
@@ -134,7 +151,6 @@ | ||
genReqId: function (req, res) { | ||
if (req.id) return req.id | ||
let id = req.get('X-Request-Id') | ||
if (id) return id | ||
id = randomUUID() | ||
res.header('X-Request-Id', id) | ||
const existingID = req.id ?? req.headers["x-request-id"] | ||
if (existingID) return existingID | ||
const id = randomUUID() | ||
res.setHeader('X-Request-Id', id) | ||
return id | ||
@@ -207,2 +223,3 @@ }, | ||
req.log.info('something else') | ||
res.log.info('just in case you need access to logging when only the response is in scope') | ||
res.end('hello world') | ||
@@ -290,2 +307,3 @@ } | ||
logger(req, res) | ||
res.log.info('log is available on both req and res'); | ||
res.end('hello world') | ||
@@ -292,0 +310,0 @@ }).listen(3000) |
@@ -201,2 +201,22 @@ 'use strict' | ||
test('uses the custom log level passed in as an option, req and res is defined', function (t) { | ||
const dest = split(JSON.parse) | ||
const logger = pinoHttp({ | ||
customLogLevel: function (_req, _res, _err) { | ||
t.ok(_req, 'req is defined') | ||
t.ok(_res, 'res is defined') | ||
return 'warn' | ||
} | ||
}, dest) | ||
setup(t, logger, function (err, server) { | ||
t.error(err) | ||
doGet(server) | ||
}) | ||
dest.on('data', function () { | ||
t.end() | ||
}) | ||
}) | ||
test('uses the log level passed in as an option, where the level is a custom one', function (t) { | ||
@@ -1269,2 +1289,26 @@ const dest = split(JSON.parse) | ||
test('uses custom request properties and once customProps', function (t) { | ||
const dest = split() | ||
function customPropsHandler (req, res) { | ||
return { | ||
key1: 'value1' | ||
} | ||
} | ||
const logger = pinoHttp({ | ||
customProps: customPropsHandler | ||
}, dest) | ||
setup(t, logger, function (err, server) { | ||
t.error(err) | ||
doGet(server) | ||
}) | ||
dest.on('data', function (line) { | ||
t.equal(line.match(/key1/g).length, 1, 'once customProps') | ||
t.end() | ||
}) | ||
}) | ||
test('dont pass custom request properties to log additional attributes', function (t) { | ||
@@ -1271,0 +1315,0 @@ const dest = split(JSON.parse) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
78729
4
1845
477
- Removedfast-url-parser@^1.1.3
- Removedfast-url-parser@1.1.3(transitive)
- Removedpunycode@1.4.1(transitive)