0.1.10 • Published 8 months ago

@ikualo/lib-ms-log v0.1.10

Weekly downloads
-
License
ISC
Repository
-
Last release
8 months ago

lib-ms-log

npm version

NPM

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"}
0.1.10

8 months ago

0.1.8

8 months ago

0.1.7

8 months ago

0.1.9

8 months ago

0.1.6

8 months ago

0.1.5

8 months ago

0.1.4

8 months ago

0.1.3

8 months ago

0.1.2

8 months ago

0.1.1

8 months ago

0.1.0

8 months ago

0.0.2

8 months ago

0.0.1

8 months ago