logixia 1.12.4 → 1.12.6

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.
Files changed (166) hide show
  1. package/README.md +80 -27
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/async-context-CSHWoHMB.js +88 -0
  4. package/dist/async-context-CSHWoHMB.js.map +1 -0
  5. package/dist/async-context-CwBNMm2E.mjs +68 -0
  6. package/dist/async-context-CwBNMm2E.mjs.map +1 -0
  7. package/dist/azure-monitor.transport-CG7ClkYj.d.ts +62 -0
  8. package/dist/azure-monitor.transport-CG7ClkYj.d.ts.map +1 -0
  9. package/dist/azure-monitor.transport-CHnjVRF-.mjs +152 -0
  10. package/dist/azure-monitor.transport-CHnjVRF-.mjs.map +1 -0
  11. package/dist/azure-monitor.transport-Cm74kXZS.d.mts +62 -0
  12. package/dist/azure-monitor.transport-Cm74kXZS.d.mts.map +1 -0
  13. package/dist/azure-monitor.transport-CrvfHd9C.js +157 -0
  14. package/dist/azure-monitor.transport-CrvfHd9C.js.map +1 -0
  15. package/dist/azure.d.mts +3 -0
  16. package/dist/azure.d.ts +3 -0
  17. package/dist/azure.js +6 -0
  18. package/dist/azure.mjs +6 -0
  19. package/dist/batch-buffer-BY-mRWIK.js +170 -0
  20. package/dist/batch-buffer-BY-mRWIK.js.map +1 -0
  21. package/dist/batch-buffer-PGvSgbmd.mjs +132 -0
  22. package/dist/batch-buffer-PGvSgbmd.mjs.map +1 -0
  23. package/dist/browser.d.mts +427 -0
  24. package/dist/browser.d.mts.map +1 -0
  25. package/dist/browser.d.ts +427 -0
  26. package/dist/browser.d.ts.map +1 -0
  27. package/dist/browser.js +590 -0
  28. package/dist/browser.js.map +1 -0
  29. package/dist/browser.mjs +586 -0
  30. package/dist/browser.mjs.map +1 -0
  31. package/dist/chunk-DLSkYcPk.mjs +7 -0
  32. package/dist/chunk-nOFOJqeH.js +30 -0
  33. package/dist/cloudwatch.d.mts +3 -0
  34. package/dist/cloudwatch.d.ts +3 -0
  35. package/dist/cloudwatch.js +6 -0
  36. package/dist/cloudwatch.mjs +6 -0
  37. package/dist/cloudwatch.transport-CGHY4buE.d.mts +81 -0
  38. package/dist/cloudwatch.transport-CGHY4buE.d.mts.map +1 -0
  39. package/dist/cloudwatch.transport-DK_8cKd3.d.ts +81 -0
  40. package/dist/cloudwatch.transport-DK_8cKd3.d.ts.map +1 -0
  41. package/dist/cloudwatch.transport-pNBNWJLt.js +370 -0
  42. package/dist/cloudwatch.transport-pNBNWJLt.js.map +1 -0
  43. package/dist/cloudwatch.transport-yBwm4OeO.mjs +360 -0
  44. package/dist/cloudwatch.transport-yBwm4OeO.mjs.map +1 -0
  45. package/dist/coerce.utils-BN980Y9V.js +44 -0
  46. package/dist/coerce.utils-BN980Y9V.js.map +1 -0
  47. package/dist/coerce.utils-Dxv4_ikC.mjs +38 -0
  48. package/dist/coerce.utils-Dxv4_ikC.mjs.map +1 -0
  49. package/dist/correlation.d.mts +238 -0
  50. package/dist/correlation.d.mts.map +1 -0
  51. package/dist/correlation.d.ts +238 -0
  52. package/dist/correlation.d.ts.map +1 -0
  53. package/dist/correlation.js +272 -0
  54. package/dist/correlation.js.map +1 -0
  55. package/dist/correlation.mjs +261 -0
  56. package/dist/correlation.mjs.map +1 -0
  57. package/dist/gcp.d.mts +3 -0
  58. package/dist/gcp.d.ts +3 -0
  59. package/dist/gcp.js +6 -0
  60. package/dist/gcp.mjs +6 -0
  61. package/dist/gcp.transport-BJuNRFe_.mjs +192 -0
  62. package/dist/gcp.transport-BJuNRFe_.mjs.map +1 -0
  63. package/dist/gcp.transport-BOhkVKlI.d.ts +71 -0
  64. package/dist/gcp.transport-BOhkVKlI.d.ts.map +1 -0
  65. package/dist/gcp.transport-Bi6CUqZR.d.mts +71 -0
  66. package/dist/gcp.transport-Bi6CUqZR.d.mts.map +1 -0
  67. package/dist/gcp.transport-SHdtc1n0.js +198 -0
  68. package/dist/gcp.transport-SHdtc1n0.js.map +1 -0
  69. package/dist/{index-CwFww7VC.d.ts → index-BPKwwERo.d.mts} +18 -174
  70. package/dist/index-BPKwwERo.d.mts.map +1 -0
  71. package/dist/{index-DnyeaoZU.d.mts → index-C1X-TE5I.d.ts} +18 -174
  72. package/dist/index-C1X-TE5I.d.ts.map +1 -0
  73. package/dist/index.d.mts +41 -11
  74. package/dist/index.d.mts.map +1 -1
  75. package/dist/index.d.ts +40 -10
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +87 -147
  78. package/dist/index.js.map +1 -1
  79. package/dist/index.mjs +62 -132
  80. package/dist/index.mjs.map +1 -1
  81. package/dist/internal-log-BUJYMZbE.js +70 -0
  82. package/dist/internal-log-BUJYMZbE.js.map +1 -0
  83. package/dist/internal-log-Cm8SOWSV.mjs +52 -0
  84. package/dist/internal-log-Cm8SOWSV.mjs.map +1 -0
  85. package/dist/{logitron-logger.module-BIGTm2V6.mjs → logitron-logger.module-Bs3XYZgF.mjs} +266 -166
  86. package/dist/logitron-logger.module-Bs3XYZgF.mjs.map +1 -0
  87. package/dist/{logitron-logger.module-BTxDpK6u.js → logitron-logger.module-BsDZR5BH.js} +297 -203
  88. package/dist/logitron-logger.module-BsDZR5BH.js.map +1 -0
  89. package/dist/{logitron-logger.module-BmT-ewin.d.ts → logitron-logger.module-CxT1F6Cm.d.ts} +23 -10
  90. package/dist/logitron-logger.module-CxT1F6Cm.d.ts.map +1 -0
  91. package/dist/{logitron-logger.module-BCq3sF27.d.mts → logitron-logger.module-zDKVd_o0.d.mts} +23 -10
  92. package/dist/logitron-logger.module-zDKVd_o0.d.mts.map +1 -0
  93. package/dist/middleware.d.mts +5 -2
  94. package/dist/middleware.d.mts.map +1 -1
  95. package/dist/middleware.d.ts +5 -2
  96. package/dist/middleware.d.ts.map +1 -1
  97. package/dist/middleware.js +13 -4
  98. package/dist/middleware.js.map +1 -1
  99. package/dist/middleware.mjs +14 -4
  100. package/dist/middleware.mjs.map +1 -1
  101. package/dist/nest.d.mts +3 -2
  102. package/dist/nest.d.mts.map +1 -1
  103. package/dist/nest.d.ts +3 -2
  104. package/dist/nest.d.ts.map +1 -1
  105. package/dist/nest.js +6 -2
  106. package/dist/nest.mjs +6 -2
  107. package/dist/safe-stringify-DJ66tW5I.mjs +118 -0
  108. package/dist/safe-stringify-DJ66tW5I.mjs.map +1 -0
  109. package/dist/safe-stringify-DWo3aZp_.js +142 -0
  110. package/dist/safe-stringify-DWo3aZp_.js.map +1 -0
  111. package/dist/search-CFQRISUv.mjs +1596 -0
  112. package/dist/search-CFQRISUv.mjs.map +1 -0
  113. package/dist/search-CQOo-Iq6.d.mts +816 -0
  114. package/dist/search-CQOo-Iq6.d.mts.map +1 -0
  115. package/dist/search-DujhR94O.d.ts +816 -0
  116. package/dist/search-DujhR94O.d.ts.map +1 -0
  117. package/dist/search-njTI2hdo.js +1631 -0
  118. package/dist/search-njTI2hdo.js.map +1 -0
  119. package/dist/search.d.mts +4 -1
  120. package/dist/search.d.ts +4 -1
  121. package/dist/search.js +9 -1
  122. package/dist/search.mjs +3 -2
  123. package/dist/testing.d.mts +2 -1
  124. package/dist/testing.d.mts.map +1 -1
  125. package/dist/testing.d.ts +2 -1
  126. package/dist/testing.d.ts.map +1 -1
  127. package/dist/{transport.manager-ciG4r5uz.js → transport.manager-BivyUTtU.js} +497 -437
  128. package/dist/transport.manager-BivyUTtU.js.map +1 -0
  129. package/dist/{transport.manager-DETpXuaY.mjs → transport.manager-D6KL3t9V.mjs} +473 -364
  130. package/dist/transport.manager-D6KL3t9V.mjs.map +1 -0
  131. package/dist/transport.types-B5vcyv2k.d.mts +187 -0
  132. package/dist/transport.types-B5vcyv2k.d.mts.map +1 -0
  133. package/dist/transport.types-BuY84TwO.d.ts +187 -0
  134. package/dist/transport.types-BuY84TwO.d.ts.map +1 -0
  135. package/dist/transports.d.mts +90 -29
  136. package/dist/transports.d.mts.map +1 -1
  137. package/dist/transports.d.ts +90 -29
  138. package/dist/transports.d.ts.map +1 -1
  139. package/dist/transports.js +14 -2
  140. package/dist/transports.mjs +10 -2
  141. package/dist/worker-entry.js +1241 -0
  142. package/dist/worker.d.mts +3 -0
  143. package/dist/worker.d.ts +3 -0
  144. package/dist/worker.js +4 -0
  145. package/dist/worker.mjs +4 -0
  146. package/dist/worker.transport-BP8Q28Z2.d.mts +76 -0
  147. package/dist/worker.transport-BP8Q28Z2.d.mts.map +1 -0
  148. package/dist/worker.transport-BhMyvqQ2.mjs +167 -0
  149. package/dist/worker.transport-BhMyvqQ2.mjs.map +1 -0
  150. package/dist/worker.transport-CfH6z37Z.js +168 -0
  151. package/dist/worker.transport-CfH6z37Z.js.map +1 -0
  152. package/dist/worker.transport-mKXgNK0L.d.ts +76 -0
  153. package/dist/worker.transport-mKXgNK0L.d.ts.map +1 -0
  154. package/package.json +23 -18
  155. package/dist/index-CwFww7VC.d.ts.map +0 -1
  156. package/dist/index-DnyeaoZU.d.mts.map +0 -1
  157. package/dist/logitron-logger.module-BCq3sF27.d.mts.map +0 -1
  158. package/dist/logitron-logger.module-BIGTm2V6.mjs.map +0 -1
  159. package/dist/logitron-logger.module-BTxDpK6u.js.map +0 -1
  160. package/dist/logitron-logger.module-BmT-ewin.d.ts.map +0 -1
  161. package/dist/search-Cg_OasF-.d.ts +0 -1
  162. package/dist/search-DN676Dnz.d.mts +0 -1
  163. package/dist/search-DOvSI-mb.mjs +0 -1
  164. package/dist/search-DoZF3RZj.js +0 -0
  165. package/dist/transport.manager-DETpXuaY.mjs.map +0 -1
  166. package/dist/transport.manager-ciG4r5uz.js.map +0 -1
