A pino logger plugin for hono
This repository is inspired by pino-http and nestjs-pino.
# npm
npm install hono-pino pino
# pnpm
pnpm add hono-pino pino
# bun
bun add hono-pino pino
import { Hono } from 'hono'
import { pinoLogger } from 'hono-pino'
const app = new Hono()
.use(
pinoLogger({
pino: {level: "debug"}
}),
)
.get((c) => {
const { logger } = c.var;
const token = c.req.header("Authorization") ?? "";
logger.debug({ token });
const user = getAuthorizedUser(token);
logger.assign({ user });
const posts = getPosts();
logger.assign({ posts });
logger.setResMessage("Get posts success"); // optional
return c.text("");
});
await app.request("/", {
headers: {
Authorization: "Bearer token",
},
});
// output (formatted for easier reading)
{"level":20, "token":"Bearer token"}
{
"level": 30,
"msg": "Get posts success",
"user": {
"id": 1,
"name": "john"
},
"posts": [
{
"id": 1,
"title": "My first post"
},
{
"id": 2,
"title": "My second post"
}
],
"req": {
"headers": {
"authorization": "Bearer token"
},
"method": "GET",
"url": "/"
},
"reqId": 1,
"res": {
"headers": {},
"status": 200
},
"responseTime": 2
}
see examples
export interface Options {
/**
* custom context key
* @description context key for hono, Must be set to literal string.
* @default "logger"
*/
contextKey?: ContextKey;
/**
* a pino instance or pino options
*/
pino?: pino.Logger | pino.LoggerOptions | pino.DestinationStream;
/**
* http request log options
*/
http?:
| false
| {
/**
* custom request id
* @description set to false to disable
* @default () => n + 1
*/
reqId?: false | (() => string);
/**
* custom on request bindings
* @default
* (c) => ({
* req: {
* url: c.req.path,
* method: c.req.method,
* headers: c.req.header(),
* },
* })
*/
onReqBindings?: (c: Context) => pino.Bindings;
/**
* custom on request level
* @default (c) => "info"
*/
onReqLevel?: (c: Context) => pino.Level;
/**
* custom on request message
* @description set to false to disable
* @default false // disable
*/
onReqMessage?: false | ((c: Context) => string);
/**
* custom on response bindings
* @default
* (c) => ({
* res: {
* status: c.res.status,
* headers: c.res.headers,
* },
* })
*/
onResBindings?: (c: Context) => pino.Bindings;
/**
* custom on response level
* @default (c) => c.error ? "error" : "info"
*/
onResLevel?: (c: Context) => pino.Level;
/**
* custom on response message
* @description set to false to disable
* @default (c) => c.error ? c.error.message : "Request completed"
*/
onResMessage?: false | ((c: Context) => string);
/**
* adding response time to bindings
* @default true
*/
responseTime?: boolean;
};
}
class PinoLogger {
// Same as pino[logger level]
trace: pino.LogFn
debug: pino.LogFn
info: pino.LogFn
warn: pino.LogFn
error: pino.LogFn
fatal: pino.LogFn
// Get bindings (object)
bindings(): pino.Bindings
// Reset bindings
resetBindings(): void
// Assign bindings (default shallow merge)
assign(
bindings: pino.Bindings
opts?: {
/** deep merge */
deep?: boolean;
},
): void
}