@icd-iot-aicf/nestjs-logger
v2.0.5
Published
NestJS logging and metrics toolkit with opinionated formats (AICF, Cloudron, ESB), Winston-based logger, and Prometheus metrics. Ships with ready-to-use middleware, interceptors, and decorators for structured logs and service KPIs.
Readme
@icd-iot-aicf/nestjs-logger
NestJS logging and metrics toolkit with opinionated formats (AICF, Cloudron, ESB), Winston-based logger, and Prometheus metrics. Ships with ready-to-use middleware, interceptors, and decorators for structured logs and service KPIs.
- Logger: Winston, JSON payloads, async-context aware
- Formats: aicf | cloudron | esb
- Metrics: Prometheus counters/gauges, HTTP middleware, manual API
- Extras: standard response codes, decorators, guards, utilities
Install
npm install @icd-iot-aicf/nestjs-loggerOr
yarn add @icd-iot-aicf/nestjs-loggerRequirements:
- NestJS v11
- Express platform (default for Nest)
- Optional: set env C20_NAME to prefix Prometheus metric names
Quick start
- Configure the library (global) using AppLogConfigModule
import { Module, MiddlewareConsumer } from '@nestjs/common';
import {
AppLogConfigModule,
LoggerModule,
MetricsModule,
HTTPLogsMiddleware,
HTTPMetricsMiddleware,
} from '@icd-iot-aicf/nestjs-logger';
import { FORMAT_TYPE, DEBUG_MODE } from '@icd-iot-aicf/nestjs-logger';
@Module({
imports: [
AppLogConfigModule.forRoot({
appName: 'my-app',
componentName: 'http-api',
format: FORMAT_TYPE.AICF, // or FORMAT_TYPE.CLOUDRON, FORMAT_TYPE.ESB
logLevel: 'info', // 'info' | 'warning' | 'error' | 'debug'
debugLib: DEBUG_MODE.DISABLE,
// Optional: map result structure if your response is not the default
// structureResponse: { resultCode: 'resultCode', httpCode: 'httpCode', resultDescription: 'resultDescription' },
}),
LoggerModule,
MetricsModule.forRoot({ path: '/metrics' }), // optional options
],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(HTTPLogsMiddleware, HTTPMetricsMiddleware)
.forRoutes('*');
}
}- Register the HTTP interceptor (correlation headers)
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpInterceptor } from '@icd-iot-aicf/nestjs-logger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new HttpInterceptor());
await app.listen(3000);
}
bootstrap();- Use decorators to name your operations (recommended for better logs/metrics)
import { Controller, Get } from '@nestjs/common';
import { RecordName, CommandInfo } from '@icd-iot-aicf/nestjs-logger';
@Controller('health')
export class HealthController {
@Get()
@RecordName('HealthCheck')
@CommandInfo({ CommandName: 'HealthCheck', Description: 'API liveness probe' })
ping() {
return { ok: true };
}
}Logger usage
Inject CustomLoggerService and log structured JSON or plain strings. The library will set appropriate level fields for the chosen format.
import { Injectable } from '@nestjs/common';
import { CustomLoggerService } from '@icd-iot-aicf/nestjs-logger';
@Injectable()
export class ExampleService {
constructor(private readonly logger: CustomLoggerService) {}
doWork() {
this.logger.log({ message: 'work started' });
// ...
this.logger.warn({ message: 'slower than expected' });
// ...
this.logger.error({ message: 'failure' }, 'optional-stack-trace');
}
}Notes:
- log() is info level. Other methods: warn(), debug(), verbose(), error(message, trace?).
- Prefer structured objects; strings also work but won’t include format extras.
Automatic HTTP logs
- HTTPLogsMiddleware emits inbound/outbound logs per request using the configured format (AICF/Cloudron/ESB).
- Use @RecordName to categorize metrics/logs by endpoint/business name.
- HttpInterceptor reads correlation headers:
- x-ais-orderref: transaction id
- x-origin-session: session chain (if present)
Metrics
The library exposes a Prometheus endpoint (via @willsoto/nestjs-prometheus) and tracks:
- request totals by path/method/status
- time-bucket counters
- concurrent requests (current and max)
Setup was done in Quick start. Ensure C20_NAME is set in your environment to prefix metric names.
Manual metrics API:
import { Injectable } from '@nestjs/common';
import { MetricsManualService } from '@icd-iot-aicf/nestjs-logger';
import { RESULTS } from '@icd-iot-aicf/nestjs-logger';
@Injectable()
export class TaskRunner {
constructor(private readonly metrics: MetricsManualService) {}
async run() {
this.metrics.increment();
try {
// ... your work
this.metrics.finish('POST', RESULTS.SUCCESS);
} catch (e) {
this.metrics.finish('POST', RESULTS.INTERNAL_SERVER_ERROR);
throw e;
}
}
}Customize metrics endpoint:
MetricsModule.forRoot({ path: '/custom-metrics', defaultMetrics: { enabled: true } });Decorators for external calls
Tag outbound calls (dependencies) to enrich detail/endpoint logs.
import { EXTCMDName, NodeName } from '@icd-iot-aicf/nestjs-logger';
@NodeName('user-service')
export class UserClient {
@EXTCMDName({ cmdName: 'GetUser', action: 'HTTP', subAction: 'GET' })
async getUser() {
// call your HTTP client here
}
}Standard responses (helpers)
Use pre-defined operation statuses for consistency.
import { RESULTS } from '@icd-iot-aicf/nestjs-logger';
import { HttpCode } from '@nestjs/common';
// in controller method
@HttpCode(RESULTS.SUCCESS.httpCode)
get() {
return { ...RESULTS.SUCCESS, data: { ok: true } };
}If your response uses different field names, set structureResponse in AppLogConfigModule.forRoot so metrics can extract resultCode/httpCode.
Configuration reference
AppLogConfigModule.forRoot({ ...config })
- appName: string (required)
- componentName: string (required)
- format: FORMAT_TYPE.AICF | FORMAT_TYPE.CLOUDRON | FORMAT_TYPE.ESB (required)
- logLevel?: 'info' | 'warning' | 'error' | 'debug' (default 'info')
- debugLib?: DEBUG_MODE (default DISABLE)
- structureResponse?: { resultCode?: string; httpCode?: string; resultDescription?: string }
Common enums
import { FORMAT_TYPE, DEBUG_MODE } from '@icd-iot-aicf/nestjs-logger';What’s exported
From the package root:
- Modules: LoggerModule, MetricsModule, AppLogConfigModule
- Services: CustomLoggerService, MetricsService, MetricsManualService
- Middleware: HTTPLogsMiddleware, HTTPMetricsMiddleware
- Interceptors: HttpInterceptor, CoreLogsInterceptor, AmqpInterceptor
- Decorators: RecordName, CommandInfo, EXTCMDName, NodeName, RecordManual
- Config: FORMAT_TYPE, DEBUG_MODE
- Helpers: RESULTS, STATUS_METHOD, dayJs
Troubleshooting
- No logs? Ensure AppLogConfigModule.forRoot is imported before LoggerModule and that HTTPLogsMiddleware is applied.
- Missing correlation? Register HttpInterceptor globally.
- Metrics labels show undefined path? Use @RecordName; also ensure your controllers are hit after middleware.
- Metric names start with undefined_: set env C20_NAME in your process.
- Cloudron/ESB format specifics: pick FORMAT_TYPE matching your deployment pipeline; the library adjusts level fields automatically.
License
UNLICENSED