package/README.md CHANGED
@@ -202,24 +202,26 @@ logixia takes a different approach: **everything ships built-in, and nothing blo
202
202
 
203
203
  ## Performance
204
204
 
205
- logixia is async-first and built for the hot path: a synchronous fast path for in-process transports (no Promise allocated when the write completes synchronously), a millisecond-cached timestamp, lazy formatting (each transport formats once — no wasted pre-format), and per-call work (level check, namespace resolution, redaction decision) served off pre-built caches. The result: logixia **beats pino on 5 of 6 real-world scenarios**, beats winston and bunyan across the board, and keeps **p99 latency at 1–3µs** with no tail spikes.
205
+ logixia is async-first and built for the hot path: a synchronous fast path for in-process transports (no Promise allocated when the write completes synchronously), a millisecond-cached timestamp, lazy formatting (each transport formats once), and per-call work (level check, namespace resolution, redaction decision) served off pre-built caches.
206
206
 
207
- Benchmarked against **pino, winston, and bunyan** — all writing to `/dev/null` (pure serialization + framework overhead, no disk/terminal cost). Node 20, Apple M-series; numbers are ops/sec, higher is better. Reproduce with `npm run benchmark`.
207
+ Every library below writes the **same JSON output** to a null sink, so this measures serialization and framework overhead, not disk or terminal speed. Node 22, Apple Silicon, ops/sec (higher is better). Reproduce with `npm run benchmark`.
208
208
 
