# Logger
Ts.ED has its own logger available through @tsed/logger
(opens new window) package.
# Features
Ts.ED logger supports many features, and is optimized to be used in production.
- Many layout (opens new window) formats are supported:
- Colored console (opens new window) logging to stdout or stderr.
- Json layout (opens new window).
- Many appender (stream) formats are supported:
- Console (opens new window).
- File (opens new window).
- File date (opens new window), with configurable log rolling based on file size or date.
- Stdout (opens new window).
- Stderr (opens new window).
- Insight (opens new window).
- LogEntries (opens new window).
- LogStash HTTP (opens new window).
- LogStash UDP (opens new window).
- Loggly (opens new window).
- RabbitMQ (opens new window).
- Seq (opens new window).
- Slack (opens new window).
- Smtp (opens new window).
- ContextLogger , in production mode, caches all request logs until the response is sent to your consumer. See request logger section bellow.
You can create your own layout/appender:
# Configuration
Logger can be configured through the Configuration decorator:
Props | Description |
---|---|
logger.level | Change the default log level displayed in the terminal. Values: debug , info , warn or error . By default: info . |
logger.logRequest | Log all incoming requests. By default, it's true and prints the configured logger.requestFields . |
logger.requestFields | Fields displayed when a request is logged. Possible values: reqId , method , url , headers , body , query ,params , duration . This option have only effect on info level. |
logger.reqIdBuilder | A function called for each incoming request to create a request id. |
logger.jsonIndentation | The number of space characters to use as white space in JSON output. Default is 2 (0 in production). |
logger.disableRoutesSummary | Disable routes table displayed in the logger. |
logger.format | Specify log format. Example: %[%d{[yyyy-MM-dd hh:mm:ss,SSS}] %p%] %m . See @tsed/logger configuration (opens new window). |
logger.ignoreUrlPatterns | (String or RegExp ) List of patterns to ignore logged request according to the request.url . |
WARNING
It is recommended to disable logRequest in production. Logger has a cost on the performance.
# Use Json Layout in production
You add this code to switch the logger to Json layout in production mode:
import {env} from "@tsed/core";
import {$log, Configuration} from "@tsed/common";
import "@tsed/platform-express";
export const isProduction = process.env.NODE_ENV === Env.PROD;
if (isProduction) {
$log.appenders.set("stdout", {
type: "stdout",
levels: ["info", "debug"],
layout: {
type: "json"
}
});
$log.appenders.set("stderr", {
levels: ["trace", "fatal", "error", "warn"],
type: "stderr",
layout: {
type: "json"
}
});
}
@Configuration({
logger: {
disableRoutesSummary: isProduction // remove table with routes summary
}
})
export class Server {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
This configuration will display the log as following:
{"startTime":"2017-06-05T22:23:08.479Z","categoryName":"json-test","data":["this is just a test"],"level":"INFO","context":{}}
It's more useful if you planed to parse the log with LogStash or any log tool parser.
# Inject logger
Logger can be injected in any injectable provider as follows:
import {Logger} from "@tsed/common";
import {Injectable, Inject} from "@tsed/di";
@Injectable()
export class MyService {
@Inject()
logger: Logger;
$onInit() {
this.logger.info("Hello world");
}
}
2
3
4
5
6
7
8
9
10
11
12
TIP
Prefer the ContextLogger usage if you want to attach your log the current request. See the next section.
# Request logger
For each Request, a logger will be attached to the PlatformContext and can be used like here:
import {Controller, Context, Get} from "@tsed/common";
import {Logger} from "@tsed/logger";
import {MyService} from "../services/MyService";
@Controller("/")
class MyController {
@Inject()
myService: MyService;
@Get("/")
get(@Context() ctx: Context) {
ctx.logger.info({customData: "test"}); // parameter is optional
ctx.logger.debug({customData: "test"});
ctx.logger.warn({customData: "test"});
ctx.logger.error({customData: "test"});
ctx.logger.trace({customData: "test"});
// forward ctx object to the service and use logger inside.
// All request
myService.doSomething("test", ctx);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {PlatformContext} from "@tsed/common";
import {Injectable, Inject} from "@tsed/di";
@Injectable()
export class MyService {
doSomething(input: string, ctx: PlatformContext) {
ctx.logger.info({event: "test", input});
}
}
2
3
4
5
6
7
8
9
TIP
All log use through ctx.logger will be associated with the uniq request id generated by Ts.ED.
TIP
ContextLogger , in production mode, caches all request logs until the response is sent to your consumer.
A call with one of these methods will generate a log according to the logger.requestFields
configuration:
[2017-09-01 11:12:46.994] [INFO ] [TSED] - {
"status": 200,
"reqId": 1,
"method": "GET",
"url": "/api-doc/swagger.json",
"duration": 92,
"headers": {
"host": "0.0.0.0:8001",
"connection": "keep-alive",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip, deflate",
"accept-language": "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4"
},
"body": {},
"query": {},
"customData": "test"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
You can configure the displayed fields from the server configuration:
import {Configuration} from "@tsed/common";
@Configuration({
logger: {
requestFields: ["reqId", "method", "url", "headers", "body", "query", "params", "duration"]
}
})
export class Server {}
2
3
4
5
6
7
8
or you can override the middleware with OverrideProvider .
Example:
import {Context, OverrideProvider, PlatformLogMiddleware} from "@tsed/common";
@OverrideProvider(PlatformLogMiddleware)
export class CustomPlatformLogMiddleware extends PlatformLogMiddleware {
public use(@Context() ctx: Context) {
// do something
return super.use(ctx); // required
}
protected requestToObject(ctx: Context) {
const {request} = ctx;
// NOTE: request => PlatformRequest. To get Express.Request use ctx.getRequest<Express.Request>();
return {
method: request.method,
url: request.url,
headers: request.headers,
body: request.body,
query: request.query,
params: request.params
};
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Another example to redact some fields:
import {Context} from "@tsed/common";
import {OverrideProvider} from "@tsed/di";
import {PlatformLogMiddleware} from "@tsed/platform-log-middleware";
@OverrideProvider(PlatformLogMiddleware)
export class CustomPlatformLogMiddleware extends PlatformLogMiddleware {
attributesToHide = ["password", "client_secret"];
private redactAttributes(body: any): any {
if (body) {
for (const attribute of this.attributesToHide) {
if (body[attribute]) {
body[attribute] = "[REDACTED]";
}
}
}
return body;
}
requestToObject(ctx: Context): any {
const {request} = ctx;
return {
method: request.method,
url: request.url,
route: request.route,
headers: request.headers,
body: this.redactAttributes(request.body),
query: request.query,
params: request.params
};
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Shutdown logger
Shutdown returns a Promise that will be resolved when @tsed/logger has closed all appenders and finished writing log events. Use this when your program exits to make sure all your logs are written to files, sockets are closed, etc.
import {$log} from "@tsed/logger";
$log.shutdown().then(() => {
console.log("Complete");
});
2
3
4
5
Last Updated: 10/5/2024, 7:24:49 PM
Other topics
- Session & cookies
- Passport.js
- Keycloak
- Prisma
- TypeORM
- MikroORM
- Mongoose
- GraphQL
- GraphQL WS
- Apollo
- TypeGraphQL
- GraphQL Nexus
- Socket.io
- Swagger
- AJV
- Multer
- Serve static files
- Templating
- Serverless HTTP
- Seq
- OIDC
- Stripe
- Agenda
- Terminus
- Serverless
- Server-sent events
- IORedis
- Vike
- Jest
- Vitest
- Controllers
- Providers
- Model
- JsonMapper
- Middlewares
- Pipes
- Interceptors
- Authentication
- Hooks
- Exceptions
- Throw HTTP Exceptions
- Cache
- Command
- Response Filter
- Injection scopes
- Custom providers
- Lazy-loading provider
- Custom endpoint decorator
- Testing
- Customize 404