@ikualo/lib-ms-log v0.1.10
lib-ms-log
lib-ms-log is a log management library for the Íkualo Microservices Ecosystem. This library sets a standard for creating logs in various ways.
This library is centered around two main utilities:
- The creation of logs. This can be done manually, or using decorators.
- The usage of nest-winston, to change the default Nest.js logger with winston.
Getting Started
This library is expected to work in Nest.js environments, as the decorators and the winston module are created for this framework.
Installing the Library
Before using the library, we need to install it. We'll use npm for this example:
npm install @ikualo/lib-ms-log@latest
Using the Library
The library centers around making logs and showing information to the developer. This can be done in various ways, we'll start showing the most important part: the connection of the winston logger to the app.
We'll follow most of the documentation from nest-winston
with a few small changes. So, we will start by defining the configuration for the app.module.ts
of a
basic Nest.js application.
import { Module, Logger } from "@nestjs/common";
import { ClsModule } from "nestjs-cls";
@Module({
providers: [Logger],
imports: [ClsModule],
})
export class AppModule {}
As we can see, we have to register the main Logger
class from Nest.js as a provider, and import the
ClsModule
from the nest-cls package. This package allows
us to store information in the context of the request made to the service. We'll use this to get the
TRACKING_ID_HEADER
from the request. We'll see more about the tracking ID when we use the
TrackingIdInterceptor
.
With the app.module.ts
created and configured, we can start connecting the microservice and main logger
to the Nest.js application.
Connecting the Logger
We want to replace the default Nest.js logger, so any log made with thedefault Logger
class will use
the winston implementation:
// src/main.ts
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
import { createIkualoWinstonLogger } from "@ikualo/lib-ms-log";
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
},
logger: WinstonModule.createLogger(createIkualoWinstonLogger()),
);
await app.listen();
}
bootstrap();
Now, any call done with the Logger
class, will be redirected to our winston logger. The usage of
the default Nest.js Logger can be seen in their documentation.
Using the Logger
We can use our registered logger in two main ways: using the library @Log
decorator, or using the
Logger
directly.
Using the Decorator
The decorator can be registered in any method, and it will use our registered logger to show the developer information about how the method is being called, and what does it return.
!NOTE We recomend you use this decorator only for development purposes, as it's too granular and gives us too much information for a production environment.
We'll register the @Log
decorator in a test service to see how it works:
import { Injectable } from "@nestjs/common";
import { Log } from "@ikualo/lib-ms-log";
import { hideProperties } from "@ikualo/lib-ms-log/util";
@Injectable()
class TestService {
@Log()
decoratorTest() {
// Do something...
}
@Log({
transform: hideProperties(["password"]),
})
hidePropertiesTest(data: object) {
return {
user: "test",
password: "test",
};
}
}
We have created two methods: decoratorTest
, which uses the @Log
decorator as is, and a
hidePropertiesTest
method, which uses the transform property from the decorator.
When decoratorTest
is called, the log decorator will print two debug
level messages;
one containing information about how the method is being called; and another message with
information about the result of the method. It will look something like:
Event Type: DEBUG - Message: >>> Tracking ID: [1234] | decoratorTest - {"context":"TestService","timestamp":"2024-10-23 09:03:54"}
Event Type: INFO - Message: This is a test. - {"timestamp":"2024-10-23 09:03:54"}
Event Type: DEBUG - Message: <<< Tracking ID: [1234] | decoratorTest - {"context":"TestService","timestamp":"2024-10-23 09:03:54"}
As we can see, the decorator automatically uses the tracking ID from the request context and adds it to the log.
When hidePropertiesTest
is called, the decorator will execute the function passed through
the transform
property. It can be any function that modifies the data that's being supplied
to the log decorator.
Imagine we have some data that we don't want to show with the decorator, in this case
the hidePropertiesTest
method returns some user information. If we want to hide, say, the
password, we can use the util function hideProperties
, and it will not show that information
in the debug
log. It will look something like:
Event Type: DEBUG - Message: >>> Tracking ID: [1234] | hidePropertiesTest Request: { name: 'test' } - {"context":"TestService","timestamp":"2024-10-23 09:47:01"}
Event Type: DEBUG - Message: <<< Tracking ID: [1234] | hidePropertiesTest Request: { name: 'test' } - {"context":"TestService","timestamp":"2024-10-23 09:47:01"}
Using the Logger Directly
If you want to log something directly, you can use the Logger
object provided via dependency
injection by Nest.js, as:
import { Injectable, Logger, Inject } from "@nestjs/common";
import { Log } from "@ikualo/lib-ms-log";
import { hideProperties } from "@ikualo/lib-ms-log/util";
@Injectable()
class TestService {
constructor(@Inject(Logger) private readonly logger: Logger) {}
@Log()
decoratorTest() {
// Do something...
}
@Log({
transform: hideProperties(["password"]),
})
hidePropertiesTest() {
this.logger.log("This is a test.");
return {
name: "test",
password: "test",
};
}
}
We can do this, because we added the provider in the app.module.ts
. If we call now hidePropertiesTest
,
we'll see something like:
Event Type: DEBUG - Message: >>> Tracking ID: [1234] | hidePropertiesTest - {"context":"TestService","timestamp":"2024-10-23 10:09:20"}
Event Type: INFO - Message: This is a test. - {"timestamp":"2024-10-23 10:09:20"}
Event Type: DEBUG - Message: <<< Tracking ID: [1234] | hidePropertiesTest Request: { name: 'test' } - {"context":"TestService","timestamp":"2024-10-23 10:09:20"}