npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adatechnology/logger

v0.0.9

Published

Pacote que expõe um provider de logs seguindo o padrão das outras libs do monorepo.

Readme

Logger provider

Pacote que expõe um provider de logs seguindo o padrão das outras libs do monorepo.

Exporta LoggerModule e o token LOGGER_PROVIDER.

Exemplos de uso

  1. Uso padrão (Winston como implementação padrão):
import { Module } from "@nestjs/common";
import { LoggerModule } from "@adatechnology/logger";

@Module({
  imports: [
    // Opção 1: Configuração estática (forRoot)
    LoggerModule.forRoot({
      level: "debug",
      context: "MyService",
      isProduction: process.env.NODE_ENV === "production",
      colorize: true,
    }),

    // Opção 2: Configuração dinâmica (forRootAsync)
    LoggerModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        level: configService.get("LOG_LEVEL"),
        isProduction: configService.get("NODE_ENV") === "production",
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}
  1. Customizando o Winston e adicionando chaves sensíveis para ofuscar:
import { Module } from "@nestjs/common";
import { LoggerModule } from "@adatechnology/logger";
import { transports } from "winston";

const loggerOptions = {
  level: "debug",
  transports: [new transports.Console()],
};

@Module({
  imports: [
    LoggerModule.forRoot({
      loggerOptions,
      // obfuscatorKeys aceita strings ou objetos { key, obfuscator }
      obfuscatorKeys: [
        "password",
        {
          key: "creditCard",
          obfuscator: (v: any) =>
            typeof v === "string" ? v.replace(/\d(?=\d{4})/g, "*") : "****",
        },
      ],
    }),
  ],
})
export class AppModule {}
  1. Injetando o provider e usando nos serviços:
import { Inject, Injectable } from "@nestjs/common";
import { LOGGER_PROVIDER } from "@adatechnology/logger";
import type { LoggerProviderInterface } from "@adatechnology/logger";

@Injectable()
export class FooService {
  constructor(
    @Inject(LOGGER_PROVIDER) private readonly logger: LoggerProviderInterface,
  ) {
    this.logger.info({ message: "iniciando FooService" });
  }
}

Observação: o obfuscator padrão é aplicado recursivamente em objetos e aceita entradas do tipo string (nome do campo) ou objetos { key, obfuscator } para permitir funções customizadas do usuário.

Se quiser, eu adiciono um exemplo de teste unitário para validar o comportamento do obfuscator.

Padrão de Logging (Desenvolvimento)

Este pacote implementa um formato de log padronizado para todo o monorepo, facilitando o rastreamento de chamadas entre múltiplas bibliotecas e serviços.

Formato Final

[App-name@version][lib-name:version][requestId][timestamp][source][libMethod][LEVEL] - message - {payload}

Propriedades do Payload

Ao realizar um log, você pode passar as seguintes propriedades para enriquecer o contexto:

  • message: A mensagem principal do log.
  • context: O contexto geral (ex: nome da classe da biblioteca).
  • source: O chamador original (breadcrumb). Ex: HttpClientController.listPokemon.
  • lib: Nome da biblioteca que está gerando o log. Ex: @adatechnology/http-client.
  • libVersion: Versão da biblioteca.
  • libMethod: O método interno da biblioteca sendo executado. Ex: get.
  • meta: Objeto com metadados adicionais (será exibido em uma única linha compacta).

Padrão recomendado: enviar payload estruturado em meta.

⚠️ Compatibilidade legada: payload em params ainda é aceito e promovido para meta internamente para não quebrar serviços antigos.

meta vs params (recomendação)

Use meta para todo conteúdo estruturado de log (request/response/error/details).

Exemplo recomendado:

this.logger.error({
  message: "Exception caught in filter",
  context: "HttpExceptionFilter.logResponse",
  requestId,
  meta: {
    request: { path, method, headers, params, query, body },
    response: { status, headers, messages },
    error: { type, message, status, body, details },
  },
});

Exemplo legado (ainda funciona, mas evite em código novo):

this.logger.error({
  message: "Exception caught in filter",
  context: "HttpExceptionFilter.logResponse",
  requestId,
  params: {
    request: { path, method, headers, params, query, body },
    response: { status, headers, messages },
    error: { type, message, status, body, details },
  },
});

Exemplo de Log de Biblioteca

Para uma biblioteca que segue o padrão:

this.logger.info({
  message: 'HTTP Request GET https://pokeapi.co/api/v2/pokemon',
  context: 'HttpRedisClient',
  lib: '@adatechnology/http-client',
  libVersion: '0.0.2',
  libMethod: 'get',
  source: 'HttpClientController.listPokemon', // vindo do logContext da chamada
  meta: { ... }
});

Resultado visual: [[email protected]][@adatechnology/http-client:0.0.2][req-id][2026-03-29...][HttpClientController.listPokemon][HttpRedisClient.get][INFO] - HTTP Request... - { headers: ... }

Middleware e contexto automático

O pacote oferece um middleware RequestContextMiddleware que injeta um requestId (a partir do header x-request-id ou gerando um UUID) e executa a request dentro de um contexto assíncrono (AsyncLocalStorage). Para usá-lo no NestJS:

import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import { RequestContextMiddleware, LoggerModule } from "@adatechnology/logger";

@Module({ imports: [LoggerModule.forRoot()] })
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(RequestContextMiddleware).forRoutes("*");
  }
}

Com o middleware ativo, o logger automaticamente incluirá requestId nos metadados quando não for passado explicitamente.

Request-scoped provider

Se desejar um provider por request (cada request recebe uma instância com setContext isolado), passe requestScoped: true ao forRoot:

LoggerModule.forRoot({ requestScoped: true });