You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/techniques/logger.md
+48-10Lines changed: 48 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -105,7 +105,7 @@ You can tell Nest to use your extended logger for system logging by passing an i
105
105
106
106
For more advanced logging functionality, you'll want to take advantage of dependency injection. For example, you may want to inject a `ConfigService` into your logger to customize it, and in turn inject your custom logger into other controllers and/or providers. To enable dependency injection for your custom logger, create a class that implements `LoggerService` and register that class as a provider in some module. For example, you can
107
107
108
-
1. Define a `MyLogger` class that either extends the built-in `Logger` or completely overrides it, as shown in previous sections.
108
+
1. Define a `MyLogger` class that either extends the built-in `Logger` or completely overrides it, as shown in previous sections. Be sure to implement the `LoggerService` interface.
109
109
2. Create a `LoggerModule` as shown below, and provide `MyLogger` from that module.
110
110
111
111
```typescript
@@ -133,30 +133,61 @@ await app.listen(3000);
133
133
134
134
Here we use the `get()` method on the `NestApplication` instance to retrieve the singleton instance of the `MyLogger` object. This technique is essentially a way to "inject" an instance of a logger for use by Nest. The `app.get()` call retrieves the singleton instance of `MyLogger`, and depends on that instance being first injected in another module, as described above.
135
135
136
-
You can also inject this `MyLogger` provider in your feature classes, thus ensuring consistent logging behavior across both Nest system logging and application logging. See <ahref="techniques/logger#using-the-logger-for-application-logging">Using the logger for application logging</a> below for more information.
136
+
The only downside of this solution is that your first initialization messages won't be printed anywhere at all, so in rare cases you may miss some important initialization errors.
137
+
Alternatively you can print first initialization messages using default logger, and then switch to your custom one:
137
138
138
-
The only downside of this solution is that your first initialization messages won't be handled by your logger instance, though, it shouldn't really matter at this point.
You can also inject this `MyLogger` provider in your feature classes, thus ensuring consistent logging behavior across both Nest system logging and application logging. See <ahref="techniques/logger#using-the-logger-for-application-logging">Using the logger for application logging</a> and <ahref="techniques/logger#injecting-a-custom-logger">Injecting a custom logger</a> below for more information.
139
146
140
147
#### Using the logger for application logging
141
148
142
-
We can combine several of the techniques above to provide consistent behavior and formatting across both Nest system logging and our own application event/message logging. In this section, we'll achieve this with the following steps:
149
+
We can combine several of the techniques above to provide consistent behavior and formatting across both Nest system logging and our own application event/message logging.
150
+
151
+
A good practice is to instantiate `Logger` class from `@nestjs/common` in each of our services. We can supply our service name as the `context` argument in the `Logger` constructor, like so:
143
152
144
-
1. We extend the built-in logger and customize the `context` portion of the log message (e.g., the phrase `NestFactory` in square brackets in the log line shown below).
In the default logger implementation, `context` is printed in the square brackets, like `NestFactory` in the example below:
145
167
146
168
```bash
147
169
[Nest] 19096 - 12/08/2019, 7:12:59 AM [NestFactory] Starting Nest application...
148
170
```
149
171
150
-
2. We inject a [transient](/fundamentals/injection-scopes) instance of the `Logger` into our feature modules so that each one has its own custom context.
151
-
3. We supply this extended logger for Nest to use for system logging.
172
+
If we supply a custom logger via `app.useLogger()`, it will actually be used by Nest internally. That means that our code remains implementation agnostic, while we can easily substitute the default logger for our custom one by calling `app.useLogger()`.
173
+
174
+
That way if we follow the steps from the previous section and call `app.useLogger(app.get(MyLogger))`, the following calls to `this.logger.log()` from `MyService` would result in calls to method `log` from `MyLogger` instance.
175
+
176
+
This should be suitable for most cases. But if you need more customization (like adding and calling custom methods), move to the next section.
177
+
178
+
#### Injecting a custom logger
152
179
153
-
To start, extend the built-in logger with code like the following. We supply the `scope` option as configuration metadata for the `Logger` class, specifying a [transient](/fundamentals/injection-scopes) scope, to ensure that we'll have a unique instance of the `Logger` in each feature module. In this example, we do not extend the individual `Logger` methods (like `log()`, `warn()`, etc.), though you may choose to do so.
180
+
To start, extend the built-in logger with code like the following. We supply the `scope` option as configuration metadata for the `Logger` class, specifying a [transient](/fundamentals/injection-scopes) scope, to ensure that we'll have a unique instance of the `MyLogger` in each feature module. In this example, we do not extend the individual `Logger` methods (like `log()`, `warn()`, etc.), though you may choose to do so.
Next, create a `LoggerModule` with a construction like this:
@@ -172,7 +203,7 @@ import { MyLogger } from './my-logger.service';
172
203
exportclassLoggerModule {}
173
204
```
174
205
175
-
Next, import the `LoggerModule` into your feature module. Then set the logger context, and start using the context-aware custom logger, like this:
206
+
Next, import the `LoggerModule` into your feature module. Since we extended default `Logger` we have the convenience of using `setContext` method. So we can start using the context-aware custom logger, like this:
176
207
177
208
```typescript
178
209
import { Injectable } from'@nestjs/common';
@@ -183,11 +214,16 @@ export class CatsService {
183
214
privatereadonly cats:Cat[] = [];
184
215
185
216
constructor(privatemyLogger:MyLogger) {
217
+
// Due to transient scope, CatsService has its own unique instance of MyLogger,
218
+
// so setting context here will not affect other instances in other services
Be mindful that if you supply `logger: false` to `NestFactory.create`, nothing will be logged until you call `useLogger`, so you may miss some important initialization errors. If you don't mind that some of your initial messages will be logged with the default logger, you can just omit the `logger: false` option.
243
+
206
244
#### Use external logger
207
245
208
246
Production applications often have specific logging requirements, including advanced filtering, formatting and centralized logging. Nest's built-in logger is used for monitoring Nest system behavior, and can also be useful for basic formatted text logging in your feature modules while in development, but production applications often take advantage of dedicated logging modules like [Winston](https://github.com/winstonjs/winston). As with any standard Node.js application, you can take full advantage of such modules in Nest.
0 commit comments