209
- | Scenario | pino | **logixia** | winston | bunyan |
210
- | ------------------------------ | --------: | ------------: | --------: | ------: |
211
- | Simple string log | 3,220,000 | 2,769,000 | 1,577,000 | 707,000 |
212
- | **Structured log (5 fields)** | 1,319,000 | **1,536,000** | 699,000 | 536,000 |
213
- | **Error object logging** | 907,000 | **1,940,000** | 1,062,000 | 573,000 |
214
- | **Child / per-request logger** | 1,093,000 | **1,436,000** | 321,000 | 380,000 |
215
- | **Deep nested object** | 891,000 | **1,040,000** | 435,000 | 442,000 |
216
- | **High-cardinality (12 flds)** | 651,000 | **1,027,000** | 316,000 | 404,000 |
209
+ | Scenario | pino | logixia (json) | winston |
210
+ | ---------------------------- | --------: | -------------: | --------: |
211
+ | Simple string log | 3,396,000 | 1,804,000 | 1,533,000 |
212
+ | Structured log (5 fields) | 1,308,000 | 931,000 | 729,000 |
213
+ | Error object logging | 1,192,000 | 1,587,000 | 1,078,000 |
214
+ | Child / per-request logger | 1,134,000 | 892,000 | 494,000 |
215
+ | Deep nested object | 1,327,000 | 1,023,000 | 549,000 |
216
+ | High-cardinality (12 fields) | 734,000 | 525,000 | 400,000 |
217
217
 
