logixia 1.6.3 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -949,18 +949,18 @@ import { KafkaTraceInterceptor } from 'logixia';
949
949
  import { UseInterceptors, Controller } from '@nestjs/common';
950
950
  import { MessagePattern } from '@nestjs/microservices';
951
951
 
952
+ @UseInterceptors(new KafkaTraceInterceptor())
952
953
  @Controller()
953
- @UseInterceptors(KafkaTraceInterceptor)
954
954
  export class OrdersConsumer {
955
- @MessagePattern('order.created')
956
- async handle(data: OrderCreatedEvent) {
957
- // getCurrentTraceId() works here — extracted from the Kafka message
955
+ @EventPattern('order.created')
956
+ async handle(@Payload() data: OrderCreatedEvent) {
957
+ // getCurrentTraceId() works here — extracted from the Kafka message body/headers
958
958
  await logger.info('Processing order event', { orderId: data.orderId });
959
959
  }
960
960
  }
961
961
  ```
962
962
 
963
- `KafkaTraceInterceptor` and `WebSocketTraceInterceptor` are automatically provided when you use `LogixiaLoggerModule.forRoot()`. You can also inject them directly.
963
+ > **Note:** Pass `new KafkaTraceInterceptor()` (an instance), not the class reference. The interceptor's constructor takes an optional config and is not a NestJS DI provider.
964
964
 
965
965
  ### WebSocket trace interceptor
966
966
 
@@ -970,23 +970,36 @@ Propagates trace IDs through WebSocket event handlers. Reads `traceId` from the
970
970
  import { WebSocketTraceInterceptor } from 'logixia';
971
971
  import { UseInterceptors, WebSocketGateway, SubscribeMessage } from '@nestjs/websockets';
972
972
 
973
- @WebSocketGateway()
974
- @UseInterceptors(WebSocketTraceInterceptor)
973
+ @UseInterceptors(new WebSocketTraceInterceptor())
974
+ @WebSocketGateway({ namespace: '/events', cors: { origin: '*' } })
975
975
  export class EventsGateway {
976
- @SubscribeMessage('message')
977
- async handleMessage(client: Socket, data: MessagePayload) {
978
- // trace ID propagated from the WebSocket event context
979
- await logger.info('WS message received', { event: 'message' });
976
+ @SubscribeMessage('ping')
977
+ async handlePing(@MessageBody() data: { traceId?: string }) {
978
+ // trace ID propagated from the WS message body / handshake headers
979
+ await logger.info('WS ping received', { traceId: getCurrentTraceId() });
980
980
  }
981
981
  }
982
982
  ```
983
983
 
984
+ > **Note:** Pass `new WebSocketTraceInterceptor()` (an instance), not the class reference. `UseInterceptors` must be imported from `@nestjs/common`, not `@nestjs/websockets`.
985
+
986
+ ````
987
+
984
988
  ---
985
989
 
986
990
  ## NestJS integration
987
991
 
988
992
  Drop-in module with zero boilerplate. Registers `TraceMiddleware` for all routes, provides `LogixiaLoggerService`, `KafkaTraceInterceptor`, and `WebSocketTraceInterceptor` via the global DI container.
989
993
 
994
+ > **Full working example** — see [`examples/nestjs-app/`](./examples/nestjs-app/) for a complete NestJS app with Docker Compose (Postgres, MongoDB, Kafka, Kafdrop) that exercises every feature: `LogixiaLoggerModule`, `TraceMiddleware`, `LogixiaExceptionFilter`, `HttpLoggingInterceptor`, `WebSocketTraceInterceptor`, `KafkaTraceInterceptor`, `@LogMethod`, `child()` loggers, `timeAsync`, real Kafka producer + consumer.
995
+ >
996
+ > ```bash
997
+ > cd examples/nestjs-app
998
+ > cp .env.example .env
999
+ > docker compose up -d
1000
+ > curl http://localhost:3000/health
1001
+ > ```
1002
+
990
1003
  ```typescript
991
1004
  // app.module.ts
992
1005
  import { Module } from '@nestjs/common';
@@ -1006,7 +1019,7 @@ import { LogixiaLoggerModule } from 'logixia';
1006
1019
  ],
1007
1020
  })
1008
1021
  export class AppModule {}
1009
- ```
1022
+ ````
1010
1023
 
1011
1024
  **Async configuration** (for credentials from a config service):
1012
1025
 
@@ -1184,17 +1197,39 @@ import { LogixiaExceptionFilter, LogixiaLoggerService } from 'logixia';
1184
1197
  }
1185
1198
  ```
1186
1199
 
1187
- The filter returns this shape on error:
1200
+ The filter returns a consistent structured shape on every error:
1188
1201
 
1189
1202
  ```json
1190
1203
  {
1191
- "statusCode": 500,
1192
- "message": "Internal server error",
1193
- "timestamp": "2025-03-14T10:22:01.412Z",
1194
- "path": "/api/orders"
1204
+ "success": false,
1205
+ "error": {
1206
+ "type": "validation_error",
1207
+ "code": "ORD-001",
1208
+ "message": "Order amount must be greater than zero.",
1209
+ "param": "amount"
1210
+ },
1211
+ "meta": {
1212
+ "request_id": "req_8579ef8ff7a64c3cbc752fd1cb9852df",
1213
+ "timestamp": "2026-03-24T16:30:19.217Z",
1214
+ "path": "/orders/boom",
1215
+ "status": 400
1216
+ },
1217
+ "debug": {
1218
+ "stack": "LogixiaException: Order amount must be greater than zero.\n at ..."
1219
+ }
1195
1220
  }
1196
1221
  ```
1197
1222
 
1223
+ And every log line carries `method`, `url`, `status`, `request_id` as structured fields — not a plain string:
1224
+
1225
+ ```
1226
+ WARN [NestApplication] (traceId) [ORD-001] Order amount must be greater than zero.
1227
+ { method: "GET", url: "/orders/boom", status: 400, request_id: "req_..." }
1228
+
1229
+ ERROR [NestApplication] (traceId) DB connection timed out after 5000ms
1230
+ { method: "GET", url: "/orders/crash", status: 500, request_id: "req_...", error: { ... } }
1231
+ ```
1232
+
1198
1233
  ---
1199
1234
 
1200
1235
  ## Correlation ID propagation