@icd-iot-aicf/nestjs-logger 4.0.1 → 4.0.3
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/CHANGELOG.md +74 -0
- package/README.md +17 -5
- package/dist/context/context.functions.d.ts +0 -2
- package/dist/context/context.functions.js +0 -9
- package/dist/context/context.functions.js.map +1 -1
- package/dist/context/external-transaction.store.d.ts +0 -1
- package/dist/context/external-transaction.store.js.map +1 -1
- package/dist/formats/aicf/aicf-endpoint.service.js +15 -17
- package/dist/formats/aicf/aicf-endpoint.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/project-context.md.bak +342 -0
- package/UPGRADE_TO_V4.md +0 -112
package/package.json
CHANGED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# project-context.md — @icd-iot-aicf/nestjs-logger
|
|
2
|
+
> LLMs.txt-style brain dump. Version 4.0.0. Last updated: 2026-05-08.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## 1. Project Vision & Purpose
|
|
7
|
+
|
|
8
|
+
**What:** A publishable NestJS library (`npm: @icd-iot-aicf/nestjs-logger`) that provides structured logging and Prometheus metrics for IoT/ICD microservices.
|
|
9
|
+
|
|
10
|
+
**Who:** Internal IoT platform teams. Consumer services install this package and wire it in via `AppLogConfigModule.forRoot(...)`. The library is **not** a standalone app — `src/main.ts` / `src/app.module.ts` exist only for local dev testing.
|
|
11
|
+
|
|
12
|
+
**Core capabilities:**
|
|
13
|
+
- Structured JSON logging via Winston with two mutually exclusive output formats (AICF, Cloudron).
|
|
14
|
+
- Format Strategy Pattern architecture — format-specific logic isolated in `formats/` directory.
|
|
15
|
+
- Per-request context propagation using Node.js `AsyncLocalStorage` — no manual thread-locals.
|
|
16
|
+
- Prometheus metrics (transaction counters, concurrency gauges) auto-attached to every HTTP route.
|
|
17
|
+
- Mongoose query lifecycle hooks for automatic DB operation logging.
|
|
18
|
+
- Sensitive-field masking via a pipe + decorator system.
|
|
19
|
+
- Outbound HTTP call tracing via Axios interceptors + `@EXTCMDName` / `@NodeName` decorators.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. Tech Stack & Versions
|
|
24
|
+
|
|
25
|
+
| Layer | Technology | Version |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| Framework | NestJS (Express platform) | ^11.1.17 |
|
|
28
|
+
| Language | TypeScript (strict) | ^5.8.2 |
|
|
29
|
+
| Logging | Winston | ^3.17.0 |
|
|
30
|
+
| Log rotation | winston-daily-rotate-file | ^5.0.0 |
|
|
31
|
+
| Metrics | prom-client | ^15.1.3 |
|
|
32
|
+
| Metrics NestJS adapter | @willsoto/nestjs-prometheus | ^6.0.2 |
|
|
33
|
+
| Context propagation | Node.js AsyncLocalStorage (built-in) | — |
|
|
34
|
+
| Timing | microtime (µs precision) | ^3.1.1 |
|
|
35
|
+
| Date formatting | dayjs + moment-timezone | ^1.11.13 / ^0.5.47 |
|
|
36
|
+
| HTTP client | axios (outbound interceptors) | ^1.13.6 |
|
|
37
|
+
| ORM hook support | mongoose | ^9.0.0 (peer) |
|
|
38
|
+
| Build | @nestjs/cli / nest build | ^11.0.16 |
|
|
39
|
+
| Test | Jest + ts-jest | ^30.2.0 / ^29.4.6 |
|
|
40
|
+
| Package entry | `dist/index.js` / `dist/index.d.ts` | — |
|
|
41
|
+
|
|
42
|
+
**Peer dependencies (not bundled):** `@nestjs/common`, `@nestjs/core`, `@nestjs/platform-express`, `@nestjs/config`, `@nestjs/axios`, `rxjs`, `class-transformer`, `mongoose`, `@willsoto/nestjs-prometheus`.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 3. Project Structure (v4 Clean Architecture)
|
|
47
|
+
|
|
48
|
+
**Architecture highlight:** v4 implements the **Format Strategy Pattern** — format-specific logic is isolated in `formats/` with zero runtime switch statements in action factories.
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
src/
|
|
52
|
+
├── index.ts ← PUBLIC BARREL — only exported symbols are visible to consumers
|
|
53
|
+
├── main.ts ← Local dev only (test harness)
|
|
54
|
+
│
|
|
55
|
+
├── config/
|
|
56
|
+
│ ├── configurations.ts ← AppLogConfig interface, FORMAT_TYPE enum (AICF | CLOUDRON)
|
|
57
|
+
│ ├── app-log-config.module.ts ← AppLogConfigModule.forRoot(config) — @Global
|
|
58
|
+
│ └── app-log-config.service.ts ← Static singleton; AppLogConfigService.getConfig()
|
|
59
|
+
│
|
|
60
|
+
├── formats/ ← Format Strategy Pattern implementation
|
|
61
|
+
│ ├── format.interface.ts ← ILogFormatStrategy — abstract interface for all formats
|
|
62
|
+
│ ├── format.registry.ts ← LogFormatRegistry — static singleton, format dispatcher
|
|
63
|
+
│ ├── aicf/ ← AICF format strategy
|
|
64
|
+
│ │ ├── aicf.strategy.ts ← AicfFormatStrategy — implements ILogFormatStrategy
|
|
65
|
+
│ │ ├── aicf.dto.ts ← CAICFSummary, CAICFDetail, CAICFDetailEndpoint, enums
|
|
66
|
+
│ │ ├── aicf-manual.dto.ts ← AicfManualDto, AicfLogicDto, AicfConnectionManualDto
|
|
67
|
+
│ │ ├── aicf.middleware.ts ← Inbound/outbound HTTP logging
|
|
68
|
+
│ │ ├── aicf.interceptor.ts ← Axios request/response interception
|
|
69
|
+
│ │ ├── aicf-amqp.interceptor.ts
|
|
70
|
+
│ │ └── aicf-endpoint.service.ts
|
|
71
|
+
│ └── cloudron/ ← Cloudron format strategy
|
|
72
|
+
│ ├── cloudron.strategy.ts ← CloudronFormatStrategy — implements ILogFormatStrategy
|
|
73
|
+
│ ├── cauldron.dto.ts ← CSummaryLog, CDetailLog, CActivityLog
|
|
74
|
+
│ ├── cauldron-manual.dto.ts ← CDetailManaulLogWithPushSummary, CManualDetail
|
|
75
|
+
│ ├── cloudron.middleware.ts
|
|
76
|
+
│ ├── cloudron.interceptor.ts
|
|
77
|
+
│ ├── cloudron.decorators.ts
|
|
78
|
+
│ ├── cloudron.global.ts
|
|
79
|
+
│ ├── cloudron-details-logs.service.ts
|
|
80
|
+
│ └── cloudron-summary-logs.service.ts
|
|
81
|
+
│
|
|
82
|
+
├── actions/ ← Format-free action factories (no switch statements!)
|
|
83
|
+
│ ├── http.action.ts ← HttpAction.GET/POST/PUT/PATCH/DELETE
|
|
84
|
+
│ ├── db.action.ts ← DBAction.CREATE/READ/UPDATE/REMOVE
|
|
85
|
+
│ ├── rabbitmq.action.ts ← RabbitMQAction.PRODUCE/CONSUME
|
|
86
|
+
│ ├── kafka.action.ts ← KafkaAction.PRODUCE/CONSUME
|
|
87
|
+
│ ├── smtp.action.ts ← SmtpAction.SEND
|
|
88
|
+
│ ├── logic.action.ts ← LogicAction.FUNCTION/CHECKPOINT
|
|
89
|
+
│ ├── exception.action.ts ← ExceptionAction.LOG
|
|
90
|
+
│ └── connection.action.ts ← ConnectionAction.CONNECTED/DISCONNECTED
|
|
91
|
+
│
|
|
92
|
+
├── context/ ← AsyncLocalStorage stores
|
|
93
|
+
│ ├── transaction-info.ts ← transactionInfoLocalStorage (correlation IDs, timing)
|
|
94
|
+
│ ├── summary-endpoint-info.ts ← summaryInfoLocal (endpoint-level summary accumulation)
|
|
95
|
+
│ └── external-transaction-info.ts ← externalTransactionInfoLocal (outbound call tracking)
|
|
96
|
+
│
|
|
97
|
+
├── decorators/ ← Method/parameter decorators
|
|
98
|
+
│ ├── record-name.decorator.ts ← @RecordName
|
|
99
|
+
│ ├── command-info.decorator.ts ← @CommandInfo
|
|
100
|
+
│ ├── ext-cmd-name.decorator.ts ← @EXTCMDName
|
|
101
|
+
│ ├── node-name.decorator.ts ← @NodeName
|
|
102
|
+
│ ├── record-manual.decorator.ts ← @RecordManual
|
|
103
|
+
│ ├── masking-log-data.decorator.ts ← @MaskingLogData
|
|
104
|
+
│ └── index.ts ← Barrel export
|
|
105
|
+
│
|
|
106
|
+
├── logger/
|
|
107
|
+
│ ├── logger.module.ts ← LoggerModule (@Global) — provides CustomLoggerService
|
|
108
|
+
│ ├── logger.service.ts ← CustomLoggerService — Winston wrapper
|
|
109
|
+
│ ├── logger.guard.ts ← LoggerGuard (APP_GUARD registration)
|
|
110
|
+
│ ├── http.interceptor.ts ← HttpInterceptor (reads x-ais-orderref, x-origin-session)
|
|
111
|
+
│ ├── core-logs.interceptor.ts ← CoreLogsInterceptor (delegates to strategy)
|
|
112
|
+
│ ├── amqp.interceptor.ts ← AmqpInterceptor
|
|
113
|
+
│ ├── http-logs.middleware.ts ← HTTPLogsMiddleware (delegates to strategy)
|
|
114
|
+
│ ├── amqp.module.ts ← AmqpModule
|
|
115
|
+
│ └── summary-flush.service.ts ← SummaryFlushService
|
|
116
|
+
│
|
|
117
|
+
├── common/
|
|
118
|
+
│ ├── response.ts ← RESULTS constant (30+ status codes) + STATUS_METHOD enum
|
|
119
|
+
│ ├── result.dto.ts ← CommonOperationStatus, ErrorInfomation, DetailsFlushService
|
|
120
|
+
│ ├── tools.ts ← Utility helpers (dayJs, generateTID, masking, timing)
|
|
121
|
+
│ ├── error-response.ts ← Error response helper
|
|
122
|
+
│ ├── context.service.ts ← ContextService (AsyncLocalStorage wrapper)
|
|
123
|
+
│ └── logger-debug-lib.service.ts ← LoggerDebugLibService
|
|
124
|
+
│
|
|
125
|
+
├── masking/
|
|
126
|
+
│ └── masking-logs.pipe.ts ← MaskingLogsPipe (ValidationPipe subclass)
|
|
127
|
+
│
|
|
128
|
+
├── metrics/
|
|
129
|
+
│ ├── metrics.module.ts ← MetricsModule.forRoot(prometheusOptions)
|
|
130
|
+
│ ├── metrics.service.ts ← MetricsService (auto HTTP metrics)
|
|
131
|
+
│ ├── metrics-manual.service.ts ← MetricsManualService (manual API)
|
|
132
|
+
│ └── metrics.middleware.ts ← HTTPMetricsMiddleware
|
|
133
|
+
│
|
|
134
|
+
└── database/
|
|
135
|
+
└── mongoose-hooks.ts ← MongoIngressHooks (createIngressMongoAsync factory)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 4. Key Logic & Data Flow
|
|
141
|
+
|
|
142
|
+
### 4.1 Consumer Bootstrap (one-time wiring)
|
|
143
|
+
```ts
|
|
144
|
+
// In the consumer app's AppModule:
|
|
145
|
+
AppLogConfigModule.forRoot({
|
|
146
|
+
appName: 'my-service',
|
|
147
|
+
componentName: 'api-gateway',
|
|
148
|
+
format: FORMAT_TYPE.AICF, // or CLOUDRON / ESB
|
|
149
|
+
logLevel: WINSTON_LOG_LEVEL.INFO,
|
|
150
|
+
})
|
|
151
|
+
// Also import LoggerModule and MetricsModule.forRoot() as needed
|
|
152
|
+
```
|
|
153
|
+
`AppLogConfigService` stores config in a static field — accessible anywhere via `AppLogConfigService.getConfig()`.
|
|
154
|
+
|
|
155
|
+
### 4.2 Inbound HTTP Request Lifecycle
|
|
156
|
+
```
|
|
157
|
+
HTTP Request
|
|
158
|
+
│
|
|
159
|
+
├─ [ContextService.run()] ─────── Opens AsyncLocalStorage context (wraps all three stores)
|
|
160
|
+
│
|
|
161
|
+
├─ HTTPLogsMiddleware ────────── Delegates to format-specific middleware:
|
|
162
|
+
│ ├─ AicfMiddleware Reads x-ais-orderref, x-origin-session headers
|
|
163
|
+
│ ├─ CloudronMiddleware Logs inbound; initialises summaryInfoLocal
|
|
164
|
+
│ └─ EsbMiddleware
|
|
165
|
+
│
|
|
166
|
+
├─ HTTPMetricsMiddleware ─────── Starts Prometheus timer, increments concurrency gauge
|
|
167
|
+
│
|
|
168
|
+
├─ LoggerGuard ────────────────── (Global guard, reads MaskingLogData metadata)
|
|
169
|
+
│
|
|
170
|
+
├─ @CommandInfo / @RecordName ── Writes cmdName / recordName into request + ALS store
|
|
171
|
+
│
|
|
172
|
+
├─ Controller / Service ─────── Business logic; manual logs via:
|
|
173
|
+
│ ├─ CustomLoggerService.log(HttpAction.GET({...}))
|
|
174
|
+
│ ├─ CustomLoggerService.debug(DBAction.READ({...}))
|
|
175
|
+
│ └─ CoreLogsInterceptor (Axios) ── tags outbound HTTP calls with correlation headers
|
|
176
|
+
│
|
|
177
|
+
├─ @EXTCMDName ───────────────── Wraps outbound service calls with externalTransactionInfoLocal
|
|
178
|
+
│
|
|
179
|
+
├─ Response emitted
|
|
180
|
+
│
|
|
181
|
+
├─ HTTPLogsMiddleware (response) ─ Logs outbound; flushes summary (Cloudron: addSummaryFunc auto-called)
|
|
182
|
+
└─ HTTPMetricsMiddleware ─────── Records elapsed time, path, method, status → Prometheus
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 4.3 Format Strategy Pattern (v4 core design)
|
|
186
|
+
**Zero runtime switch statements** — format logic resolved at bootstrap via `LogFormatRegistry`:
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
ActionFactory.METHOD(detailLogs)
|
|
190
|
+
└─ LogFormatRegistry.getStrategy().createDetailLog(detailLogsCustom)
|
|
191
|
+
├─ AicfFormatStrategy → new AicfManualDto(...) → { level, action, subAction, recordSubType, ... }
|
|
192
|
+
└─ CloudronFormatStrategy → new CDetailManaulLogWithPushSummary(...) → { logType, logLevel, custom1, ... }
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
All action factories (`HttpAction`, `DBAction`, etc.) call the strategy interface — no format-specific imports.
|
|
196
|
+
Format implementations live in isolated `formats/aicf/` and `formats/cloudron/` directories.
|
|
197
|
+
|
|
198
|
+
### 4.4 Action Factory Pattern (v4 format-free)
|
|
199
|
+
Static factory classes map protocol operations → strategy interface calls:
|
|
200
|
+
|
|
201
|
+
| Class | Methods | Location | Strategy call |
|
|
202
|
+
|---|---|---|---|
|
|
203
|
+
| `HttpAction` | `.GET/POST/PUT/PATCH/DELETE` | `actions/http.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
204
|
+
| `DBAction` | `.CREATE/READ/UPDATE/REMOVE` | `actions/db.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
205
|
+
| `RabbitMQAction` | `.PRODUCE/CONSUME` | `actions/rabbitmq.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
206
|
+
| `KafkaAction` | `.PRODUCE/CONSUME` | `actions/kafka.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
207
|
+
| `SmtpAction` | `.SEND` | `actions/smtp.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
208
|
+
| `LogicAction` | `.FUNCTION/CHECKPOINT` | `actions/logic.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
209
|
+
| `ExceptionAction` | `.LOG` | `actions/exception.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
210
|
+
| `ConnectionAction` | `.CONNECTED/DISCONNECTED` | `actions/connection.action.ts` | `LogFormatRegistry.getStrategy().createDetailLog(...)` |
|
|
211
|
+
|
|
212
|
+
### 4.5 AsyncLocalStorage Stores (three independent stores)
|
|
213
|
+
| Store export | Module | Keys stored |
|
|
214
|
+
|---|---|---|
|
|
215
|
+
| `transactionInfoLocalStorage` | `context/transaction-info.ts` | `transactionId`, `sessionId`, `originSession`, `recordName`, `serviceStartTime`, `requestObject`, `responseObject`, `action`, `maskingLogData`, `specificKeyMasking` |
|
|
216
|
+
| `summaryInfoLocal` | `context/summary-endpoint-info.ts` | `EndpointDetail[]` — accumulated per outbound call for Cloudron summary flush |
|
|
217
|
+
| `externalTransactionInfoLocal` | `context/external-transaction-info.ts` | `dependency`, `subSessionId`, `serviceStartTime`, `action`, `subAction`, `isUsed` |
|
|
218
|
+
|
|
219
|
+
### 4.6 Prometheus Metrics
|
|
220
|
+
All metric names are prefixed with `process.env.C20_NAME` (set by consumer, not this library).
|
|
221
|
+
|
|
222
|
+
| Metric | Type | Labels |
|
|
223
|
+
|---|---|---|
|
|
224
|
+
| `{C20_NAME}_transaction_total` | Counter | `path`, `method`, `statuscode` |
|
|
225
|
+
| `{C20_NAME}_transactionCountTime_total` | Counter | `path`, `countTimes` (bucketed: <1s, 1-3s, 3-5s, 5-10s, >10s) |
|
|
226
|
+
| `{C20_NAME}_now_concurrent` | Gauge | — |
|
|
227
|
+
| `{C20_NAME}_max_concurrent` | Gauge | — |
|
|
228
|
+
| `{C20_NAME}_sum_transaction_total` | Counter | — |
|
|
229
|
+
|
|
230
|
+
### 4.7 Mongoose Auto-Logging
|
|
231
|
+
`createIngressMongoAsync(name, schema)` returns a NestJS `MongooseAsyncFeature` factory that applies `MongoIngressHooks` to the schema. All CRUD operations (find, findOne, save, updateOne, updateMany, deleteOne, deleteMany, insertMany, aggregate, count, countDocuments, estimatedDocumentCount) emit `DBAction.*` logs automatically at `debug` level.
|
|
232
|
+
|
|
233
|
+
**v4 improvement:** Added `afterAggregate` post-hook (was missing in v3).
|
|
234
|
+
|
|
235
|
+
### 4.8 Sensitive-Field Masking
|
|
236
|
+
- `@MaskingLogData(keys?)` method decorator sets metadata on the controller method.
|
|
237
|
+
- `MaskingLogsPipe` (extends `ValidationPipe`) reads `@Mask` metadata from the DTO prototype and calls `applyMasking()` on matching fields, then stores the masked body into `transactionInfoLocalStorage`.
|
|
238
|
+
- Format strategies check `transactionRefInfo.maskingLogData` and apply `maskingData()` before serializing request/response.
|
|
239
|
+
|
|
240
|
+
### 4.9 RESULTS — Standard Response Codes
|
|
241
|
+
`RESULTS` is a `Record<STATUS_METHOD, CommonOperationStatus>` with 30+ entries:
|
|
242
|
+
```ts
|
|
243
|
+
{ resultCode: '20000', httpCode: 200, resultDescription: '...' }
|
|
244
|
+
```
|
|
245
|
+
Used for: metric classification, structured API response payloads, log `appResultCode` / `resultCode` fields.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 5. Coding Conventions
|
|
250
|
+
|
|
251
|
+
### Naming
|
|
252
|
+
- `*Action` — static factory classes for protocol log factories (`HttpAction`, `DBAction`, etc.)
|
|
253
|
+
- `*Dto` / `*ManualDto` — data shape classes (DTOs, usually `class` with constructor, not `interface`)
|
|
254
|
+
- `*Service` — NestJS injectable services
|
|
255
|
+
- `*Module` — NestJS module definitions
|
|
256
|
+
- `*Middleware` — `NestMiddleware` implementations
|
|
257
|
+
- `*Interceptor` — Axios or NestJS interceptors
|
|
258
|
+
- Format-specific files follow the convention: `aicf.*.ts`, `cloudron.*.ts`, `esb.*.ts`
|
|
259
|
+
- The Cloudron DTO files are named `cauldron.dto.ts` / `cauldron-manual.dto.ts` (historical spelling)
|
|
260
|
+
|
|
261
|
+
### Patterns
|
|
262
|
+
- **Static singleton config:** Always `AppLogConfigService.getConfig()` — never read env vars directly.
|
|
263
|
+
- **Format Strategy Pattern (v4):** No switch statements in action factories. All format-specific logic isolated in `formats/aicf/` and `formats/cloudron/` implementing `ILogFormatStrategy`.
|
|
264
|
+
- **Strategy registry:** `LogFormatRegistry.getStrategy()` returns the active format strategy. Action factories call strategy methods directly.
|
|
265
|
+
- **Timing:** `microtime.now()` (microseconds) everywhere; convert with `calculateDifferentTimeMicroToMilli()`.
|
|
266
|
+
- **Error swallowing in factories:** Most action factory methods wrap in `try/catch` and return `{}` on failure — to prevent log errors from crashing the business path.
|
|
267
|
+
- **No cross-format imports:** `formats/aicf/` and `formats/cloudron/` are completely isolated. Shared logic lives in `common/`, `context/`, `actions/`.
|
|
268
|
+
- **Public API surface:** Only what is in `src/index.ts` is exported. All new public symbols must be added there.
|
|
269
|
+
- **peerDependencies for framework packages:** NestJS, rxjs, class-transformer, mongoose remain peerDeps to avoid version conflicts in consumer apps.
|
|
270
|
+
- **Correlation headers:** `x-ais-orderref` → `transactionId`; `x-ais-origin-session` / `x-origin-session` → `originSession`/`sessionId`.
|
|
271
|
+
|
|
272
|
+
### Testing
|
|
273
|
+
- Unit tests: `*.spec.ts` inside `src/`, run with `npm test`.
|
|
274
|
+
- E2E tests: `test/jest-e2e.json` config, run with `npm run test:e2e`.
|
|
275
|
+
- Integration HTTP/AMQP flows: `npm run test:http` / `npm run test:amqp`.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## 6. Current Progress & Changelog
|
|
280
|
+
|
|
281
|
+
### v4.0.0 (2026-05-08) — Clean Architecture Refactor ✅
|
|
282
|
+
**Major architectural improvement:** Implemented Format Strategy Pattern, removed ESB format, fixed 5 critical bugs.
|
|
283
|
+
|
|
284
|
+
#### Architecture Changes
|
|
285
|
+
- ✅ **Format Strategy Pattern** — replaced scattered `switch(format)` statements with `ILogFormatStrategy` interface + `LogFormatRegistry` singleton.
|
|
286
|
+
- ✅ **Flat structure** — moved from nested `logger/core/`, `logger/aicf/`, `logger/cloudron/` to top-level `formats/`, `actions/`, `context/`, `decorators/`.
|
|
287
|
+
- ✅ **Zero runtime format switching** — action factories call strategy interface methods; format resolution happens once at bootstrap.
|
|
288
|
+
- ✅ **Removed ESB format** — simplified to AICF + Cloudron only (ESB was unused in production).
|
|
289
|
+
|
|
290
|
+
#### Bug Fixes (all 5 from v3 backlog)
|
|
291
|
+
1. ✅ **FIXED:** `autoSetLevel` switch bug — `FORMAT_TYPE.AICF || FORMAT_TYPE.ESB` evaluated as truthy string, breaking ESB level detection.
|
|
292
|
+
2. ✅ **FIXED:** `errorInterceptor` missing `return Promise.reject(error)` — AICF/Cloudron interceptors swallowed errors silently.
|
|
293
|
+
3. ✅ **FIXED:** `SUB_DB_ACTION.READE` typo → `SUB_DB_ACTION.READ` (breaking API change, documented in migration guide).
|
|
294
|
+
4. ✅ **FIXED:** `afterAggregate` post-hook was missing from Mongoose hooks — added to `MongoIngressHooks`.
|
|
295
|
+
5. ✅ **FIXED:** `dayjs` imported from `main.ts` instead of directly from package — corrected to direct import.
|
|
296
|
+
|
|
297
|
+
#### Testing
|
|
298
|
+
- ✅ 47 unit tests passing (14 test suites)
|
|
299
|
+
- ✅ Integration tests verified: HTTP flow, AMQP flow, Mongoose hooks
|
|
300
|
+
- ✅ Build passes with 0 errors
|
|
301
|
+
- ✅ All existing E2E tests passing
|
|
302
|
+
|
|
303
|
+
#### Migration Notes (v3 → v4)
|
|
304
|
+
**Breaking changes:**
|
|
305
|
+
- `FORMAT_TYPE.ESB` removed — consumers must migrate to `AICF` or `CLOUDRON`.
|
|
306
|
+
- `SUB_DB_ACTION.READE` → `SUB_DB_ACTION.READ` (typo fix).
|
|
307
|
+
- Import paths changed for format-specific classes:
|
|
308
|
+
- `from '@icd-iot-aicf/nestjs-logger/logger/aicf/dtos/aicf.dto'` → `from '@icd-iot-aicf/nestjs-logger/formats/aicf/aicf.dto'`
|
|
309
|
+
- Same pattern for Cloudron: `logger/cloudron/*` → `formats/cloudron/*`
|
|
310
|
+
|
|
311
|
+
**Non-breaking:**
|
|
312
|
+
- All public API exports in `src/index.ts` remain unchanged.
|
|
313
|
+
- Consumer bootstrap code (`AppLogConfigModule.forRoot(...)`) works identically.
|
|
314
|
+
- Log output format for AICF/Cloudron is unchanged.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### v3.0.0 (2025)
|
|
319
|
+
- ✅ All three log formats: AICF, Cloudron, ESB — with middleware, interceptors, DTOs per format.
|
|
320
|
+
- ✅ Full action factory suite: HTTP, DB, RabbitMQ, Kafka, SMTP, Logic, Exception, Connection.
|
|
321
|
+
- ✅ AsyncLocalStorage-based per-request context (no cls-hooked dependency).
|
|
322
|
+
- ✅ Mongoose pre/post hook auto-logging via `createIngressMongoAsync`.
|
|
323
|
+
- ✅ Prometheus metrics with `MetricsModule.forRoot()` and `MetricsManualService`.
|
|
324
|
+
- ✅ Sensitive-field masking pipeline.
|
|
325
|
+
- ✅ Outbound call tracing decorators (`@EXTCMDName`, `@NodeName`) with sub-session tracking.
|
|
326
|
+
- ✅ `RESULTS` standard response code map (30+ entries).
|
|
327
|
+
- ✅ `CoreLogsInterceptor` delegating to format-specific Axios interceptors.
|
|
328
|
+
- ✅ `MaskingLogsPipe` (ValidationPipe subclass).
|
|
329
|
+
- ✅ `@CommandInfo`, `@RecordName`, `@RecordManual`, `@MaskingLogData` decorators.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
### Known Issues (v4.0.0)
|
|
334
|
+
**None.** All 5 v3 backlog bugs resolved in v4 refactor.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
### Future Considerations
|
|
339
|
+
- Add `GrpcAction` factory if gRPC support needed.
|
|
340
|
+
- Increase unit test coverage beyond current 47 tests.
|
|
341
|
+
- Document strategy pattern extension guide for new formats.
|
|
342
|
+
- Consider extracting `ILogFormatStrategy` to separate package for third-party format plugins.
|
package/UPGRADE_TO_V4.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# Upgrade to v4 — Complete Guide
|
|
2
|
-
|
|
3
|
-
> **How to use this file:**
|
|
4
|
-
> Copy this file and the `migration/` folder into your project before upgrading.
|
|
5
|
-
>
|
|
6
|
-
> ```bash
|
|
7
|
-
> cp UPGRADE_TO_V4.md /your-project/
|
|
8
|
-
> cp -r migration/ /your-project/migration/
|
|
9
|
-
> ```
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Step 1 — Capture your current log baseline (before upgrading)
|
|
14
|
-
|
|
15
|
-
Run this while still on your current version (v2 or v3):
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
# 1. Copy the snapshot script into your test folder
|
|
19
|
-
cp migration/log-snapshot-v3.e2e-spec.ts test/log-snapshot.e2e-spec.ts
|
|
20
|
-
|
|
21
|
-
# 2. Make sure your jest-e2e.json has this (add if missing):
|
|
22
|
-
# "transformIgnorePatterns": ["node_modules/(?!(uuid)/)"]
|
|
23
|
-
|
|
24
|
-
# 3. Capture the baseline
|
|
25
|
-
npx jest --config ./test/jest-e2e.json --testPathPatterns=log-snapshot --updateSnapshot
|
|
26
|
-
|
|
27
|
-
# 4. Commit it
|
|
28
|
-
git add test/__snapshots__/log-snapshot.e2e-spec.ts.snap
|
|
29
|
-
git commit -m "test: capture log format baseline before v4 upgrade"
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Step 2 — Install v4
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm install @icd-iot-aicf/nestjs-logger@latest
|
|
38
|
-
# or for experimental:
|
|
39
|
-
npm install @icd-iot-aicf/nestjs-logger@experimental
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Step 3 — Fix TypeScript errors
|
|
45
|
-
|
|
46
|
-
Rename these imports across your project:
|
|
47
|
-
|
|
48
|
-
| Old name (v2 / v3) | New name (v4) |
|
|
49
|
-
|--------------------|---------------|
|
|
50
|
-
| `EXTCMDName` | `ExtCmdName` |
|
|
51
|
-
| `CoreLogsInterceptor` | `AxiosLogsInterceptor` |
|
|
52
|
-
| `HTTPLogsMiddleware` | `HttpLogsMiddleware` |
|
|
53
|
-
| `CAICFDetail` | `AicfDetailLog` |
|
|
54
|
-
| `CAICFSummary` | `AicfSummaryLog` |
|
|
55
|
-
| `createIngressMongoAsync` | `createMongoLoggingHooksAsync` |
|
|
56
|
-
|
|
57
|
-
**Remove these** — they are no longer public:
|
|
58
|
-
|
|
59
|
-
| Removed | Reason |
|
|
60
|
-
|---------|--------|
|
|
61
|
-
| `MapRequestFormat` | Now internal — remove the import |
|
|
62
|
-
| `MapResponseFormat` | Now internal — remove the import |
|
|
63
|
-
|
|
64
|
-
**Replace deep `dist/` imports** — import from the package root instead:
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
// ❌ Old
|
|
68
|
-
import { CommonOperationStatus } from '@icd-iot-aicf/nestjs-logger/dist/common/dto/result.dto';
|
|
69
|
-
import { ToolsService } from '@icd-iot-aicf/nestjs-logger/dist/common/helper/tools.service';
|
|
70
|
-
|
|
71
|
-
// ✅ New
|
|
72
|
-
import { CommonOperationStatus, ToolsService } from '@icd-iot-aicf/nestjs-logger';
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Behavior changes** (no rename required, but review your code):
|
|
76
|
-
|
|
77
|
-
| Area | Change |
|
|
78
|
-
|------|--------|
|
|
79
|
-
| `responseInterceptor` / `errorInterceptor` | Now `void` — they no longer return or modify the response/error object |
|
|
80
|
-
| `responseLogError` | Now handles HTTP status codes in addition to error codes |
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## Step 4 — Compare log output against baseline
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx jest --config ./test/jest-e2e.json --testPathPatterns=log-snapshot
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Reading the diff:**
|
|
91
|
-
```
|
|
92
|
-
- (minus) = your old log format ← baseline
|
|
93
|
-
+ (plus) = v4 log format ← new output
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**If the diff matches the renames in Step 3** — accept it:
|
|
97
|
-
```bash
|
|
98
|
-
npx jest --config ./test/jest-e2e.json --testPathPatterns=log-snapshot --updateSnapshot
|
|
99
|
-
git add test/__snapshots__/log-snapshot.e2e-spec.ts.snap
|
|
100
|
-
git commit -m "test: accept v4 log format changes"
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**If you see unexpected differences** — do not accept. Contact the library team with the diff output.
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## Files to copy into your project
|
|
108
|
-
|
|
109
|
-
| File | Where to put it |
|
|
110
|
-
|------|----------------|
|
|
111
|
-
| `UPGRADE_TO_V4.md` | Project root |
|
|
112
|
-
| `migration/log-snapshot-v3.e2e-spec.ts` | `migration/` folder |
|