218
218
  **What this means:**
219
219
 
220
- - ✅ **logixia is faster than pino on 5 of 6 scenarios** — including **+114% on error logging**, **+58% on high-cardinality**, **+31% on child loggers**, and **+16% on structured logs** — the shapes that dominate real production traffic.
221
- - ✅ **logixia beats winston and bunyan in every scenario**, often by 2–3×, and avoids their tail-latency spikes (winston hit **3,038µs p99** on high-cardinality and **412µs** on deep objects; logixia stays **1–3µs p99** throughout).
222
- - ⚖️ **pino still wins the trivial simple-string case** (−14%) because it writes synchronously straight to `process.stdout` — fast in a microbenchmark, but it blocks the event loop under real I/O and is exactly the path behind pino's open [flush-on-exit log-loss bug](#graceful-shutdown). logixia stays non-blocking and guarantees delivery, and pulls ahead the moment you log anything structured.
220
+ - **pino is the fastest raw JSON serializer here.** It leads in 5 of 6 scenarios, by 21–47%. If raw throughput is the only thing you need, pino is a great choice.
221
+ - **logixia is 1.2–1.9× faster than winston in every scenario**, with p99 latency of 1–5µs, against winston's 2.5–7.5µs.
222
+ - logixia is ahead on error logging, partly because pino also serializes the full stack through its error serializer.
223
+ - logixia's default human-readable console format is faster than its JSON mode. `npm run benchmark` prints both.
224
+ - The point of logixia is everything else in one package: non-blocking file and database transports, tracing, redaction, OpenTelemetry, NestJS and the CLI. It aims to be fast enough that you never notice it, without six extra installs.
223
225
 
224
226
  **Distinctive-feature throughput** (no cross-library equivalent — `npm run benchmark:features`):
