Integrating Dapr JS SDK logging into NestJS

When we are working with a framework, we want to be able to pipe as much logging as we can to this framework. This ensures that we can process the logging without having to do much customization later on.

While working with the Dapr JS SDK, logging is implemented for us through a default service. Luckily however, we are able to adapt this logging implementation such that we can integrate it in the Nest.js framework its logging.

Creating a Dapr Module

First in nestjs we should create a Dapr Module. For this create a folder that looks like the below:

dapr/
  dapr.logger.ts
  dapr.module.ts
  dapr.service.ts

Next, open the dapr.module.ts file and add the module code

import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { DaprService } from "./dapr.service";

@Module({
    // List of imported modules
    imports: [ ConfigModule ],

    // List of controllers
    controllers: [ ],

    // Providers that will be instantiated by the Nest injector and that may be shared at least across this module
    providers: [ DaprService ],
    
    // which providers can be used in other modules?
    exports: [ DaprService ]
})
export class DaprModule {}

And configure our app.module.ts to utilize the module

import {
  Module,
} from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import configuration from '../config/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DaprModule } from './dapr/dapr.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [configuration],
    }),
    DaprModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Implementing the Dapr Logger into Nestjs

As shown on the Dapr documentation we can integrate a logger by implementing the logger interface and passing it to the Dapr Client.

So in our dapr.logger.ts file we can write

import { Logger } from '@nestjs/common';
import { LoggerService } from '@dapr/dapr';

export class DaprLogger implements LoggerService {
  private readonly logger = new Logger(DaprLogger.name);

  constructor() {}

  error(message: any, ...optionalParams: any[]): void {
    this.logger.error(message, ...optionalParams);
  }

  warn(message: any, ...optionalParams: any[]): void {
    this.logger.warn(message, ...optionalParams);
  }

  info(message: any, ...optionalParams: any[]): void {
    this.logger.log(message, ...optionalParams);
  }

  verbose(message: any, ...optionalParams: any[]): void {
    this.logger.verbose(message, ...optionalParams);
  }

  debug(message: any, ...optionalParams: any[]): void {
    this.logger.debug(message, ...optionalParams);
  }
}

Which very easily implements each method and utilizes the @nestjs/common logger to pipe its messages.

Configuring the Dapr JS SDK with the Logger

Finally, since we have a Logger implemented, we can now start up the Dapr Client with the implemented logger. Open up dapr.service.ts and add the following code:

import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DaprClient, CommunicationProtocolEnum, LogLevel } from '@dapr/dapr';
import { DaprLogger } from './dapr.logger';

@Injectable()
export class DaprService {
  daprClient: DaprClient;
  private readonly logger = new Logger(DaprService.name);

  constructor(private readonly configService: ConfigService) {
    const daprHost = this.configService.get<string>('third_party.dapr.host');
    const daprPort = this.configService.get<string>('third_party.dapr.port');

    this.logger.log(`Initializing DaprClient("${daprHost}", ${daprPort})`);
    this.daprClient = new DaprClient(
      daprHost,
      daprPort,
      CommunicationProtocolEnum.HTTP,
      {
        logger: {
          level: LogLevel.Verbose,
          service: new DaprLogger(),
        },
      },
    );
  }
}

The above will load the Dapr sidecar connection details and start a client using our custom logger

Summary

When we now start up our application, we will see the following

Show how beautiful the Dapr JS SDK has been integrated in Nest.js. All of this, taking just 5 minutes.