iamolegga / nestjs-pino Goto Github PK
View Code? Open in Web Editor NEWPlatform agnostic logger for NestJS based on Pino with REQUEST CONTEXT IN EVERY LOG
License: MIT License
Platform agnostic logger for NestJS based on Pino with REQUEST CONTEXT IN EVERY LOG
License: MIT License
Thank you guys for your good job with this library.
Pino is a great logger, and nestjs-pino provides a very nice integration for NestJS.
However, I'm interested to know your point of view about performance question we can read about async_hooks
which is still in experimental status, and with the main reason of performance impact.
In addition to this (or linked with this), async_hooks
is not recommended for production deployment.
As you mentioned in nestjs-pino docs, REQUEST
scope can have performance issues. It's true and I fully agree.
But async_hooks
have also some performance impact too.
It will be very friendly if you could share your opinion on this topic.
Thank you very much.
I'd like to use this as a NestJS app logger as described here: https://github.com/iamolegga/nestjs-pino#usage-as-nestjs-app-logger
How can I specify the log levels and other configuration?
What is the current behavior?
Recommended way to use nestjs logger is to instantiate the singleton class Logger
from @nestjs/common
and supply context to it (https://stackoverflow.com/a/52907695/4601673), like so:
import { Logger } from '@nestjs/common';
class MyService implements OnModuleInit {
logger = new Logger(MyService.name);
onModuleInit() {
this.logger.log({ msg: 'test' });
}
}
Using this pattern with nestjs-pino works quite well, but there is a catch.
When context is supplied, message is sent as a second argument to pino here: https://github.com/iamolegga/nestjs-pino/blob/master/src/Logger.ts#L35.
This results in message being treated as the format string here: https://github.com/pinojs/pino/blob/master/lib/tools.js#L52.
So if message is an object, it gets stringified into the "msg" field of the logged json object, like so:
{"level":30,"time":1598681218911,"pid":92,"hostname":"sse-sandbox-hxfsk","context":"AppService","msg":"{\"msg\":\"test\"} "}
If context is not supplied, the message is supplied as the first argument and pino correctly logs the message as an object.
Please provide the steps to reproduce.
Here is the minimal codesandbox based on nestjs-typescript-starter with pino-logger applied and used from AppService.
https://codesandbox.io/s/nestjs-pino-logger-context-forked-hxfsk?file=/src/app.service.ts
There are some issues with displaying logging output though :(
What is the expected behavior?
I expect message to be logged the same way it is logged when context is not supplied (i.e. merged into root object), like so:
{"level":30,"time":1598681218911,"pid":92,"hostname":"sse-sandbox-hxfsk","context":"AppService","msg":"test"}
Please mention other relevant information such as Node.js version and Operating System.
I do not think this is relevant, but I am using node v12.18.2 and OS Windows 10 Pro 2004.
P.S.
If this is not an intended behavior, I can make a PR to fix it by merging message into context object in all of the methods of Logger
class. I would also like to add this usage example to the documentation.
Hi... Is possible toggle on/off the request logger?
When I'm throwing an error from Nest application nestjs-pino always prints in the error message "failed with status code 500" even though I'm throwing an error with a detailed message any idea how to solve this?
this is how I setup nestjs-pino
LoggerModule.forRoot({
pinoHttp: {
prettyPrint: { colorize: true, translateTime: true },
serializers: {
req: (req) => ({
...req,
headers: undefined,
}),
res: (res) => ({
...res,
headers: undefined,
}),
},
},
}),
and this is how I throw the error
import {InternalServerErrorException} from '@nestjs/common';
throw new InternalServerErrorException("This is my detailed error");
And nestjs-pino output
res: {
"statusCode": 500
}
err: {
"type": "Error",
"message": "failed with status code 500",
"stack":
Error: failed with status code 500
at ServerResponse.onResFinished (/Users/shahaf/Source/muil/muil/node_modules/pino-http/logger.js:73:38)
at ServerResponse.clsBind (/Users/shahaf/Source/muil/muil/node_modules/cls-hooked/context.js:172:17)
at ServerResponse.emit (node:events:388:22)
at ServerResponse.EventEmitter.emit (node:domain:532:15)
at ServerResponse.emitted (/Users/shahaf/Source/muil/muil/node_modules/emitter-listener/listener.js:134:21)
at onFinish (node:_http_outgoing:800:10)
at callback (node:internal/streams/writable:557:21)
at afterWrite (node:internal/streams/writable:503:5)
at afterWriteTick (node:internal/streams/writable:490:10)
at processTicksAndRejections (node:internal/process/task_queues:79:21)
}
responseTime: 94
req: {
"id": 1,
"method": "POST",
"url": "/api/test/test",
"remoteAddress": "::1",
"remotePort": 61221
}
Im using below code to generate request ID:-
shared.module.ts
import {
Module,
HttpModule
} from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { APP_FILTER } from '@nestjs/core';
import { LoggerModule } from 'nestjs-pino';
import * as config from 'config';
import { CorrelationIdGeneratorService } from './services/helpers/generators/correlation-id-generator.service';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'Device', schema: DeviceSchema }]),
MongooseModule.forFeature([{ name: 'File', schema: FileSchema }]),
HttpModule,
LoggerModule.forRootAsync({
providers: [
CorrelationIdGeneratorService,
],
inject: [CorrelationIdGeneratorService],
useFactory: (correlationIdGeneratorService: CorrelationIdGeneratorService) => {
return {
pinoHttp: {
genReqId: (request) => {
correlationIdGeneratorService.generateCorrelationId(request);
console.log('Im here 1',correlationIdGeneratorService.getCorrelationId());
return correlationIdGeneratorService.getCorrelationId();
},
level: config.get('log.LEVEL'),
useLevelLabels: true,
base: null,
timestamp: () => {
return `, "time":"${new Date().toISOString()}"`;
},
},
};
}
})
],
providers: [
CorrelationIdGeneratorService,
],
exports: [
CorrelationIdGeneratorService,
]
})
export class SharedModule { }
Now the issue is, i need to fetch the correlationId in another module for which i have exported the CorrelationIdGeneratorService from shared.module.ts and imported in my consuming modules.
Now in the consuming module im getting correlationId as undefined.
It seems that the object of CorrelationIdGeneratorService passed in loggermodule is different from the object passed in my consuming module. Please help, how can i share the singleton instance of correlation id throughout my code.
Below is the code for CorrelationIdGeneratorService
correlation-id-generator.service.ts
import { Injectable } from '@nestjs/common';
import * as config from 'config';
import { UniqueIdGeneratorService } from './unique-id-generator.service';
@Injectable()
export class CorrelationIdGeneratorService {
private correlationId: string;
constructor(private readonly uniqueIdGeneratorService: UniqueIdGeneratorService) {}
public generateCorrelationId(request: any) {
this.correlationId = request?.headers?.[config.get('httpHeaders.CORRELATION_ID')] ||
this.uniqueIdGeneratorService.generate(
config.get('correlationId.VALID_CHARS'),
config.get('correlationId.LENGTH')
);
console.log('Ammy 2', this.correlationId)
}
public getCorrelationId(): string {
return this.correlationId;
}
}
What is the current behavior?
Nest framework logs are not in JSON format:
However, injecting PinoLogger into services and using that, those logs are in JSON just fine.
Please provide the steps to reproduce.
Simply install following readme instructions into the root module:
@Module({
imports: [
LoggerModule.forRoot(),
UsersModule,
],
controllers: [AppController],
})
export class AppModule {}
What is the expected behavior?
Nest framework logs should be in JSON.
Please mention other relevant information such as Node.js version and Operating System.
Node version v12.13.0
, OS is Ubuntu latest LTR.
According to the Nest docs:
https://docs.nestjs.com/techniques/logger#logger
You can only replace the logger in NestFactory.create(...);
, which happens in src/main.ts
in my application.
Hi! Do you think that it would be possible to expose the underlying pino instance so that we can use the convenient syntax to print objects and other variables?
What is the current behavior?
Implementation of route exclusion (see #122 ) does not allow conditional exclusion of predefined paths without explicitly specyfing all of the applications controllers in forRoutes
attribute. This issue is caused by a known limitation of Nest interoperability with functional middlewares (please see nestjs #853 for more details).
Please provide the steps to reproduce.
Nestjs-pino module configuration like the one specified below doesn't work as expected, that is GET requests to /live
and /ready
paths still leave log traces in applications stdout.
{
forRoutes: [{ path: '*', method: RequestMethod.ALL }],
exclude: [
{ path: 'live', method: RequestMethod.GET },
{ path: 'ready', method: RequestMethod.GET },
],
}
What is the expected behavior?
This is not explicitly stated anywhere, but a good implementation would allow conditional exclusion of predefined routes from request logging without explicitly passing all of the apps controllers, as this approach is cumbersome and error prone. Wrapping logger middleware with path exclusion logic as suggested in #853
might be a good solution.
Please mention other relevant information such as Node.js version and Operating System.
package | version |
---|---|
node | v12 |
nest | v6+ |
nestjs-pino | v1.1.3 |
I have a microservice architecture, where all external requests are http, while internal ones are gRPC.
Now for logging, I want to have a unique id for each http request, so that I can have a correlation between my logs in different microservices.
Is there a way to retrieve the 'req.id', so that I can provide it as metadata in my clientGrpc call?
When I use a PinoLogger
instance to display some error object like this.logger.error(Error('foo'))
I get this:
{
"level": 50,
"time": 1590422389076,
"pid": 27787,
"hostname": "--",
"name": "app",
"req": {
"id": 1,
"method": "GET",
"url": "--",
"headers": {
"host": "localhost:3000",
"user-agent": "insomnia/7.1.1",
"accept": "*/*"
},
"remoteAddress": "127.0.0.1",
"remotePort": 52126
},
"context": "ExceptionsHandler"
}
seems like the arg isn't serialized by pino.stdSerializers.err
because
this.logger.error( pino.stdSerializers.err(Error('foo')) )
works as expected (with { type, message, stack }
). This happen even when I explicity define the serializers. Is it the right behavior?
Great lib btw!
As discussed in the docs:
// Logs by app itself
{"level":30,"time":1570470154387,"pid":17383,"hostname":"my-host","context":"RoutesResolver","msg":"AppController {/}: true","v":1}
{"level":30,"time":1570470154391,"pid":17383,"hostname":"my-host","context":"RouterExplorer","msg":"Mapped {/, GET} route true","v":1}
{"level":30,"time":1570470154405,"pid":17383,"hostname":"my-host","context":"NestApplication","msg":"Nest application successfully started true","v":1}
// Logs by injected Logger and PinoLogger in Services/Controllers
// Every log has it's request data and unique `req.id` (per process)
{"level":30,"time":1570470161805,"pid":17383,"hostname":"my-host","req":{"id":1,"method":"GET","url":"/","headers":{...},"remoteAddress":"::1","remotePort":53957},"context":"AppController","msg":"getHello()","v":1}
{"level":30,"time":1570470161805,"pid":17383,"hostname":"my-host","req":{"id":1,"method":"GET","url":"/","headers":{...},"remoteAddress":"::1","remotePort":53957},"context":"MyService","msg":"getWorld([])","v":1}
// Automatic logs of every request/response
{"level":30,"time":1570470161819,"pid":17383,"hostname":"my-host","req":{"id":1,"method":"GET","url":"/","headers":{...},"remoteAddress":"::1","remotePort":53957},"res":{"statusCode":304,"headers":{...}},"responseTime":15,"msg":"request completed","v":1}
I'm talking about these last logs in the list, "automatic logs of every request/response". (The ones where "msg":"request completed"
...)
I need to add a "context" to these logs, e.g. "Http", so that I can filter them out of my log aggregator.
How can I set "context":"Http"
on these logs?
Hello,
I'm using the syntax shown in https://github.com/iamolegga/nestjs-pino#asynchronous-configuration
@Module({
imports: [
LoggerModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => {
return {
pinoHttp: {
level: config.level,
prettyPrint: true
},
};
}
})
],
...
})
class TestModule {}
I get this kind of logs:
{"level":40,"time":1612819694266,"pid":37211,"hostname":"...","context":"..Service","msg":"a message"}
[1612819713135] INFO (my-app/37211 on truc): request completed
res: {
"statusCode": 201,
"headers": {
"x-powered-by": "Express",
"access-control-allow-origin": "*",
"content-type": "application/vnd.api+json; charset=utf-8",
"content-length": "91",
"etag": "W/\"5b-otKW0l0jfPtZ563iVaysTjm6m5s\""
}
}
responseTime: 12
...
Some of them are pretty-printed, some others aren't.
I also tried to force pino configuration:
...
useFactory: async (config: ConfigService) => {
return {
pinoHttp: {
logger: pino({
level: config.level,
prettyPrint: true
},
level: config.level,
prettyPrint: true
},
}
})
],
...
})
class TestModule {}
But no change.
How to get the same configuration for all logs?
Thank you
this.logger.info("test info") // print 2 times
this.logger.debug("test debug") // 1 time
Is there a way nestjs-pino supports automatically logging function start and end along with function arguments.
I just want to avoid tedious work of adding a info log in each function everytime.
It's overloaded to log req
object with every log. Is there a way to just print req.id
only?
Of course, the pinoHttp.autoLogging
should be turned on. the request completed
log and error
logs should contain req
and req
completely.
Thanks in advance.
sorry, I am a newbie in nestjs, How to use in Guards Interceptors Pipes Exception filters Middleware, can you provide a demo.
Is your feature request related to a problem? Please describe.
A clear and concise description of what you want to happen.
Is it possible to support GCP logging like they have integration with Bunyan and Winston?
When using pino on GCP I see that it's formating logs well to make them supported in Stackdriver and Logging but it's not setting Trace field:( Also there is option to support logs related to request with section "Formatting Request Logs"
Describe the solution you'd like
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Allow user to pass only a string to pinoHttp options, instead of a DestinationString. Forcing them to import pino
to do a (recommended) pino.destination(string)
Describe the solution you'd like
A clear and concise description of what you want to happen.
Allow to pass a string as destination to pinoHttp
option stream
and do in nestjs-pino the pino.destination(string) transformation.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Did not see any other way to do so
Additional context
Add any other context or screenshots about the feature request here.
I didn't want to import pino as a main dependency since i'll be using nestjs-pino, this way we can used the pino dependency contained in nestjs-pino instead.
What are your thought about this ?
I can try to make a PR for this if needed :)
Is your feature request related to a problem? Please describe.
I just migrated from another library I used to use name: {ModuleName}
for the context.
The main reason I did choose this, is that the default key used by pino-pretty
I would like to change the context key to use name
instead.
Describe the solution you'd like
I think it would be a good idea to have an extra option at the initialization to define the key used for the context.
Describe alternatives you've considered
I tried to implement it, but I didn't weel understood the typing of the options. So I don't know how to add the option.
My code is here : https://github.com/Nhacsam/nestjs-pino/tree/add-param-to-context-key
What is the current behavior?
Basic configuration as described by Usage as NestJS app logger doesn't work.
Please provide the steps to reproduce.
On a NestJS 6.10.10 project, just :
import { Logger } from "nestjs-pino";
const app = await NestFactory.create(MyModule, { logger: false });
app.useLogger(app.get(Logger));
gives:
Error: Nest could not find Logger element (this provider does not exist in the current context)
at ContainerScanner.getWrapperCollectionPairByHost (/myproject/node_modules/@nestjs/core/injector/container-scanner.js:34:19)
at ContainerScanner.findInstanceByToken (/myproject/node_modules/@nestjs/core/injector/container-scanner.js:20:40)
at ContainerScanner.find (/myproject/node_modules/@nestjs/core/injector/container-scanner.js:13:21)
at NestApplication.find (/myproject/node_modules/@nestjs/core/nest-application-context.js:184:38)
at NestApplication.get (/myproject/node_modules/@nestjs/core/nest-application-context.js:43:25)
at /myproject/node_modules/@nestjs/core/nest-factory.js:112:40
at Function.run (/myproject/node_modules/@nestjs/core/errors/exceptions-zone.js:8:13)
at Proxy.<anonymous> (/myproject/node_modules/@nestjs/core/nest-factory.js:111:46)
at bootstrap (/myproject/dist/src/main.js:9:23)
at processTicksAndRejections (internal/process/task_queues.js:85:5)
What is the expected behavior?
Please mention other relevant information such as Node.js version and Operating System.
NodeJS: 12.9.1
NestJS: 6.10.10
What is the current behavior?
TS2322: Type '(configService: ConfigurationService) => Promise<{ useExisting: false; }>' is not assignable to type '(...args: any[]) => Params | Promise<Params>'.
Type 'Promise<{ useExisting: false; }>' is not assignable to type 'Params | Promise<Params>'.
Type 'Promise<{ useExisting: false; }>' is not assignable to type 'Promise<Params>'.
Type '{ useExisting: false; }' is not assignable to type 'Params'.
Types of property 'useExisting' are incompatible.
Type 'false' is not assignable to type 'true'.
14 useFactory: async (configService: ConfigurationService) => ({
Please provide the steps to reproduce.
LoggerModule.forRootAsync({
useFactory: async (configService: ConfigurationService) => ({
useExisting: false,
}),
inject: [ConfigurationService],
}),
What is the expected behavior?
Should be able to set to false
Please mention other relevant information such as Node.js version and Operating System.
in params.ts
export interface Params {
pinoHttp?: pinoHttp.Options | DestinationStream | [pinoHttp.Options, DestinationStream];
exclude?: Parameters<MiddlewareConfigProxy["exclude"]>;
forRoutes?: Parameters<MiddlewareConfigProxy["forRoutes"]>;
useExisting?: true;
renameContext?: string;
}
should be?
export interface Params {
pinoHttp?: pinoHttp.Options | DestinationStream | [pinoHttp.Options, DestinationStream];
exclude?: Parameters<MiddlewareConfigProxy["exclude"]>;
forRoutes?: Parameters<MiddlewareConfigProxy["forRoutes"]>;
useExisting?: boolean;
renameContext?: string;
}
In some situation, i would‘t want to logging http info (header 、req 、ua and so on) how to diable it?
Okay, so i think this project can better communicate its value through some visuals.
Is your feature request related to a problem? Please describe.
The latest version of pino-http (4.4.0
) includes a new param for autoLogging called ignorePaths which allows you to specify an array of paths to ignore. We need this to prevent logging for our health-check endpoints.
There are two issues I discovered when trying to see if I could get this working with nestjs-pino.
The typescript definitions for pino-http
haven't been updated to include this new option. I have created a pull request to add it here (DefinitelyTyped/DefinitelyTyped#43137)
The underlying pino-http feature uses the req.url
property to compare against the configured ignore paths. This is a problem because req.url
in nest class middlewares gets rewritten with the route mount point stripped. So it is always /
regardless of which route is hit. I believe this is a byproduct of how app.use()
works in express
Describe the solution you'd like
Somehow figure out how this feature could be implemented.
Describe alternatives you've considered
As a more proactive measure I've put up a PR against pino-http
that if accepted would make this feature request irrelevant. It would allow for us to specify the current path through a function passed as an autoLogging
option. This would allow us to use req.originalUrl instead of req.url. pinojs/pino-http#80
I had a hard time finding a clean and easy way to log HTTP requests with Nest. Thank you ❤️
Hi!
First of all, thanks for this module, it is really appreciated.
I am trying to use Pino Logger throughout the application; perhaps I am wrong about it, but what I am doing is to add the following code to app.module.ts
:
@Module({
imports: [
ConfigModule.forRoot(),
LoggerModule.forRoot({
pinoHttp: { prettyPrint: true, useLevelLabels: true }, // <--
}),
// ...
],
// ...
})
export class AppModule {}
And, in main.ts
:
import { NestFactory } from '@nestjs/core';
import { Logger } from 'nestjs-pino';
async function bootstrap() {
// Create the application.
const app = await NestFactory.create(AppModule, { logger: false });
// Get Pino Logger instance.
const logger = app.get(Logger);
// Use Pino as the main logger!
app.useLogger(logger);
// Start the server!
await app.listen(3030);
}
// Initialize application!
bootstrap();
The issue is that, if I import LoggerModule
and call forRoot
(or forRootAsync
by injecting ConfigService
etc), without any Pino options (prettyPrint
or useLevelLabels
) it works perfectly, however when adding even one option, it hangs the entire application without even booting!
I would like to use Pino as the main logging system for the entire application, no exclusions.
I am using NestJS v7.
Again, thanks for this library! And thanks in advance for any commentary this might receive :)
I am new to NestJS and NodeJS. I am using nestjs-pino
in my application.
In my AppModule
class I am importing the LoggerModule
. Then when I configure TypeOrmModule
I want to log something with nestjs-pino
. How can I inject the nestjs-pino
logger into my module configuration?
@Module({
imports: [
LoggerModule.forRoot({
pinoHttp: {
autoLogging: false
}
}),
TypeOrmModule.forRootAsync({
useFactory: async () => {
const host = process.env.DATABASE_HOST || "localhost";
const port = Number(process.env.DATABASE_PORT) || 5432;
const username = process.env.DATABASE_USER || "postgres";
const password = process.env.DATABASE_PASSWORD || "mysecretpassword";
const database = process.env.DATABASE_DATABASE || "postgres";
// TODO use nestjs-pino here
console.log(`Connecting to database ${database} on ${host}:${port} with user ${username}`);
return {
type: "postgres", host: host, port: port, username: username, password: password, database: database, synchronize: true
};
}
})
],
controllers: [AppController, HealthController],
providers: [AppService]
})
export class AppModule {
}
Is your feature request related to a problem? Please describe.
I'm using globally imported pino logger module. Every time when I make a log line I would like to know from which class the log was created. Right now, I have to include the context manually. Like the following lines in the README.md
:
https://github.com/iamolegga/nestjs-pino/blob/master/README.md#L56
https://github.com/iamolegga/nestjs-pino/blob/master/README.md#L72
Currently, we can set base
context per configuration of logger module. That's too broad for my use case. Even if I migrate my logger module import from global to per module import, I'd prefer finer level of granularity in defining base
context. (But not as fine as log line :) )
Describe the solution you'd like
I would like to write log lines using injected logger without manually providing class context on each log line. I'd like the context to be either set up once per class (injection) or somehow dynamically configured to use class name (or whatever else) per module configuration.
I'm probably off on these, but my superficial suggestions would be:
child
functionality so we can fork (child) a logger manually. Then we could set it up with context in each class constructor (or wherever we deem useful)Is your feature request related to a problem? Please describe.
I'm looking for a way to add the Application name into each log.
Describe the solution you'd like
I would like a new parameter in forRoot module method in order to give an App name.
Describe alternatives you've considered
I would like to get access to Pino instance logger used in the module in order to create a child logger with this property. This option is maybe more powerful.
Additional context
This kind of information is especially useful when a save all the logs of all micro-services in the same space.
Hi guys! I would like to extend the Pino logger to be able to inject my own business logic in some cases (for example logger.error).
So decided to build a logger module on top of nestjs-pino.
Here are my two files
logger.service.ts
import { Injectable } from '@nestjs/common';
import { PinoLogger } from 'nestjs-pino';
@Injectable()
export class LoggerService extends PinoLogger {
error(message: any, trace?: string, context?: string, ...args: any[]) {
// My business logic here
super.error(message, trace);
}
}
logger.module.ts
import { Global, Module } from '@nestjs/common';
import { LoggerService } from './logger.service';
import { LoggerModule as PinoModule } from 'nestjs-pino';
@Global()
@Module({
imports: [PinoModule.forRoot()],
providers: [LoggerService],
exports: [LoggerService],
})
export class LoggerModule {}
I am importing the module in app.module.ts.
My issue is when I start the application, I got this error at module initialization.
Error: Nest can't resolve dependencies of the LoggerService (?). Please make sure that the argument pino-params at index [0] is available in the LoggerModule context.
Potential solutions:
- If pino-params is a provider, is it part of the current LoggerModule?
- If pino-params is exported from a separate @Module, is that module imported within LoggerModule?
@Module({
imports: [ /* the Module containing pino-params */ ]
})
I cannot figured out why I have this message, I am well imported the PinoModule in the loggerModule.
Thanks for any help 😸
how to integrate with pino-multi-stream? It looks like can't function well with it.
Hi,
would it be possible to reuse the instance of pino
from the FastifyAdapter
?
Hello,
Is your feature request related to a problem? Please describe.
I would like the ability to customize the messages automatically logged by pino-http
(request completed
and request errored
).
Describe the solution you'd like
Since version 5.0.0 of pino-http
, two new options were added: customSuccessMessage
and customErrorMessage
to do this. So in the end my feature request is only updating the dependencies and publishing a new version. However, the types package is not up to date, so it might not be possible right now.
Describe alternatives you've considered
I haven't considered any alternative yet.
Additional context
Nothing to add.
Thank you!
I would like to use pino-caller to log the line number where the log method was invoked. Is it currently possible to use the returned pino-caller
logger instance when configuring this module?
Hello!
How can I implement log to file or database?
I use global log as bellow:
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: false,
});
app.useLogger(app.get(Logger));
await app.listenAsync(process.env.PORT || 3000);
}
bootstrap().then();
By default, only responseTime
, statusCode
and headers
are logged.
"res":{"statusCode":304,"headers":{...}},"responseTime":15
Is there a configuration to enable logging res.body?
I am using NestJS, pino and nestjs-pino.
Normally, I am injecting the PinoLogger
like this to log my statements:
import { PinoLogger } from "nestjs-pino";
However, now I want to access the method logger.isLevelEnabled(level)
. Unfortunately
, PinoLogger does not have this method.
How can I access isLevelEnabled
with nestjs-pino?
Is there any way to dynamically change loglevel
during runtime? Like in pino using logger.level
.
https://github.com/pinojs/pino/blob/master/docs/api.md#loggerlevel-string-gettersetter
It will be very useful in my case, when I want to change loglevel
in working microservice without its reloading. Now I set it with .env
and there is no way to change it dynamicly.
Does this library support logging the user associated with the request?
My application uses a custom @nestjs/passport
strategy to handle authentication:
class MyStrategy extends PassportStrategy(BasicStrategy, 'custom') {
async validate(username: string, password: string): Promise<IUser> {...}
}
When I need to access the user in a guard, for example, I do the following:
class PermissionGuard implements CanActivate {
canActivate(context: ExecutionContext) {
const args = context.switchToHttp();
const request = args.getRequest();
const user = request.user as IUser;
...
}
}
Is there a way to automatically add the user to the log context?
Hi! Awesome module, thanks!
I have a question though. I've got a Nest.js application and here's my main.ts file:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from 'nestjs-pino/dist';
async function bootstrap() {
process.env.NODE_ENV = process.env.NODE_ENV || 'DEV';
const app = await NestFactory.create(AppModule, {logger: false});
app.useLogger(app.get(Logger));
await app.listen(process.env.PORT || 3000);
}
bootstrap();
After I set app.useLogger(...) I can see all the requests coming into the app in stdout. However I have a health check endpoint, which I'd like to prevent from being logged. How can I achieve it with this module?
Thanks in advance.
What is the current behavior?
Running my nest app fails
Output from the console
ts-node -r tsconfig-paths/register src/main.ts | pino-pretty -t
1: 0x8dc510 node::Abort() [node]
2: 0x96f439 [node]
3: 0xb62a3f [node]
4: 0xb635a9 v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
5: 0x1db7cbadbe1d
Aborted (core dumped)
Please provide the steps to reproduce.
run the above command
What is the expected behavior?
Application starts and logs correctly
Please mention other relevant information such as Node.js version and Operating System.
Behaviour only happens on ubuntu
Node v12
Core dump
node::i18n::Initialize(v8::Local<v8::Object>, v8::Local<v8::Value>, v8::Local<v8::Context>, void*) + 1401 frame #2: 0x0000000000b62a3f node
v8::internal::CompilationCacheRegExp::Lookup(v8::internal::Handlev8::internal::String, v8::base::Flags<v8::internal::JSRegExp::Flag, int>) + 335v8::internal::CompilationCache::PutEval(v8::internal::Handle<v8::internal::String>, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Handle<v8::internal::Context>, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Handle<v8::internal::FeedbackCell>, int) + 89 frame #4: 0x00003b61a755be1d frame #5: 0x00003b61a75118d5 frame #6: 0x00003b61a7e7e798 frame #7: 0x00003b61a7541811 frame #8: 0x00003b61a751f83a frame #9: 0x00003b61a7504ba1 frame #10: 0x0000000000e73f0e node
v8::internal::ParserBasev8::internal::Parser::ParseForAwaitStatement(v8::internal::ZoneList<v8::internal::AstRawString const*>, v8::internal::ZoneList<v8::internal::AstRawString const>) + 94v8::internal::Runtime_StringCharCodeAt(int, unsigned long*, v8::internal::Isolate*) + 1115 frame #12: 0x0000000000b62a3f node
v8::internal::CompilationCacheRegExp::Lookup(v8::internal::Handlev8::internal::String, v8::base::Flags<v8::internal::JSRegExp::Flag, int>) + 335v8::internal::CompilationCache::PutEval(v8::internal::Handle<v8::internal::String>, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Handle<v8::internal::Context>, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Handle<v8::internal::FeedbackCell>, int) + 89 frame #14: 0x00003b61a755be1d frame #15: 0x00003b61a75118d5 frame #16: 0x00003b61a750ee75 frame #17: 0x00003b61a75092c1 frame #18: 0x0000000000e725d3 node
v8::internal::Parser::CloseTemplateLiteral(v8::internal::Parser::TemplateLiteral**, int, v8::internal::Expression) + 307v8::internal::Builtin_Impl_ArrayPrototypeFill(v8::internal::BuiltinArguments, v8::internal::Isolate*) + 1705 frame #20: 0x0000000000affaa1 node
v8::internal::Builtin_Impl_Stats_ArrayPrototypeFill(int, unsigned long*, v8::internal::Isolate*) + 97node::AsyncWrap::GetConstructorTemplate(node::Environment*) + 297 frame #22: 0x00000000008ddbd7 node
node::AsyncHooks::AsyncHooks() + 1911node::AsyncWrap::DestroyAsyncIdsCallback(node::Environment*) + 361 frame #24: 0x00000000008b8a7c node
node::cares_wrap::(anonymous namespace)::ChannelWrap::New(v8::FunctionCallbackInfov8::Value const&) + 156report::PrintVersionInformation(report::JSONWriter*) + 11438 frame #26: 0x0000000000a5a5c8 node
void report::JSONWriter::json_keyvalue<char [5], char [10]>(char const (&) [5], char const (&) [10]) + 376node::crypto::ClientHelloParser::ParseHeader(unsigned char const*, unsigned long) + 219 frame #28: 0x00000000008e6f45 node
napi_get_array_length + 357Hi guys,
I want the following setup for my NestJS application:
nestjs-pino
. They'll be sent to the ELK logging facilities by Filebeat or whatever.Logger
Pino object is available for manual invocation across the project (this.logger.log("...")
).How do I achieve that?
Say, I let the "middleware" thing initialize like this:
@Module({
imports: [ LoggerModule.forRoot({ autologging: false, pinoHttp: { ... } }) ],
...
})
export class AppModule {}
Is there a way I can re-create the middleware manually, where I can use my custom class (as per NestJS documentation) which in turn uses Pino logger configured by the LoggerModule
, but directs its output to a file?
Thank you very much.
Hello,
I am using your library in my project. Thanks for your work, it is really helpful!
We are using a Passport local strategy for authentication (https://docs.nestjs.com/security/authentication#implementing-passport-local). If the authentication is performed correctly, the user
object will be added on the request
object that it will be later passed to the controllers.
What I would like to do is to add the userId
value to each request information that is bundled together with each log. It seems that the serializer methods are called before this auth layer is called and I did not find a way to do this in the documentation.
Do you have any advice on how to implement this?
Thank you!
Is your feature request related to a problem? Please describe.
Avoid writing logs on each function. Lets say I want to write function entry and exit log in 'INFO' level, so I can have a option like a decorator which I can mention on top of function something like @loggable, then the logs with function argument will be printed on function start and function end.
Describe the solution you'd like
It would avoid writing tedious log line on each function.
Describe alternatives you've considered
NA
Additional context
Might be there are packages existing for Java on the same lines.
Hi,
I am using pino with configuration as illustrated below:
// app.module.ts
import { Module } from '@nestjs/common';
import { LoggerModule } from 'nestjs-pino';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import * as pino from 'pino';
const logger = pino({
level: process.env.NODE_ENV !== 'prod' ? 'debug' : 'info',
},pino.destination({
minLength: 4096,
sync: false,
}));
setInterval(function() {
logger.flush();
}, 5000).unref();
@Module({
imports: [
LoggerModule.forRoot({
pinoHttp: {
logger,
autoLogging: true,
serializers: {
err: pino.stdSerializers.err,
req: r => {
return {
id: r.id,
method: r.method,
url: r.url,
};
},
res: pino.stdSerializers.res,
}
},
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
and
// main.ts
import { NestFactory } from '@nestjs/core';
import { Logger } from 'nestjs-pino';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, { logger: false });
app.useLogger(app.get(Logger));
await app.listen(3000);
}
bootstrap();
But the logging output missed the system logging part.
> nest start --watch
[10:11:49 PM] Starting compilation in watch mode...
[10:11:53 PM] Found 0 errors. Watching for file changes.
{"level":30,"time":1604671913986,"pid":28435,"hostname":"2070iMac","context":"RoutesResolver","msg":"AppController {}:"}
{"level":30,"time":1604671913987,"pid":28435,"hostname":"2070iMac","context":"RouterExplorer","msg":"Mapped {, GET} route"}
{"level":30,"time":1604671913989,"pid":28435,"hostname":"2070iMac","context":"NestApplication","msg":"Nest application successfully started"}
It is expected to output as many as system logging output, which has logging form modules like NestFactory and InstanceLoader. Below is the output from the default logger.
[10:33:59 PM] Starting compilation in watch mode...
[10:34:00 PM] Found 0 errors. Watching for file changes.
[Nest] 30928 - 11/06/2020, 10:34:01 PM [NestFactory] Starting Nest application...
[Nest] 30928 - 11/06/2020, 10:34:01 PM [InstanceLoader] LoggerModule dependencies initialized +15ms
[Nest] 30928 - 11/06/2020, 10:34:01 PM [InstanceLoader] LoggerCoreModule dependencies initialized +1ms
[Nest] 30928 - 11/06/2020, 10:34:01 PM [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 30928 - 11/06/2020, 10:34:01 PM [RoutesResolver] AppController {}: +6ms
[Nest] 30928 - 11/06/2020, 10:34:01 PM [RouterExplorer] Mapped {, GET} route +1ms
[Nest] 30928 - 11/06/2020, 10:34:01 PM [NestApplication] Nest application successfully started +4ms
Here are some sample code to reproduce this issue: https://github.com/wuminqi/example-pino-nestjs
Can you kindly offer a help on this?
Thanks.
In my case, we receive a specific Id per request, it goes through several systems and we use it to log and track the request cycle.
Is it possible to manually change the request Id? If so, what would be the best way to do this?
I was wondering if it is possible to redact certain JSON keys from request logging and logging? Pino has support for redaction, but I could not see a Param for redaction in nestjs-pino.
In some cases, we need to customized pino/pino-http default params. How to configure default options globally like this?
`
{
genReqId: generateLogId, //pino-http ID generation
prettyPrint: isDevMode ? { colorize: true } : undefined // dev env pino-pretty
}
`
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.