225
227
 
@@ -518,9 +520,10 @@ const logger = createLogger({
518
520
  file: {
519
521
  filename: 'app.log',
520
522
  dirname: './logs',
521
- maxSize: '50MB', // rotate when file reaches this size
522
- maxFiles: 14, // keep 14 rotated files
523
+ maxSize: '50MB', // rotate before the file passes this size ('500KB', '1GB' or bytes)
524
+ maxFiles: 14, // keep the 14 newest rotated files, delete older ones
523
525
  zippedArchive: true, // compress old files with gzip
526
+ datePattern: 'YYYY-MM-DD', // optional: also rotate when the day changes
524
527
  format: 'json', // 'json' | 'text' | 'csv'
525
528
  batchSize: 100, // buffer up to 100 entries before writing
526
529
  flushInterval: 2000, // flush buffer every 2 seconds
@@ -529,6 +532,20 @@ const logger = createLogger({
529
532
  });
530
533
  ```
531
534
 
535
+ The live file keeps its name, so `tail -f logs/app.log` keeps working. Rotated files are renamed beside it: `app-2026-10-22T09-30-00-000.log.gz`, or `app-2026-10-22.log.gz` when `datePattern` is set. Files are split on line boundaries, so no line is cut in half. On restart the transport carries on from the size of the existing `app.log`.
536
+
537
+ **Bounding memory under load.** Entries wait in memory until the disk accepts them, and by default there is no limit. Set `maxQueue` to cap how many unwritten entries (the batch being written included) the transport holds, and `queuePolicy` to choose what happens at the cap:
538
+
539
+ ```typescript
540
+ file: {
541
+ filename: 'app.log',
542
+ maxQueue: 10000,
543
+ queuePolicy: 'drop-oldest', // 'drop-oldest' (default) | 'drop-newest' | 'block'
544
+ }
545
+ ```
546
+
547
+ `drop-oldest` discards the oldest waiting entry, `drop-newest` discards the incoming one, and `block` makes `write()` wait until there is room. Dropped lines are counted and reported on stderr at most once every 5 seconds, and once more on `close()`.
548
+
532
549
  You can also use **time-based rotation** via the `rotation` sub-key:
533
550
 
534
551
  ```typescript
@@ -538,13 +555,18 @@ transports: {
538
555
  dirname: './logs',
539
556
  rotation: {
540
557
  interval: '1d', // rotate daily: '1h' | '6h' | '12h' | '1d' | '1w'
558
+ maxSize: '100MB', // and on size
541
559
  maxFiles: 30,
542
560
  compress: true,
561
+ // or decide yourself, checked before each write:
562
+ // shouldRotate: (file, { size, created }) => size > 100 * 1024 * 1024,
543
563
  },
544
564
  },
545
565
  },
546
566
  ```
547
567
 
568
+ With a `rotation` block every file is timestamped, including the one being written.
569
+
548
570
  Multiple file transports are supported — pass an array:
549
571
 
550
572
  ```typescript
@@ -642,7 +664,7 @@ logixia includes built-in support for Datadog, Mixpanel, Segment, and Google Ana
642
664
  **Datadog** — sends logs, metrics, and traces to your Datadog account:
643
665
 
644
666
  ```typescript
645
- import { DataDogTransport } from 'logixia';
667
+ import { DataDogTransport } from 'logixia/transports';
646
668
 
647
669
  const logger = createLogger({
648
670
  appName: 'api',
@@ -798,7 +820,7 @@ logixia ships three production-ready cloud transports. All are batched, non-bloc
798
820
  Batches log events and sends them to a CloudWatch Logs stream using `PutLogEvents`. Supports **EMF** (Embedded Metric Format) so numeric fields in your log entries are automatically promoted to CloudWatch Metrics — no separate SDK needed.
799
821
 
800
822
  ```typescript
801
- import { CloudWatchTransport } from 'logixia';
823
+ import { CloudWatchTransport } from 'logixia/cloudwatch';
802
824
 
803
825
  const logger = createLogger({
804
826
  appName: 'api',
@@ -809,8 +831,7 @@ const logger = createLogger({
809
831
  region: 'us-east-1', // or set AWS_REGION env var
810
832
  logGroupName: '/app/api',
811
833
  logStreamName: 'api-server-1', // defaults to hostname + PID
812
- // Credentials fall back to AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars,
813
- // or the EC2/ECS/Lambda metadata service — no hard-coding needed.
834
+ // Credentials: see "Credential sources" below — no hard-coding needed.
814
835
  batchSize: 100, // default: 100
815
836
  flushIntervalMs: 5000, // default: 5000
816
837
  emf: true, // emit numeric fields as CloudWatch Metrics
@@ -821,19 +842,31 @@ const logger = createLogger({
821
842
  });
822
843
  ```
823
844
 
824
- With `emf: true`, any numeric field in your log data is published as a CloudWatch Metric under the `Logixia` namespace:
845
+ With `emf: true`, any numeric field in your log data is published as a CloudWatch Metric in the `Logixia` namespace (override with `emfNamespace`), with a `level` dimension:
825
846
 
826
847
  ```typescript
827
848
  await logger.info('Request completed', { duration: 142, statusCode: 200 });
828
- // → CloudWatch Metric: Logixia/duration, Logixia/statusCode
849
+ // → CloudWatch Metrics in namespace "Logixia": duration, statusCode
829
850
  ```
830
851
 
852
+ **Credential sources**, tried in this order (no SDK needed):
853
+
854
+ 1. `accessKeyId` / `secretAccessKey` / `sessionToken` in the transport config
855
+ 2. `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN`
856
+ 3. The shared credentials file: `~/.aws/credentials`, or `AWS_SHARED_CREDENTIALS_FILE`, using the `AWS_PROFILE` profile (default `default`)
857
+ 4. ECS container credentials: `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` or `AWS_CONTAINER_CREDENTIALS_FULL_URI` (with `AWS_CONTAINER_AUTHORIZATION_TOKEN` or `_FILE`)
858
+ 5. EC2 instance role through IMDSv2 (set `AWS_EC2_METADATA_DISABLED=true` to skip)
859
+
860
+ Not supported: SSO, assume-role profiles, `credential_process`, web identity (EKS IRSA). If no source yields credentials, events stay buffered (and the buffer cap applies) rather than being dropped, and a warning is logged.
861
+
862
+ The log group and stream are created on first use; an already-existing one is fine. The IAM role needs `logs:CreateLogGroup`, `logs:CreateLogStream` and `logs:PutLogEvents` (if the group and stream already exist, only `PutLogEvents` is required, and a failed `CreateLogGroup` is tolerated). Use `endpoint` to point at LocalStack or a VPC endpoint.
863
+
831
864
  ### Google Cloud Logging
832
865
 
833
866
  Maps logixia levels to GCP `severity` values (`DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`), auto-injects `logging.googleapis.com/trace` for Cloud Trace correlation, and supports Application Default Credentials (ADC) — no service account JSON required when running on GKE / Cloud Run / App Engine.
834
867
 
835
868
  ```typescript
836
- import { GCPTransport } from 'logixia';
869
+ import { GCPTransport } from 'logixia/gcp';
837
870
 
838
871
  const logger = createLogger({
839
872
  appName: 'api',
@@ -859,7 +892,7 @@ const logger = createLogger({
859
892
  Sends logs to Azure Monitor via the **Logs Ingestion API** (Data Collection Rule). Uses OAuth2 client-credentials to obtain a bearer token automatically.
860
893
 
861
894
  ```typescript
862
- import { AzureMonitorTransport } from 'logixia';
895
+ import { AzureMonitorTransport } from 'logixia/azure';
863
896
 
864
897
  const logger = createLogger({
865
898
  appName: 'api',
@@ -1500,6 +1533,13 @@ const logger = createLogger({
1500
1533
 
1501
1534
  Both `paths` and `patterns` can be combined in the same config.
1502
1535
 
1536
+ Path rules follow these conventions:
1537
+
1538
+ - Matching is case-insensitive, so `req.headers.authorization` also redacts `Authorization`.
1539
+ - Array elements are addressed by index: `users.*.password` and `users.0.password` both match, and the older index-free form `users.password` still works. Nested arrays are walked the same way.
1540
+ - Circular references are printed as `[Circular]` instead of throwing.
1541
+ - Plain objects, class instances (ORM entities, documents) and arrays are walked. Built-ins such as `URL`, `Date`, `Buffer`, `Map`, `Set` and `Error` pass through unchanged unless a rule targets them directly.
1542
+
1503
1543
  ---
1504
1544
 
1505
1545
  ## Timer API
@@ -1775,6 +1815,8 @@ const logger = createLogger({
1775
1815
  });
1776
1816
  ```
1777
1817
 
1818
+ `maxLogsPerSecond` is always enforced after the rate decision, including with `traceConsistent: true` (a kept trace can still lose entries once the cap is hit). With `traceConsistent`, a trace's keep/drop decision is remembered in a bounded LRU (100k traces, dropped after 5 minutes idle) and survives stats resets; logs written outside any trace are sampled one by one.
1819
+
1778
1820
  ---
1779
1821
 
1780
1822
  ## Robust serialization
@@ -1819,11 +1861,16 @@ const logger = createLogger({
1819
1861
  enabled: true,
1820
1862
  timeout: 10_000, // wait up to 10 s; force-exits after
1821
1863
  signals: ['SIGTERM', 'SIGINT', 'SIGHUP'],
1864
+ exit: 'auto', // 'auto' | 'always' | 'never'
1822
1865
  },
1823
1866
  transports: {/* ... */},
1824
1867
  });
1825
1868
  ```
1826
1869
 
1870
+ **Who ends the process.** By default (`exit: 'auto'`) logixia flushes and then exits only if its handler is the only listener for that signal. If your app registers its own `SIGTERM` handler (`server.close()`, NestJS shutdown hooks, ...), logixia just flushes and leaves the exit to you, so your cleanup is never cut off. When logixia does exit it uses `128 + signal number` (143 for SIGTERM, 130 for SIGINT), so supervisors see a signal exit. Set `exit: 'always'` or `exit: 'never'` to override. Registered loggers are also flushed (not closed) on `beforeExit`, so an app that keeps logging after the event loop first drains still writes.
1871
+
1872
+ `flushOnExit` is configured by its first call; later calls with different `timeout`, `signals`, `exit` or hooks print a warning and are ignored.
1873
+
1827
1874
  You can also call `flushOnExit` directly with lifecycle hooks:
1828
1875
 
1829
1876
  ```typescript
@@ -2200,10 +2247,10 @@ import {
2200
2247
  LogixiaExceptionFilter, // global exception filter
2201
2248
  } from 'logixia';
2202
2249
 
2203
- // Cloud transports (import directly):
2204
- import { CloudWatchTransport } from 'logixia';
2205
- import { GCPTransport } from 'logixia';
2206
- import { AzureMonitorTransport } from 'logixia';
2250
+ // Cloud transports (subpath imports):
2251
+ import { CloudWatchTransport } from 'logixia/cloudwatch';
2252
+ import { GCPTransport } from 'logixia/gcp';
2253
+ import { AzureMonitorTransport } from 'logixia/azure';
2207
2254
 
2208
2255
  // Plugin API:
2209
2256
  import type { LogixiaPlugin } from 'logixia';
@@ -2533,11 +2580,17 @@ interface LoggerConfig {
2533
2580
  level?: string;
2534
2581
  batchSize?: number;
2535
2582
  flushInterval?: number; // ms
2583
+ maxQueue?: number; // cap on unwritten entries held in memory. Default: no cap
2584
+ queuePolicy?: 'drop-oldest' | 'drop-newest' | 'block'; // Default: 'drop-oldest'
2536
2585
  rotation?: {
2537
2586
  interval?: '1h' | '6h' | '12h' | '1d' | '1w' | '1m' | '1y';
2538
2587
  maxSize?: string | number;
2539
2588
  maxFiles?: number;
2540
2589
  compress?: boolean;
2590
+ shouldRotate?: (
2591
+ currentFile: string,
2592
+ stats: { size: number; created: Date; modified: Date }
2593
+ ) => boolean;
2541
2594
  };
2542
2595
  filter?: (entry: TransportLogEntry) => boolean;
2543
2596
  }