logixia 2.0.4 → 2.0.7

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 (218) hide show
  1. package/README.md +172 -2614
  2. package/dist/{async-context-B05ArHgM.mjs → async-context-COuvmwsS.mjs} +4 -6
  3. package/dist/async-context-COuvmwsS.mjs.map +1 -0
  4. package/dist/{async-context-DTQgi8f7.js → async-context-Dv0bmPC-.js} +4 -6
  5. package/dist/async-context-Dv0bmPC-.js.map +1 -0
  6. package/dist/{azure-monitor.transport-DV03Z5P4.d.ts → azure-monitor.transport-Bvf7Xegt.d.ts} +2 -2
  7. package/dist/{azure-monitor.transport-DV03Z5P4.d.ts.map → azure-monitor.transport-Bvf7Xegt.d.ts.map} +1 -1
  8. package/dist/{azure-monitor.transport-C7kYyZUW.d.mts → azure-monitor.transport-CbSHOnNX.d.mts} +2 -2
  9. package/dist/{azure-monitor.transport-C7kYyZUW.d.mts.map → azure-monitor.transport-CbSHOnNX.d.mts.map} +1 -1
  10. package/dist/{azure-monitor.transport-BPbgjATu.mjs → azure-monitor.transport-Coz5Gesu.mjs} +5 -5
  11. package/dist/azure-monitor.transport-Coz5Gesu.mjs.map +1 -0
  12. package/dist/{azure-monitor.transport-CwbOLZHB.js → azure-monitor.transport-D6ryi8rA.js} +5 -5
  13. package/dist/azure-monitor.transport-D6ryi8rA.js.map +1 -0
  14. package/dist/azure.d.mts +1 -1
  15. package/dist/azure.d.ts +1 -1
  16. package/dist/azure.js +1 -1
  17. package/dist/azure.mjs +1 -1
  18. package/dist/{batch-buffer-DT4gdXmf.js → batch-buffer-CFzKnuNZ.js} +3 -3
  19. package/dist/{batch-buffer-DT4gdXmf.js.map → batch-buffer-CFzKnuNZ.js.map} +1 -1
  20. package/dist/{batch-buffer-0fgLmIPn.mjs → batch-buffer-CQUWDMYq.mjs} +3 -3
  21. package/dist/{batch-buffer-0fgLmIPn.mjs.map → batch-buffer-CQUWDMYq.mjs.map} +1 -1
  22. package/dist/browser.d.mts +5 -5
  23. package/dist/browser.d.mts.map +1 -1
  24. package/dist/browser.d.ts +5 -5
  25. package/dist/browser.d.ts.map +1 -1
  26. package/dist/browser.js +72 -13
  27. package/dist/browser.js.map +1 -1
  28. package/dist/browser.mjs +72 -13
  29. package/dist/browser.mjs.map +1 -1
  30. package/dist/{builder-D70z6kjj.mjs → builder-C_TgxEOW.mjs} +106 -153
  31. package/dist/builder-C_TgxEOW.mjs.map +1 -0
  32. package/dist/{builder-M7NoaugM.js → builder-CzmM_4Ub.js} +110 -180
  33. package/dist/builder-CzmM_4Ub.js.map +1 -0
  34. package/dist/cli/index.js +157 -66
  35. package/dist/cloudwatch.d.mts +1 -1
  36. package/dist/cloudwatch.d.ts +1 -1
  37. package/dist/cloudwatch.js +1 -1
  38. package/dist/cloudwatch.mjs +1 -1
  39. package/dist/{cloudwatch.transport-Bf7L4I59.d.ts → cloudwatch.transport-CQyT6U91.d.ts} +2 -2
  40. package/dist/{cloudwatch.transport-Bf7L4I59.d.ts.map → cloudwatch.transport-CQyT6U91.d.ts.map} +1 -1
  41. package/dist/{cloudwatch.transport-Rj4yTpRn.d.mts → cloudwatch.transport-CjVrI6S4.d.mts} +2 -2
  42. package/dist/{cloudwatch.transport-Rj4yTpRn.d.mts.map → cloudwatch.transport-CjVrI6S4.d.mts.map} +1 -1
  43. package/dist/{cloudwatch.transport-BTvYfLs9.mjs → cloudwatch.transport-Cr1aeTGj.mjs} +6 -6
  44. package/dist/cloudwatch.transport-Cr1aeTGj.mjs.map +1 -0
  45. package/dist/{cloudwatch.transport-B2wKQFF7.js → cloudwatch.transport-D4G5xYfG.js} +6 -6
  46. package/dist/cloudwatch.transport-D4G5xYfG.js.map +1 -0
  47. package/dist/correlation.d.mts +10 -55
  48. package/dist/correlation.d.mts.map +1 -1
  49. package/dist/correlation.d.ts +10 -55
  50. package/dist/correlation.d.ts.map +1 -1
  51. package/dist/correlation.js +15 -13
  52. package/dist/correlation.js.map +1 -1
  53. package/dist/correlation.mjs +15 -13
  54. package/dist/correlation.mjs.map +1 -1
  55. package/dist/{entry-fields-RLd1jCoR.js → entry-fields-CVwoQplO.js} +8 -3
  56. package/dist/entry-fields-CVwoQplO.js.map +1 -0
  57. package/dist/{entry-fields-CGuvT2R0.mjs → entry-fields-DNTKQxoU.mjs} +8 -3
  58. package/dist/entry-fields-DNTKQxoU.mjs.map +1 -0
  59. package/dist/gcp.d.mts +1 -1
  60. package/dist/gcp.d.ts +1 -1
  61. package/dist/gcp.js +1 -1
  62. package/dist/gcp.mjs +1 -1
  63. package/dist/{gcp.transport-CFQfdAOK.d.ts → gcp.transport-BCIvdFV-.d.ts} +4 -4
  64. package/dist/{gcp.transport-CFQfdAOK.d.ts.map → gcp.transport-BCIvdFV-.d.ts.map} +1 -1
  65. package/dist/{gcp.transport-KZe9hCAR.js → gcp.transport-CVuRpchl.js} +20 -16
  66. package/dist/gcp.transport-CVuRpchl.js.map +1 -0
  67. package/dist/{gcp.transport-C5D72b1g.d.mts → gcp.transport-D9SdLPwP.d.mts} +4 -4
  68. package/dist/{gcp.transport-C5D72b1g.d.mts.map → gcp.transport-D9SdLPwP.d.mts.map} +1 -1
  69. package/dist/{gcp.transport-CGKopAhQ.mjs → gcp.transport-LLK2bw2-.mjs} +20 -16
  70. package/dist/gcp.transport-LLK2bw2-.mjs.map +1 -0
  71. package/dist/http-shapes-BnBkJcid.d.mts +32 -0
  72. package/dist/http-shapes-BnBkJcid.d.mts.map +1 -0
  73. package/dist/http-shapes-BnBkJcid.d.ts +32 -0
  74. package/dist/http-shapes-BnBkJcid.d.ts.map +1 -0
  75. package/dist/{index-xqaJtAZn.d.mts → index-BAkPHp5D.d.mts} +150 -8
  76. package/dist/index-BAkPHp5D.d.mts.map +1 -0
  77. package/dist/{index-DwozbmB4.d.ts → index-e7LowmAu.d.ts} +150 -8
  78. package/dist/index-e7LowmAu.d.ts.map +1 -0
  79. package/dist/index.d.mts +21 -65
  80. package/dist/index.d.mts.map +1 -1
  81. package/dist/index.d.ts +21 -65
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +26 -26
  84. package/dist/index.js.map +1 -1
  85. package/dist/index.mjs +21 -21
  86. package/dist/index.mjs.map +1 -1
  87. package/dist/{internal-log-uCSd1PMc.mjs → internal-log-Cy5nF1ZL.mjs} +2 -81
  88. package/dist/internal-log-Cy5nF1ZL.mjs.map +1 -0
  89. package/dist/{internal-log-b0Vp4qrB.js → internal-log-DwqTjhpb.js} +1 -104
  90. package/dist/internal-log-DwqTjhpb.js.map +1 -0
  91. package/dist/{logitron-logger-D2B75Oc7.d.ts → logitron-logger-Qh3y9-WH.d.ts} +13 -100
  92. package/dist/logitron-logger-Qh3y9-WH.d.ts.map +1 -0
  93. package/dist/{logitron-logger-oEd6wNhf.d.mts → logitron-logger-sYuk8fOb.d.mts} +13 -100
  94. package/dist/logitron-logger-sYuk8fOb.d.mts.map +1 -0
  95. package/dist/middleware.d.mts +4 -17
  96. package/dist/middleware.d.mts.map +1 -1
  97. package/dist/middleware.d.ts +4 -17
  98. package/dist/middleware.d.ts.map +1 -1
  99. package/dist/middleware.js +9 -39
  100. package/dist/middleware.js.map +1 -1
  101. package/dist/middleware.mjs +7 -37
  102. package/dist/middleware.mjs.map +1 -1
  103. package/dist/nest.d.mts +24 -8
  104. package/dist/nest.d.mts.map +1 -1
  105. package/dist/nest.d.ts +24 -8
  106. package/dist/nest.d.ts.map +1 -1
  107. package/dist/nest.js +140 -27
  108. package/dist/nest.js.map +1 -1
  109. package/dist/nest.mjs +140 -27
  110. package/dist/nest.mjs.map +1 -1
  111. package/dist/{transport.manager-DkcEOlqV.js → otel-ChnVYRLA.js} +214 -23
  112. package/dist/otel-ChnVYRLA.js.map +1 -0
  113. package/dist/{transport.manager-eZ_EeC00.mjs → otel-DOuwGPCd.mjs} +173 -24
  114. package/dist/otel-DOuwGPCd.mjs.map +1 -0
  115. package/dist/{request-trace-C_fvIDv4.mjs → request-trace-BgNykH9M.mjs} +1 -5
  116. package/dist/{request-trace-C_fvIDv4.mjs.map → request-trace-BgNykH9M.mjs.map} +1 -1
  117. package/dist/{request-trace-wTJdKp6-.js → request-trace-ByujsUZk.js} +1 -5
  118. package/dist/{request-trace-wTJdKp6-.js.map → request-trace-ByujsUZk.js.map} +1 -1
  119. package/dist/{safe-stringify-BMRl3EX3.mjs → safe-stringify--7gbe95n.mjs} +37 -12
  120. package/dist/safe-stringify--7gbe95n.mjs.map +1 -0
  121. package/dist/{safe-stringify-DLz1Kz3o.js → safe-stringify-CN7icp8S.js} +37 -12
  122. package/dist/safe-stringify-CN7icp8S.js.map +1 -0
  123. package/dist/{search-DUfWuzFP.js → search-CRjhHxe9.js} +269 -25
  124. package/dist/search-CRjhHxe9.js.map +1 -0
  125. package/dist/{search-CazwyX5Z.d.ts → search-D-8HJADE.d.mts} +5 -2
  126. package/dist/search-D-8HJADE.d.mts.map +1 -0
  127. package/dist/{search-CWMVYC-R.mjs → search-DAXKE-P9.mjs} +269 -25
  128. package/dist/search-DAXKE-P9.mjs.map +1 -0
  129. package/dist/{search-BH33XhuU.d.mts → search-DPwTKPve.d.ts} +5 -2
  130. package/dist/search-DPwTKPve.d.ts.map +1 -0
  131. package/dist/search.d.mts +1 -1
  132. package/dist/search.d.ts +1 -1
  133. package/dist/search.js +1 -1
  134. package/dist/search.mjs +1 -1
  135. package/dist/{secret-config-CBZBs0p1.js → secret-config-BvFl2dC8.js} +7 -7
  136. package/dist/secret-config-BvFl2dC8.js.map +1 -0
  137. package/dist/{secret-config-BegMLkYl.mjs → secret-config-ByGq7kJd.mjs} +5 -5
  138. package/dist/secret-config-ByGq7kJd.mjs.map +1 -0
  139. package/dist/sensitive-names-CHMowujD.js +276 -0
  140. package/dist/sensitive-names-CHMowujD.js.map +1 -0
  141. package/dist/sensitive-names-o__1PUUR.mjs +217 -0
  142. package/dist/sensitive-names-o__1PUUR.mjs.map +1 -0
  143. package/dist/{slack.transport-DxHOXlLu.d.mts → slack.transport-BDyENuR0.d.mts} +2 -2
  144. package/dist/{slack.transport-DxHOXlLu.d.mts.map → slack.transport-BDyENuR0.d.mts.map} +1 -1
  145. package/dist/{slack.transport-DrirgDNy.d.ts → slack.transport-C6E0l4kw.d.ts} +2 -2
  146. package/dist/{slack.transport-DrirgDNy.d.ts.map → slack.transport-C6E0l4kw.d.ts.map} +1 -1
  147. package/dist/{slack.transport-Ce96JBDk.mjs → slack.transport-CSj1j0_X.mjs} +66 -15
  148. package/dist/slack.transport-CSj1j0_X.mjs.map +1 -0
  149. package/dist/{slack.transport-Dlx3xvb7.js → slack.transport-zLQ9MGxS.js} +67 -16
  150. package/dist/slack.transport-zLQ9MGxS.js.map +1 -0
  151. package/dist/testing.d.mts +11 -4
  152. package/dist/testing.d.mts.map +1 -1
  153. package/dist/testing.d.ts +11 -4
  154. package/dist/testing.d.ts.map +1 -1
  155. package/dist/testing.js +38 -3
  156. package/dist/testing.js.map +1 -1
  157. package/dist/testing.mjs +38 -3
  158. package/dist/testing.mjs.map +1 -1
  159. package/dist/{transport.types-BJVL1QQl.d.ts → transport.types-CzJq4IrF.d.mts} +14 -3
  160. package/dist/transport.types-CzJq4IrF.d.mts.map +1 -0
  161. package/dist/{transport.types-BJVL1QQl.d.mts → transport.types-CzJq4IrF.d.ts} +14 -3
  162. package/dist/transport.types-CzJq4IrF.d.ts.map +1 -0
  163. package/dist/transports.d.mts +25 -13
  164. package/dist/transports.d.mts.map +1 -1
  165. package/dist/transports.d.ts +25 -13
  166. package/dist/transports.d.ts.map +1 -1
  167. package/dist/transports.js +15 -15
  168. package/dist/transports.mjs +6 -6
  169. package/dist/worker-entry.js +130 -25
  170. package/dist/worker.d.mts +1 -1
  171. package/dist/worker.d.ts +1 -1
  172. package/dist/worker.js +1 -1
  173. package/dist/worker.mjs +1 -1
  174. package/dist/{worker.transport-BuPwBi3d.d.ts → worker.transport-B9mCQSM1.d.ts} +7 -2
  175. package/dist/worker.transport-B9mCQSM1.d.ts.map +1 -0
  176. package/dist/{worker.transport-hJay1wxA.d.mts → worker.transport-Bl8lFRck.d.mts} +7 -2
  177. package/dist/worker.transport-Bl8lFRck.d.mts.map +1 -0
  178. package/dist/{worker.transport-DLVA4y2e.mjs → worker.transport-D78xhNhB.mjs} +13 -10
  179. package/dist/worker.transport-D78xhNhB.mjs.map +1 -0
  180. package/dist/{worker.transport-C6GNl_r2.js → worker.transport-DQDv1nAJ.js} +13 -10
  181. package/dist/worker.transport-DQDv1nAJ.js.map +1 -0
  182. package/package.json +33 -65
  183. package/dist/async-context-B05ArHgM.mjs.map +0 -1
  184. package/dist/async-context-DTQgi8f7.js.map +0 -1
  185. package/dist/azure-monitor.transport-BPbgjATu.mjs.map +0 -1
  186. package/dist/azure-monitor.transport-CwbOLZHB.js.map +0 -1
  187. package/dist/builder-D70z6kjj.mjs.map +0 -1
  188. package/dist/builder-M7NoaugM.js.map +0 -1
  189. package/dist/cloudwatch.transport-B2wKQFF7.js.map +0 -1
  190. package/dist/cloudwatch.transport-BTvYfLs9.mjs.map +0 -1
  191. package/dist/entry-fields-CGuvT2R0.mjs.map +0 -1
  192. package/dist/entry-fields-RLd1jCoR.js.map +0 -1
  193. package/dist/gcp.transport-CGKopAhQ.mjs.map +0 -1
  194. package/dist/gcp.transport-KZe9hCAR.js.map +0 -1
  195. package/dist/index-DwozbmB4.d.ts.map +0 -1
  196. package/dist/index-xqaJtAZn.d.mts.map +0 -1
  197. package/dist/internal-log-b0Vp4qrB.js.map +0 -1
  198. package/dist/internal-log-uCSd1PMc.mjs.map +0 -1
  199. package/dist/logitron-logger-D2B75Oc7.d.ts.map +0 -1
  200. package/dist/logitron-logger-oEd6wNhf.d.mts.map +0 -1
  201. package/dist/safe-stringify-BMRl3EX3.mjs.map +0 -1
  202. package/dist/safe-stringify-DLz1Kz3o.js.map +0 -1
  203. package/dist/search-BH33XhuU.d.mts.map +0 -1
  204. package/dist/search-CWMVYC-R.mjs.map +0 -1
  205. package/dist/search-CazwyX5Z.d.ts.map +0 -1
  206. package/dist/search-DUfWuzFP.js.map +0 -1
  207. package/dist/secret-config-BegMLkYl.mjs.map +0 -1
  208. package/dist/secret-config-CBZBs0p1.js.map +0 -1
  209. package/dist/slack.transport-Ce96JBDk.mjs.map +0 -1
  210. package/dist/slack.transport-Dlx3xvb7.js.map +0 -1
  211. package/dist/transport.manager-DkcEOlqV.js.map +0 -1
  212. package/dist/transport.manager-eZ_EeC00.mjs.map +0 -1
  213. package/dist/transport.types-BJVL1QQl.d.mts.map +0 -1
  214. package/dist/transport.types-BJVL1QQl.d.ts.map +0 -1
  215. package/dist/worker.transport-BuPwBi3d.d.ts.map +0 -1
  216. package/dist/worker.transport-C6GNl_r2.js.map +0 -1
  217. package/dist/worker.transport-DLVA4y2e.mjs.map +0 -1
  218. package/dist/worker.transport-hJay1wxA.d.mts.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["serializeError","stripControlChars","safeToString","LogLevel","AsyncLocalStorage","getCurrentTraceId","createLoggerFromCore","LogixiaLogger","DEFAULT_CONFIG"],"sources":["../src/formatters/json.formatter.ts","../src/formatters/text.formatter.ts","../src/utils/runtime-control.ts","../src/utils/typed-logger.ts","../src/wide-events.ts","../src/metrics.ts","../src/index.ts"],"sourcesContent":["/**\n * JSON formatter for Logixia\n */\n\nimport type { ILogFormatter, LogEntry } from '../types';\nimport { serializeError } from '../utils/error.utils';\n\n/**\n * Build a JSON.stringify replacer that replaces circular references with the\n * string '[Circular]' instead of throwing. A fresh replacer must be created per\n * stringify call because it holds per-serialization state (the seen set).\n */\nfunction createCircularReplacer(): (key: string, value: unknown) => unknown {\n const seen = new WeakSet<object>();\n return function (this: unknown, _key: string, value: unknown): unknown {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n }\n return value;\n };\n}\n\nexport class JsonFormatter implements ILogFormatter {\n private includeTimestamp: boolean;\n private includeLevel: boolean;\n private includeAppName: boolean;\n private includeTraceId: boolean;\n private includeContext: boolean;\n private prettyPrint: boolean;\n\n constructor(\n options: {\n includeTimestamp?: boolean;\n includeLevel?: boolean;\n includeAppName?: boolean;\n includeTraceId?: boolean;\n includeContext?: boolean;\n prettyPrint?: boolean;\n } = {}\n ) {\n this.includeTimestamp = options.includeTimestamp ?? true;\n this.includeLevel = options.includeLevel ?? true;\n this.includeAppName = options.includeAppName ?? true;\n this.includeTraceId = options.includeTraceId ?? true;\n this.includeContext = options.includeContext ?? true;\n this.prettyPrint = options.prettyPrint ?? false;\n }\n\n format(entry: LogEntry): string {\n const formatted: Record<string, unknown> = {};\n\n // Add timestamp\n if (this.includeTimestamp) {\n formatted.timestamp = entry.timestamp;\n }\n\n // Add log level\n if (this.includeLevel) {\n formatted.level = entry.level.toLowerCase();\n formatted.levelValue = entry.level;\n }\n\n // Add app name\n if (this.includeAppName) {\n formatted.appName = entry.appName;\n }\n\n // Add trace ID\n if (this.includeTraceId && entry.traceId) {\n formatted.traceId = entry.traceId;\n }\n\n // Add context\n if (this.includeContext && entry.context) {\n formatted.context = entry.context;\n }\n\n // Add message\n formatted.message = entry.message;\n\n // Add payload\n if (entry.payload && Object.keys(entry.payload).length > 0) {\n formatted.payload = this.serializePayload(entry.payload);\n }\n\n // Add error if present\n if (entry.error) {\n formatted.error = serializeError(entry.error);\n }\n\n // Add metadata\n formatted.meta = {\n pid: process.pid,\n hostname: process.env.HOSTNAME || 'unknown',\n version: process.version,\n };\n\n // Use a circular-safe replacer: a payload containing a cycle (e.g. an Express\n // req/res, a DB connection, a Mongoose doc) would otherwise make JSON.stringify\n // throw and crash the entire log/transport path.\n const replacer = createCircularReplacer();\n return this.prettyPrint\n ? JSON.stringify(formatted, replacer, 2)\n : JSON.stringify(formatted, replacer);\n }\n\n private serializePayload(payload: Record<string, unknown>): Record<string, unknown> {\n const serialized: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(payload)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n try {\n if (value instanceof Error) {\n serialized[key] = serializeError(value);\n } else if (value instanceof Date) {\n serialized[key] = value.toISOString();\n } else if (typeof value === 'function') {\n serialized[key] = '[Function]';\n } else if (typeof value === 'symbol') {\n serialized[key] = value.toString();\n } else if (value === undefined) {\n serialized[key] = null;\n } else {\n serialized[key] = value;\n }\n } catch {\n serialized[key] = '[Unserializable]';\n }\n }\n\n return serialized;\n }\n}\n","/**\n * Text formatter for Logixia\n */\n\nimport type { ILogFormatter, LogEntry } from '../types';\nimport { LogLevel } from '../types';\nimport { safeToString } from '../utils/coerce.utils';\nimport { stripControlChars } from '../utils/sanitize.utils';\n\n// Coerce non-strings (objects passed via setContext, Errors as messages, etc.)\n// before .replace() to avoid TypeError on the hot path.\nconst stripControls = (value: unknown): string => stripControlChars(safeToString(value));\n\nexport class TextFormatter implements ILogFormatter {\n private colorize: boolean;\n private includeTimestamp: boolean;\n private includeAppName: boolean;\n private includeTraceId: boolean;\n private includeContext: boolean;\n private timestampFormat: 'iso' | 'locale' | 'short';\n private colors: Record<string, string>;\n\n constructor(\n options: {\n colorize?: boolean;\n includeTimestamp?: boolean;\n includeAppName?: boolean;\n includeTraceId?: boolean;\n includeContext?: boolean;\n timestampFormat?: 'iso' | 'locale' | 'short';\n colors?: Record<string, string>;\n } = {}\n ) {\n this.colorize = options.colorize ?? true;\n this.includeTimestamp = options.includeTimestamp ?? true;\n this.includeAppName = options.includeAppName ?? true;\n this.includeTraceId = options.includeTraceId ?? true;\n this.includeContext = options.includeContext ?? true;\n this.timestampFormat = options.timestampFormat ?? 'locale';\n this.colors = {\n error: '\\x1b[31m', // Red\n warn: '\\x1b[33m', // Yellow\n info: '\\x1b[32m', // Green\n debug: '\\x1b[34m', // Blue\n trace: '\\x1b[35m', // Magenta\n verbose: '\\x1b[36m', // Cyan\n reset: '\\x1b[0m', // Reset\n bold: '\\x1b[1m', // Bold\n dim: '\\x1b[2m', // Dim\n ...options.colors,\n };\n }\n\n format(entry: LogEntry): string {\n const parts: string[] = [];\n\n // Add timestamp\n if (this.includeTimestamp) {\n const timestamp = this.formatTimestamp(entry.timestamp);\n parts.push(this.colorize ? `${this.colors.dim}${timestamp}${this.colors.reset}` : timestamp);\n }\n\n // Add log level\n const levelName = entry.level.toLowerCase();\n const levelColor = this.colors[levelName] || this.colors.reset;\n const formattedLevel = this.colorize\n ? `${levelColor}${this.colors.bold}${levelName.toUpperCase().padEnd(5)}${this.colors.reset}`\n : levelName.toUpperCase().padEnd(5);\n parts.push(`[${formattedLevel}]`);\n\n // Add app name\n if (this.includeAppName) {\n const safeAppName = stripControls(entry.appName);\n const appName = this.colorize\n ? `${this.colors.bold}${safeAppName}${this.colors.reset}`\n : safeAppName;\n parts.push(`[${appName}]`);\n }\n\n // Add trace ID\n if (this.includeTraceId && entry.traceId) {\n const safeTraceId = stripControls(entry.traceId);\n const traceId = this.colorize\n ? `${this.colors.dim}${safeTraceId}${this.colors.reset}`\n : safeTraceId;\n parts.push(`[${traceId}]`);\n }\n\n // Add context\n if (this.includeContext && entry.context) {\n const safeContext = stripControls(entry.context);\n const context = this.colorize\n ? `${this.colors.cyan}${safeContext}${this.colors.reset}`\n : safeContext;\n parts.push(`[${context}]`);\n }\n\n // Add message\n const safeMessage = stripControls(entry.message);\n const message =\n this.colorize && entry.level === LogLevel.ERROR\n ? `${this.colors.error}${safeMessage}${this.colors.reset}`\n : safeMessage;\n parts.push(message);\n\n // Add payload\n if (entry.payload && Object.keys(entry.payload).length > 0) {\n const payload = this.formatPayload(entry.payload);\n if (payload) {\n parts.push(this.colorize ? `${this.colors.dim}${payload}${this.colors.reset}` : payload);\n }\n }\n\n return parts.join(' ');\n }\n\n private formatTimestamp(timestamp: string): string {\n const date = new Date(timestamp);\n\n switch (this.timestampFormat) {\n case 'iso':\n return date.toISOString();\n case 'short':\n return date.toLocaleTimeString();\n case 'locale':\n default:\n return date.toLocaleString();\n }\n }\n\n private formatPayload(payload: Record<string, unknown>): string {\n try {\n // Handle simple objects\n if (Object.keys(payload).length === 1) {\n const entry = Object.entries(payload)[0];\n if (entry) {\n const [key, value] = entry;\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return `${key}=${value}`;\n }\n }\n }\n\n // Handle multiple properties or complex objects\n const formatted = Object.entries(payload)\n .map(([key, value]) => {\n if (value === null || value === undefined) {\n return `${key}=${value}`;\n }\n if (typeof value === 'string') {\n return `${key}=\"${value}\"`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return `${key}=${value}`;\n }\n if (value instanceof Date) {\n return `${key}=${value.toISOString()}`;\n }\n if (typeof value === 'object') {\n // safeToString is circular-safe (raw JSON.stringify throws on a cycle\n // — e.g. an Express req/res — which would crash the log call) and the\n // control-char strip keeps the CWE-117 guarantee for object values.\n return `${key}=${stripControls(safeToString(value))}`;\n }\n return `${key}=${String(value)}`;\n })\n .join(' ');\n\n return formatted;\n } catch {\n // Last-resort fallback must also be circular-safe — the previous\n // JSON.stringify(payload) here threw again on the same cyclic payload.\n return stripControls(safeToString(payload));\n }\n }\n\n /**\n * Create a formatter with preset configurations\n */\n static createSimple(): TextFormatter {\n return new TextFormatter({\n colorize: true,\n includeTimestamp: true,\n includeAppName: false,\n includeTraceId: false,\n includeContext: true,\n timestampFormat: 'short',\n });\n }\n\n static createDetailed(): TextFormatter {\n return new TextFormatter({\n colorize: true,\n includeTimestamp: true,\n includeAppName: true,\n includeTraceId: true,\n includeContext: true,\n timestampFormat: 'locale',\n });\n }\n\n static createMinimal(): TextFormatter {\n return new TextFormatter({\n colorize: false,\n includeTimestamp: false,\n includeAppName: false,\n includeTraceId: false,\n includeContext: false,\n });\n }\n}\n","/**\n * logixia — Dynamic runtime log-level reconfiguration.\n *\n * Change log levels in a running process WITHOUT a restart — the single\n * most-requested logging feature across the Winston and Pino issue trackers\n * (winston#1107, pino#206/#677, nestjs-pino#371). The ecosystem even built a\n * standalone module for it (pino-arborsculpture); logixia ships it first-class.\n *\n * Two trigger surfaces:\n * - {@link registerLevelSignal} — flip levels via an OS signal (default SIGUSR2),\n * cycling through a level list. Zero HTTP surface, safe for any deployment.\n * - {@link createLevelControlHandler} — a tiny HTTP handler so an ops dashboard\n * can GET the current level and POST a new global / per-namespace level.\n *\n * @example Signal-based (cycle levels on each `kill -USR2 <pid>`)\n * ```ts\n * import { registerLevelSignal } from 'logixia';\n * const dispose = registerLevelSignal(logger);\n * // later: process.kill(process.pid, 'SIGUSR2') → info → debug → trace → info …\n * ```\n *\n * @example HTTP admin endpoint\n * ```ts\n * import { createLevelControlHandler } from 'logixia';\n * const handler = createLevelControlHandler(logger);\n * app.all('/admin/log-level', handler); // GET reads, POST { level, namespaceLevels } sets\n * ```\n */\n\nimport type { LogLevelString, NamespaceLevels } from '../types';\nimport { internalLog, internalWarn } from './internal-log';\n\n/** Minimal logger surface the runtime controls need. */\nexport interface ReconfigurableLogger {\n getLevel(): LogLevelString;\n setLevel(level: LogLevelString): void;\n setNamespaceLevels?(levels: NamespaceLevels): void;\n getNamespaceLevels?(): NamespaceLevels;\n}\n\nconst DEFAULT_CYCLE: readonly LogLevelString[] = [\n 'error',\n 'warn',\n 'info',\n 'debug',\n 'trace',\n 'verbose',\n] as unknown as readonly LogLevelString[];\n\nexport interface LevelSignalOptions {\n /** Signal to listen on. Default: 'SIGUSR2' (SIGUSR1 is used by the Node debugger). */\n signal?: NodeJS.Signals;\n /** Ordered levels to cycle through on each signal. Default: error→…→verbose. */\n cycle?: LogLevelString[];\n}\n\n/**\n * Register an OS-signal handler that cycles the logger's global level on each\n * signal. Returns a dispose function that removes the listener.\n *\n * Cycling (rather than jumping straight to a fixed level) means a single,\n * memorizable command (`kill -USR2 <pid>`) is enough to ratchet verbosity up\n * while chasing a bug and back down again — no value to remember.\n */\nexport function registerLevelSignal(\n logger: ReconfigurableLogger,\n options: LevelSignalOptions = {}\n): () => void {\n const signal = options.signal ?? 'SIGUSR2';\n const cycle = options.cycle && options.cycle.length > 0 ? options.cycle : [...DEFAULT_CYCLE];\n\n const handler = (): void => {\n const current = logger.getLevel();\n const idx = cycle.indexOf(current);\n const next = cycle[(idx + 1) % cycle.length]!;\n logger.setLevel(next);\n internalLog(`runtime level changed via ${signal}: ${current} → ${next}`);\n };\n\n process.on(signal, handler);\n return () => {\n process.removeListener(signal, handler);\n };\n}\n\n// ── HTTP admin handler ────────────────────────────────────────────────────────\n\ninterface MinimalReq {\n method?: string | undefined;\n headers?: Record<string, string | string[] | undefined> | undefined;\n on?: (event: string, cb: (chunk?: unknown) => void) => void;\n}\ninterface MinimalRes {\n statusCode?: number;\n setHeader?: (k: string, v: string) => void;\n end: (body?: string) => void;\n}\n\n/** Maximum accepted request body size for the level control handler. */\nconst MAX_BODY_BYTES = 16 * 1024;\n\nfunction isJsonContentType(req: MinimalReq): boolean {\n const raw = req.headers?.['content-type'];\n const value = Array.isArray(raw) ? raw[0] : raw;\n if (typeof value !== 'string') return false;\n return value.split(';')[0]!.trim().toLowerCase() === 'application/json';\n}\n\nconst VALID_LEVELS = new Set<string>([\n 'error',\n 'warn',\n 'info',\n 'debug',\n 'trace',\n 'verbose',\n 'fatal',\n]);\n\n/**\n * Create an HTTP handler (Node `http`/Express-compatible) that reads and sets\n * the logger's level at runtime.\n *\n * - `GET` → `{ level, namespaceLevels }`\n * - `POST` → body `{ level?, namespaceLevels? }` applies them, returns the new state\n *\n * Custom levels are accepted too: any level the logger already knows passes\n * through. Unknown levels are rejected with 400 so a typo can't silently mute\n * logging.\n *\n * **SECURITY: this handler has NO authentication or authorization.** Anyone who\n * can reach it can silence logging or turn on verbose output. Always mount it\n * behind your own auth (and on an internal-only route/port), never on a public\n * listener.\n *\n * Mutating requests must send `Content-Type: application/json` (otherwise 415,\n * which also keeps cross-site form posts out) and a body of at most 16 KB\n * (otherwise 413).\n */\nexport function createLevelControlHandler(\n logger: ReconfigurableLogger,\n options: { allowedLevels?: string[] } = {}\n): (req: MinimalReq, res: MinimalRes) => void {\n const allowed =\n options.allowedLevels && options.allowedLevels.length > 0\n ? new Set(options.allowedLevels.map((l) => l.toLowerCase()))\n : VALID_LEVELS;\n\n const snapshot = (): { level: LogLevelString; namespaceLevels: NamespaceLevels } => ({\n level: logger.getLevel(),\n namespaceLevels: logger.getNamespaceLevels?.() ?? {},\n });\n\n const send = (res: MinimalRes, status: number, body: unknown): void => {\n res.statusCode = status;\n res.setHeader?.('Content-Type', 'application/json');\n res.end(JSON.stringify(body));\n };\n\n const applyBody = (res: MinimalRes, raw: string): void => {\n let parsed: { level?: unknown; namespaceLevels?: unknown };\n try {\n parsed = raw ? (JSON.parse(raw) as typeof parsed) : {};\n } catch {\n send(res, 400, { error: 'invalid JSON body' });\n return;\n }\n\n if (parsed.level !== undefined) {\n const lvl = String(parsed.level).toLowerCase();\n if (!allowed.has(lvl)) {\n send(res, 400, { error: `unknown level \"${parsed.level}\"`, allowed: [...allowed] });\n return;\n }\n logger.setLevel(lvl as LogLevelString);\n }\n\n if (parsed.namespaceLevels !== undefined) {\n if (\n typeof parsed.namespaceLevels !== 'object' ||\n parsed.namespaceLevels === null ||\n Array.isArray(parsed.namespaceLevels)\n ) {\n send(res, 400, { error: 'namespaceLevels must be an object' });\n return;\n }\n const nl = parsed.namespaceLevels as Record<string, unknown>;\n for (const [pat, lvl] of Object.entries(nl)) {\n if (!allowed.has(String(lvl).toLowerCase())) {\n send(res, 400, { error: `unknown level \"${String(lvl)}\" for namespace \"${pat}\"` });\n return;\n }\n }\n if (logger.setNamespaceLevels) {\n const coerced: NamespaceLevels = Object.fromEntries(\n Object.entries(nl).map(([pat, lvl]) => [pat, String(lvl).toLowerCase() as LogLevelString])\n );\n logger.setNamespaceLevels(coerced);\n } else {\n internalWarn('level control: logger does not support setNamespaceLevels — ignored');\n }\n }\n\n send(res, 200, snapshot());\n };\n\n return function levelControlHandler(req: MinimalReq, res: MinimalRes): void {\n const method = (req.method ?? 'GET').toUpperCase();\n\n if (method === 'GET') {\n send(res, 200, snapshot());\n return;\n }\n\n if (method === 'POST' || method === 'PUT' || method === 'PATCH') {\n if (!isJsonContentType(req)) {\n send(res, 415, { error: 'Content-Type must be application/json' });\n return;\n }\n const declared = Number(req.headers?.['content-length']);\n if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {\n send(res, 413, { error: 'request body too large' });\n return;\n }\n\n // Express already-parsed body (req.body) vs raw stream.\n const maybeBody = (req as unknown as { body?: unknown }).body;\n if (maybeBody !== undefined) {\n let text: string;\n if (typeof maybeBody === 'string') text = maybeBody;\n else if (Buffer.isBuffer(maybeBody)) text = maybeBody.toString('utf8');\n else text = JSON.stringify(maybeBody);\n if (Buffer.byteLength(text) > MAX_BODY_BYTES) {\n send(res, 413, { error: 'request body too large' });\n return;\n }\n applyBody(res, text);\n return;\n }\n if (typeof req.on === 'function') {\n let raw = '';\n let size = 0;\n let rejected = false;\n req.on('data', (chunk?: unknown) => {\n if (rejected) return;\n const piece = Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk ?? '');\n size += Buffer.byteLength(piece);\n if (size > MAX_BODY_BYTES) {\n rejected = true;\n raw = '';\n send(res, 413, { error: 'request body too large' });\n return;\n }\n raw += piece;\n });\n req.on('end', () => {\n if (!rejected) applyBody(res, raw);\n });\n return;\n }\n applyBody(res, '');\n return;\n }\n\n send(res, 405, { error: `method ${method} not allowed` });\n };\n}\n","/**\n * logixia — TypeScript typed log fields\n *\n * Solves the type-safety gap: standard `Record<string, unknown>` metadata gives\n * zero IDE autocomplete and lets typos slip silently into production logs.\n *\n * Two complementary utilities:\n *\n * 1. `createTypedLogger<TFields>()` — wraps any IBaseLogger so that the second\n * argument of every log method is constrained to `TFields` (a typed object).\n * Compile-time safety, zero runtime overhead.\n *\n * 2. `defineLogSchema<TFields>(schema)` — declares expected fields with optional\n * validators. In development (NODE_ENV !== 'production') every log call is\n * validated against the schema and a warning is emitted for missing required\n * fields or type mismatches.\n *\n * @example\n * ```ts\n * import { createTypedLogger, defineLogSchema } from 'logixia';\n *\n * interface OrderFields {\n * orderId: string;\n * userId: string;\n * amount?: number;\n * currency?: string;\n * }\n *\n * const schema = defineLogSchema<OrderFields>({\n * orderId: { type: 'string', required: true },\n * userId: { type: 'string', required: true },\n * amount: { type: 'number' },\n * currency: { type: 'string' },\n * });\n *\n * const orderLogger = createTypedLogger<OrderFields>(baseLogger, schema);\n * await orderLogger.info('Order created', { orderId: 'ord_123', userId: 'usr_456', amount: 99.99 });\n * // ^^^^ fully typed autocomplete ^^^^\n * ```\n */\n\nimport { internalWarn } from './internal-log';\n\n// ── Schema types ─────────────────────────────────────────────────────────────\n\nexport type LogFieldType = 'string' | 'number' | 'boolean' | 'object' | 'array';\n\nexport interface LogFieldDef {\n type: LogFieldType;\n /** Emit a warning when this field is missing from the log call. Default: false */\n required?: boolean;\n /** Custom validator — return a string to emit it as a warning message. */\n validate?: (value: unknown) => string | undefined;\n}\n\nexport type LogSchema<TFields extends Record<string, unknown>> = {\n [K in keyof TFields]: LogFieldDef;\n};\n\nexport interface CompiledSchema<TFields extends Record<string, unknown>> {\n readonly fields: LogSchema<TFields>;\n /**\n * Validate a payload against the schema.\n * Returns an array of warning strings (empty = pass).\n * Only runs in non-production environments.\n */\n validate(payload: Partial<TFields>): string[];\n}\n\n// The literal `process.env.NODE_ENV` must stay intact so bundlers can replace it;\n// on runtimes without `process` the ReferenceError is caught.\nfunction isProduction(): boolean {\n try {\n return process.env.NODE_ENV === 'production';\n } catch {\n return false;\n }\n}\n\n// ── defineLogSchema ──────────────────────────────────────────────────────────\n\n/**\n * Define a typed schema for a category of log entries.\n *\n * Call this once at module initialisation and pass it to `createTypedLogger`.\n * In development, every log call is validated against the schema.\n */\nexport function defineLogSchema<TFields extends Record<string, unknown>>(\n fields: LogSchema<TFields>\n): CompiledSchema<TFields> {\n return {\n fields,\n validate(payload: Partial<TFields>): string[] {\n if (isProduction()) return [];\n\n const warnings: string[] = [];\n\n for (const [key, def] of Object.entries(fields) as [keyof TFields & string, LogFieldDef][]) {\n const value = payload[key];\n\n if (def.required && (value === undefined || value === null)) {\n warnings.push(`Required field \"${key}\" is missing`);\n continue;\n }\n\n if (value !== undefined && value !== null) {\n const actualType = Array.isArray(value) ? 'array' : typeof value;\n if (actualType !== def.type) {\n warnings.push(`Field \"${key}\" expected type \"${def.type}\" but got \"${actualType}\"`);\n }\n\n if (def.validate) {\n const msg = def.validate(value);\n if (msg) warnings.push(`Field \"${key}\": ${msg}`);\n }\n }\n }\n\n return warnings;\n },\n };\n}\n\n// ── TypedLogger ──────────────────────────────────────────────────────────────\n\n/** IBaseLogger-compatible subset used by TypedLogger */\nexport interface LoggerLike {\n error(message: string | Error, data?: Record<string, unknown>): Promise<void>;\n warn(message: string, data?: Record<string, unknown>): Promise<void>;\n info(message: string, data?: Record<string, unknown>): Promise<void>;\n debug(message: string, data?: Record<string, unknown>): Promise<void>;\n verbose?(message: string, data?: Record<string, unknown>): Promise<void>;\n trace?(message: string, data?: Record<string, unknown>): Promise<void>;\n}\n\n/**\n * A logger whose metadata is typed to `TFields`.\n *\n * The `error` overload still accepts a plain `Error` object as the first arg\n * (with optional `TFields` data) so the typed logger remains a drop-in replacement.\n */\nexport interface TypedLogger<TFields extends Record<string, unknown>> {\n error(error: Error, data?: Partial<TFields>): Promise<void>;\n error(message: string, data?: Partial<TFields>): Promise<void>;\n warn(message: string, data?: Partial<TFields>): Promise<void>;\n info(message: string, data?: Partial<TFields>): Promise<void>;\n debug(message: string, data?: Partial<TFields>): Promise<void>;\n verbose(message: string, data?: Partial<TFields>): Promise<void>;\n trace(message: string, data?: Partial<TFields>): Promise<void>;\n /** Access the underlying untyped logger if needed. */\n readonly raw: LoggerLike;\n}\n\n/**\n * Wrap any logixia logger with a type-safe field interface.\n *\n * @param logger Any object that implements `IBaseLogger` (e.g. the result of `createLogger()`)\n * @param schema Optional schema for dev-time validation. Created with `defineLogSchema()`.\n */\nexport function createTypedLogger<TFields extends Record<string, unknown>>(\n logger: LoggerLike,\n schema?: CompiledSchema<TFields>\n): TypedLogger<TFields> {\n function withValidation(\n level: string,\n fn: (msg: string, data?: Record<string, unknown>) => Promise<void>,\n message: string,\n data?: Partial<TFields>\n ): Promise<void> {\n if (schema && data) {\n const warnings = schema.validate(data);\n for (const w of warnings) {\n internalWarn(`[logixia/schema] ${w} — level=${level} message=\"${message}\"`);\n }\n }\n return fn(message, data as Record<string, unknown> | undefined);\n }\n\n return {\n raw: logger,\n error(messageOrError: string | Error, data?: Partial<TFields>): Promise<void> {\n if (schema && data) {\n const warnings = schema.validate(data);\n const display = messageOrError instanceof Error ? messageOrError.message : messageOrError;\n for (const w of warnings) {\n internalWarn(`[logixia/schema] ${w} — level=error message=\"${display}\"`);\n }\n }\n return logger.error(messageOrError, data as Record<string, unknown> | undefined);\n },\n warn: (m, d) => withValidation('warn', logger.warn.bind(logger), m, d),\n info: (m, d) => withValidation('info', logger.info.bind(logger), m, d),\n debug: (m, d) => withValidation('debug', logger.debug.bind(logger), m, d),\n verbose: (m, d) =>\n withValidation('verbose', (logger.verbose ?? logger.debug).bind(logger), m, d),\n trace: (m, d) => withValidation('trace', (logger.trace ?? logger.debug).bind(logger), m, d),\n };\n}\n","/**\n * logixia — Canonical Log Lines / Wide Events.\n *\n * Emit ONE dense, structured event per unit of work (usually a request) instead\n * of scattering details across many narrow log lines. Fields are accumulated as\n * the request flows through middleware and business logic, then the whole event\n * is emitted ONCE — in a `finally`/teardown path so it fires even on errors.\n *\n * This is the \"canonical log line\" pattern (Stripe) / \"wide events\" /\n * \"Observability 2.0\" (Honeycomb): one pre-joined, queryable record per request,\n * so operators never JOIN across log lines during an incident. It composes with\n * logixia's existing trace correlation — when a trace is active, the event\n * carries `traceId`/`spanId`, making it OTel-friendly.\n *\n * @example Manual scope\n * ```ts\n * import { withWideEvent, addEventFields } from 'logixia';\n *\n * await withWideEvent(logger, { route: '/checkout' }, async () => {\n * addEventFields({ userId, planTier }); // from anywhere in the call tree\n * addEventFields({ dbQueries: 4, cacheHit });\n * // ...one wide event is emitted automatically when this callback settles,\n * // even if it throws.\n * });\n * ```\n *\n * @example Express middleware (auto-emit on response finish/close)\n * ```ts\n * import { wideEventMiddleware } from 'logixia';\n * app.use(wideEventMiddleware(logger));\n * app.get('/x', (req, res) => { addEventFields({ handled: 'x' }); res.json({}); });\n * ```\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nimport { getCurrentTraceId } from './utils/trace.utils';\n\n/** The accumulating event fields for the current scope. */\nexport type WideEventFields = Record<string, unknown>;\n\ninterface WideEventState {\n fields: WideEventFields;\n startMs: number;\n emitted: boolean;\n}\n\nconst _storage = new AsyncLocalStorage<WideEventState>();\n\n/** Minimal logger surface a wide event needs to emit itself. */\nexport interface WideEventLogger {\n logLevel(level: string, message: string, data?: Record<string, unknown>): Promise<void> | void;\n}\n\nexport interface WideEventOptions {\n /** Level the canonical event is logged at. Default: 'info'. */\n level?: string;\n /** Message for the canonical event line. Default: 'request'. */\n message?: string;\n /**\n * Attach `traceId` (and `spanId` when present) from the active trace context.\n * Default: true.\n */\n includeTrace?: boolean;\n /** Field name for the auto-computed duration in ms. Default: 'durationMs'. */\n durationField?: string;\n}\n\n/**\n * Merge fields into the wide event for the current async scope. No-op (with no\n * throw) when called outside a `withWideEvent` / middleware scope, so business\n * code can call it unconditionally.\n */\nexport function addEventFields(fields: WideEventFields): void {\n const state = _storage.getStore();\n if (!state || state.emitted) return;\n Object.assign(state.fields, fields);\n}\n\n/** Set a single field on the current wide event. */\nexport function setEventField(key: string, value: unknown): void {\n addEventFields({ [key]: value });\n}\n\n/** Read a shallow copy of the wide event accumulated so far, or undefined. */\nexport function getEventFields(): WideEventFields | undefined {\n const state = _storage.getStore();\n return state ? { ...state.fields } : undefined;\n}\n\nfunction emit(\n logger: WideEventLogger,\n state: WideEventState,\n options: WideEventOptions,\n extra?: WideEventFields\n): void {\n if (state.emitted) return;\n state.emitted = true;\n\n const level = options.level ?? 'info';\n const message = options.message ?? 'request';\n const durationField = options.durationField ?? 'durationMs';\n const includeTrace = options.includeTrace ?? true;\n\n const payload: WideEventFields = { ...state.fields };\n if (extra) Object.assign(payload, extra);\n payload[durationField] = Date.now() - state.startMs;\n\n if (includeTrace) {\n const traceId = getCurrentTraceId();\n if (traceId !== undefined && payload['traceId'] === undefined) payload['traceId'] = traceId;\n }\n\n // logLevel may be async (transport-backed); fire-and-forget so the wide-event\n // emit never blocks request teardown. Swallow rejections (the logger surfaces\n // its own transport errors) so this never becomes an unhandled rejection.\n const p = logger.logLevel(level, message, payload);\n if (p && typeof (p as Promise<void>).catch === 'function') {\n (p as Promise<void>).catch(() => {});\n }\n}\n\n/**\n * Run `callback` inside a wide-event scope. `addEventFields` calls anywhere in\n * the (async) call tree accumulate onto one event, which is emitted exactly once\n * when the callback settles — on success OR error (the canonical \"emit in\n * finally\" guarantee). On error, `error` + `errorMessage` fields are added.\n */\nexport async function withWideEvent<T>(\n logger: WideEventLogger,\n initialFields: WideEventFields,\n callback: () => Promise<T> | T,\n options: WideEventOptions = {}\n): Promise<T> {\n const state: WideEventState = {\n fields: { ...initialFields },\n startMs: Date.now(),\n emitted: false,\n };\n\n return _storage.run(state, async () => {\n try {\n const result = await callback();\n emit(logger, state, options);\n return result;\n } catch (error) {\n emit(logger, state, options, {\n error: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n });\n}\n\n// ── HTTP middleware ─────────────────────────────────────────────────────────\n\ninterface MwReq {\n method?: string | undefined;\n url?: string | undefined;\n originalUrl?: string | undefined;\n ip?: string | undefined;\n headers?: Record<string, unknown> | undefined;\n socket?: { remoteAddress?: string } | undefined;\n}\ninterface MwRes {\n statusCode?: number;\n once?: (event: string, cb: () => void) => void;\n}\n\nexport interface WideEventMiddlewareOptions extends WideEventOptions {\n /** Derive extra initial fields from the request. */\n enrich?: (req: MwReq) => WideEventFields;\n /** Skip wide-event emission for a request (e.g. health checks). */\n skip?: (req: MwReq) => boolean;\n}\n\n/**\n * Express/Connect middleware that opens a wide-event scope per request and\n * emits ONE canonical event on response `finish`/`close` — even if the handler\n * throws or the client disconnects. Pre-populates method/url/ip; handlers add\n * more via `addEventFields`. The completion event includes `statusCode` and the\n * request duration.\n */\nexport function wideEventMiddleware(\n logger: WideEventLogger,\n options: WideEventMiddlewareOptions = {}\n): (req: MwReq, res: MwRes, next: () => void) => void {\n return function logixiaWideEventMiddleware(req: MwReq, res: MwRes, next: () => void): void {\n if (options.skip?.(req)) {\n next();\n return;\n }\n\n const base: WideEventFields = {\n method: req.method,\n url: req.originalUrl ?? req.url,\n ip: req.ip ?? req.socket?.remoteAddress,\n ...(options.enrich ? options.enrich(req) : {}),\n };\n\n const state: WideEventState = { fields: base, startMs: Date.now(), emitted: false };\n\n const finalize = (): void => {\n emit(logger, state, options, { statusCode: res.statusCode ?? 0 });\n };\n\n // Both 'finish' and 'close' may fire; emit() is idempotent (emitted guard),\n // so the canonical line is logged exactly once.\n res.once?.('finish', finalize);\n res.once?.('close', finalize);\n\n _storage.run(state, () => next());\n };\n}\n","/**\n * logixia — Metrics extraction → Prometheus\n *\n * Automatically extracts metrics from structured log fields and exposes them\n * in the Prometheus text exposition format (version 0.0.4).\n * No external dependency — the format is fully self-contained.\n *\n * Supported metric types:\n * - `counter` — incremented on each matching log entry\n * - `histogram` — observes a numeric payload field per entry\n * - `gauge` — tracks the most recent numeric value of a payload field\n *\n * Usage:\n * ```ts\n * import { createMetricsPlugin } from 'logixia';\n *\n * const metrics = createMetricsPlugin({\n * http_request_duration: {\n * type: 'histogram',\n * field: 'duration',\n * labels: ['method', 'statusCode'],\n * help: 'HTTP request duration in milliseconds',\n * },\n * error_count: {\n * type: 'counter',\n * levelFilter: 'error',\n * labels: ['context'],\n * help: 'Total error log entries',\n * },\n * active_connections: {\n * type: 'gauge',\n * field: 'connections',\n * help: 'Current active connection count',\n * },\n * });\n *\n * logger.use(metrics); // start collecting\n * app.get('/metrics', metrics.expressHandler()); // expose for Prometheus scrape\n * ```\n *\n * All metric names are automatically prefixed with `logixia_`.\n * Output follows https://prometheus.io/docs/instrumenting/exposition_formats/\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport type { LogixiaPlugin } from './plugin';\nimport type { LogEntry } from './types/index';\n\n// ── Metric config types ───────────────────────────────────────────────────────\n\n/**\n * Increment a counter on each matching log entry.\n *\n * @example Count every error entry, labelled by context:\n * ```ts\n * error_count: { type: 'counter', levelFilter: 'error', labels: ['context'] }\n * ```\n *\n * @example Count entries where payload.event === 'checkout':\n * ```ts\n * checkout_events: { type: 'counter', field: 'event', value: 'checkout' }\n * ```\n */\nexport interface CounterConfig {\n type: 'counter';\n /** Only increment when `entry.level` equals this value. Omit to count all entries. */\n levelFilter?: string;\n /**\n * Only increment when `entry.payload[field] === value`.\n * If omitted, every entry (matching `levelFilter`) is counted.\n */\n field?: string;\n value?: unknown;\n /** `entry.payload` fields used as Prometheus label dimensions. `'level'` is also valid. */\n labels?: string[];\n help?: string;\n}\n\n/**\n * Observe a numeric payload field and bucket it into a Prometheus histogram.\n *\n * @example Duration histogram labelled by HTTP method and status code:\n * ```ts\n * http_request_duration: {\n * type: 'histogram',\n * field: 'duration',\n * labels: ['method', 'statusCode'],\n * buckets: [10, 25, 50, 100, 250, 500, 1000],\n * }\n * ```\n */\nexport interface HistogramConfig {\n type: 'histogram';\n /** The `entry.payload` field containing the numeric value to observe. */\n field: string;\n /** `entry.payload` fields used as Prometheus label dimensions. */\n labels?: string[];\n help?: string;\n /**\n * Bucket upper bounds (inclusive). Sorted automatically.\n * Default: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000]\n */\n buckets?: number[];\n}\n\n/**\n * Track the most recent numeric value of a payload field as a gauge.\n *\n * @example Track live connection count:\n * ```ts\n * active_connections: { type: 'gauge', field: 'connections' }\n * ```\n */\nexport interface GaugeConfig {\n type: 'gauge';\n /** The `entry.payload` field containing the numeric value. */\n field: string;\n /** `entry.payload` fields used as Prometheus label dimensions. */\n labels?: string[];\n help?: string;\n}\n\nexport type MetricConfig = CounterConfig | HistogramConfig | GaugeConfig;\nexport type MetricsMap = Record<string, MetricConfig>;\n\n// ── Internal metric state ─────────────────────────────────────────────────────\n\ninterface CounterState {\n type: 'counter';\n values: Map<string, number>;\n}\n\ninterface HistogramState {\n type: 'histogram';\n buckets: number[];\n /** Parallel arrays; index = bucket index; last entry = +Inf cumulative count */\n counts: Map<string, number[]>;\n sums: Map<string, number>;\n observations: Map<string, number>;\n}\n\ninterface GaugeState {\n type: 'gauge';\n values: Map<string, number>;\n}\n\ntype MetricState = CounterState | HistogramState | GaugeState;\n\n// ── Defaults ──────────────────────────────────────────────────────────────────\n\nconst DEFAULT_BUCKETS: readonly number[] = [\n 1, 5, 10, 25, 50, 100, 250, 500, 1_000, 2_500, 5_000, 10_000,\n];\n\nconst MAX_LABEL_VALUE_LENGTH = 256;\nconst DEFAULT_MAX_LABEL_SETS = 1000;\n/** Label value used for the series that absorbs label sets beyond the cardinality cap. */\nexport const OVERFLOW_LABEL_VALUE = '__overflow__';\n\nexport interface MetricsPluginOptions {\n /**\n * Maximum number of distinct label sets tracked per metric. Once reached, new\n * label sets are folded into a single series whose label values are all\n * `__overflow__`, so payload-driven labels cannot grow memory or the scrape\n * output without bound.\n * @default 1000\n */\n maxLabelSets?: number;\n}\n\n// ── Label helpers ─────────────────────────────────────────────────────────────\n\nfunction buildLabelKey(config: MetricConfig, entry: LogEntry): string {\n const labelNames = config.labels ?? [];\n if (labelNames.length === 0) return '{}';\n const pairs: Record<string, string> = {};\n const payload = entry.payload ?? {};\n for (const name of labelNames) {\n const raw = name === 'level' ? entry.level : payload[name];\n // Sanitize the label NAME (the value is escaped at render time) so a label\n // like 'status code' can't emit unparseable Prometheus output.\n pairs[sanitizePromName(name)] =\n raw !== undefined && raw !== null ? String(raw).slice(0, MAX_LABEL_VALUE_LENGTH) : '';\n }\n return JSON.stringify(pairs);\n}\n\n/** Label key of the shared overflow series for a metric (all label values `__overflow__`). */\nfunction buildOverflowKey(config: MetricConfig): string {\n const names = config.labels ?? [];\n if (names.length === 0) return '{}';\n return JSON.stringify(\n Object.fromEntries(names.map((n) => [sanitizePromName(n), OVERFLOW_LABEL_VALUE]))\n );\n}\n\nfunction renderLabels(labelKey: string): string {\n if (labelKey === '{}') return '';\n const obj = JSON.parse(labelKey) as Record<string, string>;\n const parts = Object.entries(obj).map(([k, v]) => `${k}=\"${escapeLabel(v)}\"`);\n return `{${parts.join(',')}}`;\n}\n\nfunction escapeLabel(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n}\n\n/**\n * Coerce an arbitrary string into a valid Prometheus metric or label name\n * (`[a-zA-Z_][a-zA-Z0-9_]*`). Invalid characters become underscores and a\n * leading digit is prefixed with `_`. Without this, a user-supplied name like\n * `my-metric` or a label like `status code` would emit output Prometheus cannot\n * parse, breaking the ENTIRE scrape endpoint, not just that metric.\n */\nfunction sanitizePromName(name: string): string {\n let safe = name.replace(/\\W/g, '_');\n if (safe.length > 0 && /\\d/.test(safe[0]!)) safe = `_${safe}`;\n return safe.length > 0 ? safe : '_';\n}\n\n// ── MetricsPlugin ─────────────────────────────────────────────────────────────\n\n/**\n * A logixia plugin that extracts Prometheus-compatible metrics from log entries.\n *\n * Implements `LogixiaPlugin` — pass directly to `logger.use()`:\n * ```ts\n * const metrics = new MetricsPlugin({ ... });\n * logger.use(metrics);\n * ```\n *\n * Or use the `createMetricsPlugin()` factory (preferred):\n * ```ts\n * const metrics = createMetricsPlugin({ ... });\n * logger.use(metrics);\n * ```\n */\nexport class MetricsPlugin implements LogixiaPlugin {\n public readonly name = 'logixia-metrics';\n\n private readonly map: MetricsMap;\n private readonly metricState = new Map<string, MetricState>();\n private readonly overflowKeys = new Map<string, string>();\n\n private readonly maxLabelSets: number;\n\n constructor(map: MetricsMap, options: MetricsPluginOptions = {}) {\n this.map = map;\n const max = options.maxLabelSets;\n this.maxLabelSets =\n typeof max === 'number' && Number.isFinite(max) && max >= 1\n ? Math.floor(max)\n : DEFAULT_MAX_LABEL_SETS;\n this.initAllState();\n }\n\n // ── LogixiaPlugin lifecycle ────────────────────────────────────────────────\n\n onInit(): void {\n // State is initialised in the constructor; nothing extra needed here.\n }\n\n onLog(entry: LogEntry): LogEntry {\n const payload = entry.payload ?? {};\n\n for (const [rawName, config] of Object.entries(this.map)) {\n const state = this.metricState.get(rawName);\n if (!state) continue;\n\n const rawLabelKey = buildLabelKey(config, entry);\n const overflowKey = this.overflowKeys.get(rawName) ?? '{}';\n\n if (config.type === 'counter' && state.type === 'counter') {\n // Level filter\n if (config.levelFilter && entry.level !== config.levelFilter) continue;\n // Field/value filter\n if (config.field !== undefined && payload[config.field] !== config.value) continue;\n const labelKey = this.capLabelKey(state.values, rawLabelKey, overflowKey);\n state.values.set(labelKey, (state.values.get(labelKey) ?? 0) + 1);\n } else if (config.type === 'histogram' && state.type === 'histogram') {\n const raw = payload[config.field];\n if (raw === undefined || raw === null) continue;\n const val = Number(raw);\n if (Number.isNaN(val)) continue;\n const labelKey = this.capLabelKey(state.counts, rawLabelKey, overflowKey);\n\n // Initialise per-label arrays on first observation\n if (!state.counts.has(labelKey)) {\n state.counts.set(\n labelKey,\n Array.from<number>({ length: state.buckets.length + 1 }).fill(0)\n );\n state.sums.set(labelKey, 0);\n state.observations.set(labelKey, 0);\n }\n\n const bucketArr = state.counts.get(labelKey)!;\n for (let i = 0; i < state.buckets.length; i++) {\n if (val <= state.buckets[i]!) bucketArr[i]!++;\n }\n // The +Inf bucket (last slot) always increments\n bucketArr[state.buckets.length]!++;\n state.sums.set(labelKey, (state.sums.get(labelKey) ?? 0) + val);\n state.observations.set(labelKey, (state.observations.get(labelKey) ?? 0) + 1);\n } else if (config.type === 'gauge' && state.type === 'gauge') {\n const raw = payload[config.field];\n if (raw === undefined || raw === null) continue;\n const val = Number(raw);\n if (Number.isNaN(val)) continue;\n state.values.set(this.capLabelKey(state.values, rawLabelKey, overflowKey), val);\n }\n }\n\n // Always pass the entry through unchanged\n return entry;\n }\n\n // ── Output ─────────────────────────────────────────────────────────────────\n\n /**\n * Render all registered metrics in the Prometheus text exposition format\n * (version 0.0.4).\n *\n * All metric names are prefixed with `logixia_`.\n *\n * @example\n * ```\n * # HELP logixia_error_count Total error log entries\n * # TYPE logixia_error_count counter\n * logixia_error_count{context=\"OrderService\"} 7\n * ```\n */\n render(): string {\n const lines: string[] = [];\n\n for (const [rawName, config] of Object.entries(this.map)) {\n const metricName = `logixia_${sanitizePromName(rawName)}`;\n const state = this.metricState.get(rawName);\n if (!state) continue;\n\n const helpText = config.help ?? rawName.replace(/_/g, ' ');\n lines.push(`# HELP ${metricName} ${helpText}`);\n lines.push(`# TYPE ${metricName} ${config.type}`);\n\n if (state.type === 'counter') {\n if (state.values.size === 0) {\n lines.push(`${metricName} 0`);\n } else {\n for (const [labelKey, count] of state.values) {\n lines.push(`${metricName}${renderLabels(labelKey)} ${count}`);\n }\n }\n } else if (state.type === 'histogram') {\n for (const [labelKey, bucketCounts] of state.counts) {\n const labelSuffix = renderLabels(labelKey);\n const baseObj = labelKey === '{}' ? {} : (JSON.parse(labelKey) as Record<string, string>);\n\n // One line per finite bucket\n for (let i = 0; i < state.buckets.length; i++) {\n const leKey = JSON.stringify({ ...baseObj, le: String(state.buckets[i]) });\n lines.push(`${metricName}_bucket${renderLabels(leKey)} ${bucketCounts[i] ?? 0}`);\n }\n // +Inf bucket\n const infKey = JSON.stringify({ ...baseObj, le: '+Inf' });\n lines.push(\n `${metricName}_bucket${renderLabels(infKey)} ${bucketCounts[state.buckets.length] ?? 0}`\n );\n lines.push(`${metricName}_sum${labelSuffix} ${state.sums.get(labelKey) ?? 0}`);\n lines.push(`${metricName}_count${labelSuffix} ${state.observations.get(labelKey) ?? 0}`);\n }\n } else if (state.type === 'gauge') {\n if (state.values.size === 0) {\n lines.push(`${metricName} 0`);\n } else {\n for (const [labelKey, val] of state.values) {\n lines.push(`${metricName}${renderLabels(labelKey)} ${val}`);\n }\n }\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n }\n\n /**\n * Reset all metric counters and observations back to zero.\n * Useful between test runs or on a scheduled reset interval.\n */\n reset(): void {\n this.metricState.clear();\n this.initAllState();\n }\n\n /**\n * Express route handler — call `app.get('/metrics', metrics.expressHandler())`.\n *\n * @example\n * ```ts\n * import express from 'express';\n * const app = express();\n * app.get('/metrics', metrics.expressHandler());\n * ```\n */\n expressHandler(): (\n req: unknown,\n res: { set(k: string, v: string): unknown; end(body: string): void }\n ) => void {\n return (_req, res) => {\n res.set('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\n res.end(this.render());\n };\n }\n\n /**\n * Raw Node.js `http` server handler.\n * Responds to `GET /metrics` with the Prometheus text payload.\n *\n * @example Start a dedicated metrics server on the standard port:\n * ```ts\n * import http from 'node:http';\n * const server = http.createServer(metrics.httpHandler());\n * server.listen(9464); // Prometheus default port for custom exporters\n * ```\n */\n httpHandler(): (req: IncomingMessage, res: ServerResponse) => void {\n return (req, res) => {\n const isMetricsPath = req.url === '/metrics' || req.url === '/metrics/';\n if (!isMetricsPath) {\n res.writeHead(404).end('Not found');\n return;\n }\n const body = this.render();\n res.writeHead(200, {\n 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body),\n });\n res.end(body);\n };\n }\n\n // ── Private helpers ────────────────────────────────────────────────────────\n\n /**\n * Return `labelKey` when it is already tracked or there is room for it;\n * otherwise the shared overflow series key.\n */\n private capLabelKey(series: Map<string, unknown>, labelKey: string, overflowKey: string): string {\n if (series.has(labelKey) || series.size < this.maxLabelSets) return labelKey;\n return overflowKey;\n }\n\n private initAllState(): void {\n for (const [rawName, config] of Object.entries(this.map)) {\n this.initSingleState(rawName, config);\n }\n }\n\n private initSingleState(rawName: string, config: MetricConfig): void {\n this.overflowKeys.set(rawName, buildOverflowKey(config));\n if (config.type === 'counter') {\n this.metricState.set(rawName, { type: 'counter', values: new Map() });\n } else if (config.type === 'histogram') {\n const buckets = [...(config.buckets ?? DEFAULT_BUCKETS)].sort((a, b) => a - b);\n this.metricState.set(rawName, {\n type: 'histogram',\n buckets,\n counts: new Map(),\n sums: new Map(),\n observations: new Map(),\n });\n } else {\n this.metricState.set(rawName, { type: 'gauge', values: new Map() });\n }\n }\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Create a `MetricsPlugin` from a metrics map and return it ready for\n * `logger.use()`.\n *\n * @example\n * ```ts\n * import { createMetricsPlugin } from 'logixia';\n *\n * const metrics = createMetricsPlugin({\n * http_request_duration: {\n * type: 'histogram',\n * field: 'duration',\n * labels: ['method', 'statusCode'],\n * help: 'HTTP request duration in milliseconds',\n * },\n * error_count: {\n * type: 'counter',\n * levelFilter: 'error',\n * labels: ['context'],\n * help: 'Total error log entries',\n * },\n * });\n *\n * logger.use(metrics);\n * app.get('/metrics', metrics.expressHandler());\n * ```\n *\n * Pass `{ maxLabelSets }` to change the per-metric label cardinality cap (default 1000).\n */\nexport function createMetricsPlugin(\n map: MetricsMap,\n options?: MetricsPluginOptions\n): MetricsPlugin {\n return new MetricsPlugin(map, options);\n}\n","/**\n * Logixia - Advanced TypeScript Logger\n *\n * A comprehensive logging library with support for:\n * - Multiple output formats (console, file, JSON)\n * - Trace ID tracking\n * - Performance monitoring\n * - NestJS integration\n * - Customizable log levels and colors\n * - Intelligent log search and aggregation\n * - Natural language query processing\n * - Pattern recognition and anomaly detection\n */\n\nimport { DEFAULT_CONFIG } from './core/default-config';\nimport { createLogger as createLoggerFromCore, LogixiaLogger } from './core/logitron-logger';\n\n// Type exports\nexport * from './formatters';\nexport * from './types';\nexport * from './utils/error.utils';\nexport type { OtelBridgeOptions, OtelSpanContext } from './utils/otel';\nexport {\n disableOtelBridge,\n getActiveOtelContext,\n getOtelMetaFields,\n initOtelBridge,\n} from './utils/otel';\nexport { applyRedaction, redactObject } from './utils/redact.utils';\nexport type { LevelSignalOptions, ReconfigurableLogger } from './utils/runtime-control';\nexport { createLevelControlHandler, registerLevelSignal } from './utils/runtime-control';\nexport type { SafeStringifyOptions } from './utils/safe-stringify';\nexport { decycleValue, retrocycle, safeStringify, stringifyForLog } from './utils/safe-stringify';\nexport * from './utils/shutdown.utils';\nexport * from './utils/trace.utils';\nexport type {\n CompiledSchema,\n LogFieldDef,\n LogFieldType,\n LoggerLike,\n LogSchema,\n TypedLogger,\n} from './utils/typed-logger';\nexport { createTypedLogger, defineLogSchema } from './utils/typed-logger';\nexport type {\n WideEventFields,\n WideEventLogger,\n WideEventMiddlewareOptions,\n WideEventOptions,\n} from './wide-events';\nexport {\n addEventFields,\n getEventFields,\n setEventField,\n wideEventMiddleware,\n withWideEvent,\n} from './wide-events';\n\n// OTLP logs export transport (OpenTelemetry-native log emission)\nexport type { OtlpLogTransportConfig } from './transports/otlp.transport';\nexport { OtlpLogTransport, toOtelSeverity } from './transports/otlp.transport';\n\n// Chat webhook transports\nexport type { DiscordEmbed, DiscordTransportConfig } from './transports/discord.transport';\nexport { DiscordTransport } from './transports/discord.transport';\nexport type { SlackMessage, SlackTransportConfig } from './transports/slack.transport';\nexport { SlackTransport } from './transports/slack.transport';\n\n// Search module exports\nexport * from './search';\n\n// Context propagation (AsyncLocalStorage)\nexport type { LogContext } from './context/async-context';\nexport {\n createExpressContextMiddleware,\n createFastifyContextHook,\n LogixiaContext,\n} from './context/async-context';\n\n// Sampling stats (SamplingConfig is already exported via ./types)\nexport type { SamplingStats } from './utils/sampling.utils';\n\n// Plugin API (Feature 20)\nexport type { LogixiaPlugin } from './plugin';\nexport { globalPluginRegistry, PluginRegistry, usePlugin } from './plugin';\n\n// Exception system — typed LogixiaException + unified error response format\nexport type {\n BuildParams,\n ErrorDetail,\n LogixiaErrorResponse,\n LogixiaExceptionOptions,\n} from './exceptions';\nexport {\n ErrorResponseBuilder,\n generateRequestId,\n generateTraceId,\n isLogixiaException,\n LogixiaException,\n} from './exceptions';\n\n// Metrics extraction → Prometheus (Feature 21)\nexport type {\n CounterConfig,\n GaugeConfig,\n HistogramConfig,\n MetricConfig,\n MetricsMap,\n} from './metrics';\nexport type { MetricsPluginOptions } from './metrics';\nexport { createMetricsPlugin, MetricsPlugin, OVERFLOW_LABEL_VALUE } from './metrics';\n\n// Core exports\nexport { DEFAULT_CONFIG, LogixiaLogger };\n\n/**\n * Create a new Logixia logger instance with TypeScript support for custom levels\n * @param config - Logger configuration\n * @returns Typed logger instance\n */\nexport const createLogger = createLoggerFromCore;\n\n/**\n * Default logger instance\n */\nexport const logger = new LogixiaLogger(DEFAULT_CONFIG);\n\n/**\n * Export default configuration for reference\n */\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["serializeError","stripControlChars","safeToString","LogLevel","AsyncLocalStorage","getCurrentTraceId","buildNameSet","DEFAULT_REDACT_QUERY_PARAMS","redactUrlQuery","createLoggerFromCore","LogixiaLogger","DEFAULT_CONFIG"],"sources":["../src/formatters/json.formatter.ts","../src/formatters/text.formatter.ts","../src/utils/runtime-control.ts","../src/utils/typed-logger.ts","../src/wide-events.ts","../src/metrics.ts","../src/index.ts"],"sourcesContent":["/**\n * JSON formatter for Logixia\n */\n\nimport type { ILogFormatter, LogEntry } from '../types';\nimport { serializeError } from '../utils/error.utils';\nimport { assignOwn } from '../utils/own-property';\n\n/**\n * Build a JSON.stringify replacer that replaces circular references with the\n * string '[Circular]' instead of throwing. A fresh replacer must be created per\n * stringify call because it holds per-serialization state (the seen set).\n */\nfunction createCircularReplacer(): (key: string, value: unknown) => unknown {\n const seen = new WeakSet<object>();\n return function (this: unknown, _key: string, value: unknown): unknown {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n }\n return value;\n };\n}\n\nexport class JsonFormatter implements ILogFormatter {\n private includeTimestamp: boolean;\n private includeLevel: boolean;\n private includeAppName: boolean;\n private includeTraceId: boolean;\n private includeContext: boolean;\n private prettyPrint: boolean;\n\n constructor(\n options: {\n includeTimestamp?: boolean;\n includeLevel?: boolean;\n includeAppName?: boolean;\n includeTraceId?: boolean;\n includeContext?: boolean;\n prettyPrint?: boolean;\n } = {}\n ) {\n this.includeTimestamp = options.includeTimestamp ?? true;\n this.includeLevel = options.includeLevel ?? true;\n this.includeAppName = options.includeAppName ?? true;\n this.includeTraceId = options.includeTraceId ?? true;\n this.includeContext = options.includeContext ?? true;\n this.prettyPrint = options.prettyPrint ?? false;\n }\n\n format(entry: LogEntry): string {\n const formatted: Record<string, unknown> = {};\n\n // Add timestamp\n if (this.includeTimestamp) {\n formatted.timestamp = entry.timestamp;\n }\n\n // Add log level\n if (this.includeLevel) {\n formatted.level = entry.level.toLowerCase();\n formatted.levelValue = entry.level;\n }\n\n // Add app name\n if (this.includeAppName) {\n formatted.appName = entry.appName;\n }\n\n // Add trace ID\n if (this.includeTraceId && entry.traceId) {\n formatted.traceId = entry.traceId;\n }\n\n // Add context\n if (this.includeContext && entry.context) {\n formatted.context = entry.context;\n }\n\n // Add message\n formatted.message = entry.message;\n\n // Add payload\n if (entry.payload && Object.keys(entry.payload).length > 0) {\n formatted.payload = this.serializePayload(entry.payload);\n }\n\n // Add error if present\n if (entry.error) {\n formatted.error = serializeError(entry.error);\n }\n\n // Add metadata\n formatted.meta = {\n pid: process.pid,\n hostname: process.env.HOSTNAME || 'unknown',\n version: process.version,\n };\n\n // Use a circular-safe replacer: a payload containing a cycle (e.g. an Express\n // req/res, a DB connection, a Mongoose doc) would otherwise make JSON.stringify\n // throw and crash the entire log/transport path.\n const replacer = createCircularReplacer();\n return this.prettyPrint\n ? JSON.stringify(formatted, replacer, 2)\n : JSON.stringify(formatted, replacer);\n }\n\n private serializePayload(payload: Record<string, unknown>): Record<string, unknown> {\n const serialized: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(payload)) {\n try {\n if (value instanceof Error) {\n assignOwn(serialized, key, serializeError(value));\n } else if (value instanceof Date) {\n assignOwn(serialized, key, value.toISOString());\n } else if (typeof value === 'function') {\n assignOwn(serialized, key, '[Function]');\n } else if (typeof value === 'symbol') {\n assignOwn(serialized, key, value.toString());\n } else if (value === undefined) {\n assignOwn(serialized, key, null);\n } else {\n assignOwn(serialized, key, value);\n }\n } catch {\n assignOwn(serialized, key, '[Unserializable]');\n }\n }\n\n return serialized;\n }\n}\n","/**\n * Text formatter for Logixia\n */\n\nimport type { ILogFormatter, LogEntry } from '../types';\nimport { LogLevel } from '../types';\nimport { safeToString } from '../utils/coerce.utils';\nimport { stripControlChars } from '../utils/sanitize.utils';\n\n// Coerce non-strings (objects passed via setContext, Errors as messages, etc.)\n// before .replace() to avoid TypeError on the hot path.\nconst stripControls = (value: unknown): string => stripControlChars(safeToString(value));\n\nexport class TextFormatter implements ILogFormatter {\n private colorize: boolean;\n private includeTimestamp: boolean;\n private includeAppName: boolean;\n private includeTraceId: boolean;\n private includeContext: boolean;\n private timestampFormat: 'iso' | 'locale' | 'short';\n private colors: Record<string, string>;\n\n constructor(\n options: {\n colorize?: boolean;\n includeTimestamp?: boolean;\n includeAppName?: boolean;\n includeTraceId?: boolean;\n includeContext?: boolean;\n timestampFormat?: 'iso' | 'locale' | 'short';\n colors?: Record<string, string>;\n } = {}\n ) {\n this.colorize = options.colorize ?? true;\n this.includeTimestamp = options.includeTimestamp ?? true;\n this.includeAppName = options.includeAppName ?? true;\n this.includeTraceId = options.includeTraceId ?? true;\n this.includeContext = options.includeContext ?? true;\n this.timestampFormat = options.timestampFormat ?? 'locale';\n this.colors = {\n error: '\\x1b[31m', // Red\n warn: '\\x1b[33m', // Yellow\n info: '\\x1b[32m', // Green\n debug: '\\x1b[34m', // Blue\n trace: '\\x1b[35m', // Magenta\n verbose: '\\x1b[36m', // Cyan\n reset: '\\x1b[0m', // Reset\n bold: '\\x1b[1m', // Bold\n dim: '\\x1b[2m', // Dim\n ...options.colors,\n };\n }\n\n format(entry: LogEntry): string {\n const parts: string[] = [];\n\n // Add timestamp\n if (this.includeTimestamp) {\n const timestamp = this.formatTimestamp(entry.timestamp);\n parts.push(this.colorize ? `${this.colors.dim}${timestamp}${this.colors.reset}` : timestamp);\n }\n\n // Add log level\n const levelName = entry.level.toLowerCase();\n const levelColor = this.colors[levelName] || this.colors.reset;\n const formattedLevel = this.colorize\n ? `${levelColor}${this.colors.bold}${levelName.toUpperCase().padEnd(5)}${this.colors.reset}`\n : levelName.toUpperCase().padEnd(5);\n parts.push(`[${formattedLevel}]`);\n\n // Add app name\n if (this.includeAppName) {\n const safeAppName = stripControls(entry.appName);\n const appName = this.colorize\n ? `${this.colors.bold}${safeAppName}${this.colors.reset}`\n : safeAppName;\n parts.push(`[${appName}]`);\n }\n\n // Add trace ID\n if (this.includeTraceId && entry.traceId) {\n const safeTraceId = stripControls(entry.traceId);\n const traceId = this.colorize\n ? `${this.colors.dim}${safeTraceId}${this.colors.reset}`\n : safeTraceId;\n parts.push(`[${traceId}]`);\n }\n\n // Add context\n if (this.includeContext && entry.context) {\n const safeContext = stripControls(entry.context);\n const context = this.colorize\n ? `${this.colors.cyan}${safeContext}${this.colors.reset}`\n : safeContext;\n parts.push(`[${context}]`);\n }\n\n // Add message\n const safeMessage = stripControls(entry.message);\n const message =\n this.colorize && entry.level === LogLevel.ERROR\n ? `${this.colors.error}${safeMessage}${this.colors.reset}`\n : safeMessage;\n parts.push(message);\n\n // Add payload\n if (entry.payload && Object.keys(entry.payload).length > 0) {\n const payload = this.formatPayload(entry.payload);\n if (payload) {\n parts.push(this.colorize ? `${this.colors.dim}${payload}${this.colors.reset}` : payload);\n }\n }\n\n return parts.join(' ');\n }\n\n private formatTimestamp(timestamp: string): string {\n const date = new Date(timestamp);\n\n switch (this.timestampFormat) {\n case 'iso':\n return date.toISOString();\n case 'short':\n return date.toLocaleTimeString();\n case 'locale':\n default:\n return date.toLocaleString();\n }\n }\n\n private formatPayload(payload: Record<string, unknown>): string {\n try {\n // Handle simple objects\n if (Object.keys(payload).length === 1) {\n const entry = Object.entries(payload)[0];\n if (entry) {\n const [key, value] = entry;\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return `${key}=${value}`;\n }\n }\n }\n\n // Handle multiple properties or complex objects\n const formatted = Object.entries(payload)\n .map(([key, value]) => {\n if (value === null || value === undefined) {\n return `${key}=${value}`;\n }\n if (typeof value === 'string') {\n return `${key}=\"${value}\"`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return `${key}=${value}`;\n }\n if (value instanceof Date) {\n return `${key}=${value.toISOString()}`;\n }\n if (typeof value === 'object') {\n // safeToString is circular-safe (raw JSON.stringify throws on a cycle\n // — e.g. an Express req/res — which would crash the log call) and the\n // control-char strip keeps the CWE-117 guarantee for object values.\n return `${key}=${stripControls(safeToString(value))}`;\n }\n return `${key}=${String(value)}`;\n })\n .join(' ');\n\n return formatted;\n } catch {\n // Last-resort fallback must also be circular-safe — the previous\n // JSON.stringify(payload) here threw again on the same cyclic payload.\n return stripControls(safeToString(payload));\n }\n }\n\n /**\n * Create a formatter with preset configurations\n */\n static createSimple(): TextFormatter {\n return new TextFormatter({\n colorize: true,\n includeTimestamp: true,\n includeAppName: false,\n includeTraceId: false,\n includeContext: true,\n timestampFormat: 'short',\n });\n }\n\n static createDetailed(): TextFormatter {\n return new TextFormatter({\n colorize: true,\n includeTimestamp: true,\n includeAppName: true,\n includeTraceId: true,\n includeContext: true,\n timestampFormat: 'locale',\n });\n }\n\n static createMinimal(): TextFormatter {\n return new TextFormatter({\n colorize: false,\n includeTimestamp: false,\n includeAppName: false,\n includeTraceId: false,\n includeContext: false,\n });\n }\n}\n","/**\n * logixia — Dynamic runtime log-level reconfiguration.\n *\n * Change log levels in a running process WITHOUT a restart — the single\n * most-requested logging feature across the Winston and Pino issue trackers\n * (winston#1107, pino#206/#677, nestjs-pino#371). The ecosystem even built a\n * standalone module for it (pino-arborsculpture); logixia ships it first-class.\n *\n * Two trigger surfaces:\n * - {@link registerLevelSignal} — flip levels via an OS signal (default SIGUSR2),\n * cycling through a level list. Zero HTTP surface, safe for any deployment.\n * - {@link createLevelControlHandler} — a tiny HTTP handler so an ops dashboard\n * can GET the current level and POST a new global / per-namespace level.\n *\n * @example Signal-based (cycle levels on each `kill -USR2 <pid>`)\n * ```ts\n * import { registerLevelSignal } from 'logixia';\n * const dispose = registerLevelSignal(logger);\n * // later: process.kill(process.pid, 'SIGUSR2') → info → debug → trace → info …\n * ```\n *\n * @example HTTP admin endpoint\n * ```ts\n * import { createLevelControlHandler } from 'logixia';\n * const handler = createLevelControlHandler(logger);\n * app.all('/admin/log-level', handler); // GET reads, POST { level, namespaceLevels } sets\n * ```\n */\n\nimport type { LogLevelString, NamespaceLevels } from '../types';\nimport { internalLog, internalWarn } from './internal-log';\n\n/** Minimal logger surface the runtime controls need. */\nexport interface ReconfigurableLogger {\n getLevel(): LogLevelString;\n setLevel(level: LogLevelString): void;\n setNamespaceLevels?(levels: NamespaceLevels): void;\n getNamespaceLevels?(): NamespaceLevels;\n}\n\nconst DEFAULT_CYCLE: readonly LogLevelString[] = [\n 'error',\n 'warn',\n 'info',\n 'debug',\n 'trace',\n 'verbose',\n] as unknown as readonly LogLevelString[];\n\nexport interface LevelSignalOptions {\n /** Signal to listen on. Default: 'SIGUSR2' (SIGUSR1 is used by the Node debugger). */\n signal?: NodeJS.Signals;\n /** Ordered levels to cycle through on each signal. Default: error→…→verbose. */\n cycle?: LogLevelString[];\n}\n\n/**\n * Register an OS-signal handler that cycles the logger's global level on each\n * signal. Returns a dispose function that removes the listener.\n *\n * Cycling (rather than jumping straight to a fixed level) means a single,\n * memorizable command (`kill -USR2 <pid>`) is enough to ratchet verbosity up\n * while chasing a bug and back down again — no value to remember.\n */\nexport function registerLevelSignal(\n logger: ReconfigurableLogger,\n options: LevelSignalOptions = {}\n): () => void {\n const signal = options.signal ?? 'SIGUSR2';\n const cycle = options.cycle && options.cycle.length > 0 ? options.cycle : [...DEFAULT_CYCLE];\n\n const handler = (): void => {\n const current = logger.getLevel();\n const idx = cycle.indexOf(current);\n const next = cycle[(idx + 1) % cycle.length]!;\n logger.setLevel(next);\n internalLog(`runtime level changed via ${signal}: ${current} → ${next}`);\n };\n\n process.on(signal, handler);\n return () => {\n process.removeListener(signal, handler);\n };\n}\n\n// ── HTTP admin handler ────────────────────────────────────────────────────────\n\ninterface MinimalReq {\n method?: string | undefined;\n headers?: Record<string, string | string[] | undefined> | undefined;\n on?: (event: string, cb: (chunk?: unknown) => void) => void;\n}\ninterface MinimalRes {\n statusCode?: number;\n setHeader?: (k: string, v: string) => void;\n end: (body?: string) => void;\n}\n\n/** Maximum accepted request body size for the level control handler. */\nconst MAX_BODY_BYTES = 16 * 1024;\n\nfunction isJsonContentType(req: MinimalReq): boolean {\n const raw = req.headers?.['content-type'];\n const value = Array.isArray(raw) ? raw[0] : raw;\n if (typeof value !== 'string') return false;\n return value.split(';')[0]!.trim().toLowerCase() === 'application/json';\n}\n\nconst VALID_LEVELS = new Set<string>([\n 'error',\n 'warn',\n 'info',\n 'debug',\n 'trace',\n 'verbose',\n 'fatal',\n]);\n\n/**\n * Create an HTTP handler (Node `http`/Express-compatible) that reads and sets\n * the logger's level at runtime.\n *\n * - `GET` → `{ level, namespaceLevels }`\n * - `POST` → body `{ level?, namespaceLevels? }` applies them, returns the new state\n *\n * Custom levels are accepted too: any level the logger already knows passes\n * through. Unknown levels are rejected with 400 so a typo can't silently mute\n * logging.\n *\n * **SECURITY: this handler has NO authentication or authorization.** Anyone who\n * can reach it can silence logging or turn on verbose output. Always mount it\n * behind your own auth (and on an internal-only route/port), never on a public\n * listener.\n *\n * Mutating requests must send `Content-Type: application/json` (otherwise 415,\n * which also keeps cross-site form posts out) and a body of at most 16 KB\n * (otherwise 413).\n */\nexport function createLevelControlHandler(\n logger: ReconfigurableLogger,\n options: { allowedLevels?: string[] } = {}\n): (req: MinimalReq, res: MinimalRes) => void {\n const allowed =\n options.allowedLevels && options.allowedLevels.length > 0\n ? new Set(options.allowedLevels.map((l) => l.toLowerCase()))\n : VALID_LEVELS;\n\n const snapshot = (): { level: LogLevelString; namespaceLevels: NamespaceLevels } => ({\n level: logger.getLevel(),\n namespaceLevels: logger.getNamespaceLevels?.() ?? {},\n });\n\n const send = (res: MinimalRes, status: number, body: unknown): void => {\n res.statusCode = status;\n res.setHeader?.('Content-Type', 'application/json');\n res.end(JSON.stringify(body));\n };\n\n const applyBody = (res: MinimalRes, raw: string): void => {\n let parsed: { level?: unknown; namespaceLevels?: unknown };\n try {\n parsed = raw ? (JSON.parse(raw) as typeof parsed) : {};\n } catch {\n send(res, 400, { error: 'invalid JSON body' });\n return;\n }\n\n if (parsed.level !== undefined) {\n const lvl = String(parsed.level).toLowerCase();\n if (!allowed.has(lvl)) {\n send(res, 400, { error: `unknown level \"${parsed.level}\"`, allowed: [...allowed] });\n return;\n }\n logger.setLevel(lvl as LogLevelString);\n }\n\n if (parsed.namespaceLevels !== undefined) {\n if (\n typeof parsed.namespaceLevels !== 'object' ||\n parsed.namespaceLevels === null ||\n Array.isArray(parsed.namespaceLevels)\n ) {\n send(res, 400, { error: 'namespaceLevels must be an object' });\n return;\n }\n const nl = parsed.namespaceLevels as Record<string, unknown>;\n for (const [pat, lvl] of Object.entries(nl)) {\n if (!allowed.has(String(lvl).toLowerCase())) {\n send(res, 400, { error: `unknown level \"${String(lvl)}\" for namespace \"${pat}\"` });\n return;\n }\n }\n if (logger.setNamespaceLevels) {\n const coerced: NamespaceLevels = Object.fromEntries(\n Object.entries(nl).map(([pat, lvl]) => [pat, String(lvl).toLowerCase() as LogLevelString])\n );\n logger.setNamespaceLevels(coerced);\n } else {\n internalWarn('level control: logger does not support setNamespaceLevels — ignored');\n }\n }\n\n send(res, 200, snapshot());\n };\n\n return function levelControlHandler(req: MinimalReq, res: MinimalRes): void {\n const method = (req.method ?? 'GET').toUpperCase();\n\n if (method === 'GET') {\n send(res, 200, snapshot());\n return;\n }\n\n if (method === 'POST' || method === 'PUT' || method === 'PATCH') {\n if (!isJsonContentType(req)) {\n send(res, 415, { error: 'Content-Type must be application/json' });\n return;\n }\n const declared = Number(req.headers?.['content-length']);\n if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {\n send(res, 413, { error: 'request body too large' });\n return;\n }\n\n // Express already-parsed body (req.body) vs raw stream.\n const maybeBody = (req as unknown as { body?: unknown }).body;\n if (maybeBody !== undefined) {\n let text: string;\n if (typeof maybeBody === 'string') text = maybeBody;\n else if (Buffer.isBuffer(maybeBody)) text = maybeBody.toString('utf8');\n else text = JSON.stringify(maybeBody);\n if (Buffer.byteLength(text) > MAX_BODY_BYTES) {\n send(res, 413, { error: 'request body too large' });\n return;\n }\n applyBody(res, text);\n return;\n }\n if (typeof req.on === 'function') {\n let raw = '';\n let size = 0;\n let rejected = false;\n req.on('data', (chunk?: unknown) => {\n if (rejected) return;\n const piece = Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk ?? '');\n size += Buffer.byteLength(piece);\n if (size > MAX_BODY_BYTES) {\n rejected = true;\n raw = '';\n send(res, 413, { error: 'request body too large' });\n return;\n }\n raw += piece;\n });\n req.on('end', () => {\n if (!rejected) applyBody(res, raw);\n });\n return;\n }\n applyBody(res, '');\n return;\n }\n\n send(res, 405, { error: `method ${method} not allowed` });\n };\n}\n","/**\n * logixia — TypeScript typed log fields\n *\n * Solves the type-safety gap: standard `Record<string, unknown>` metadata gives\n * zero IDE autocomplete and lets typos slip silently into production logs.\n *\n * Two complementary utilities:\n *\n * 1. `createTypedLogger<TFields>()` — wraps any IBaseLogger so that the second\n * argument of every log method is constrained to `TFields` (a typed object).\n * Compile-time safety, zero runtime overhead.\n *\n * 2. `defineLogSchema<TFields>(schema)` — declares expected fields with optional\n * validators. In development (NODE_ENV !== 'production') every log call is\n * validated against the schema and a warning is emitted for missing required\n * fields or type mismatches.\n *\n * @example\n * ```ts\n * import { createTypedLogger, defineLogSchema } from 'logixia';\n *\n * interface OrderFields {\n * orderId: string;\n * userId: string;\n * amount?: number;\n * currency?: string;\n * }\n *\n * const schema = defineLogSchema<OrderFields>({\n * orderId: { type: 'string', required: true },\n * userId: { type: 'string', required: true },\n * amount: { type: 'number' },\n * currency: { type: 'string' },\n * });\n *\n * const orderLogger = createTypedLogger<OrderFields>(baseLogger, schema);\n * await orderLogger.info('Order created', { orderId: 'ord_123', userId: 'usr_456', amount: 99.99 });\n * // ^^^^ fully typed autocomplete ^^^^\n * ```\n */\n\nimport { internalWarn } from './internal-log';\n\n// ── Schema types ─────────────────────────────────────────────────────────────\n\nexport type LogFieldType = 'string' | 'number' | 'boolean' | 'object' | 'array';\n\nexport interface LogFieldDef {\n type: LogFieldType;\n /** Emit a warning when this field is missing from the log call. Default: false */\n required?: boolean;\n /** Custom validator — return a string to emit it as a warning message. */\n validate?: (value: unknown) => string | undefined;\n}\n\nexport type LogSchema<TFields extends object> = {\n [K in keyof TFields]: LogFieldDef;\n};\n\nexport interface CompiledSchema<TFields extends object> {\n readonly fields: LogSchema<TFields>;\n /**\n * Validate a payload against the schema.\n * Returns an array of warning strings (empty = pass).\n * Only runs in non-production environments.\n */\n validate(payload: Partial<TFields>): string[];\n}\n\n// The literal `process.env.NODE_ENV` must stay intact so bundlers can replace it;\n// on runtimes without `process` the ReferenceError is caught.\nfunction isProduction(): boolean {\n try {\n return process.env.NODE_ENV === 'production';\n } catch {\n return false;\n }\n}\n\n// ── defineLogSchema ──────────────────────────────────────────────────────────\n\n/**\n * Define a typed schema for a category of log entries.\n *\n * Call this once at module initialisation and pass it to `createTypedLogger`.\n * In development, every log call is validated against the schema.\n */\nexport function defineLogSchema<TFields extends object>(\n fields: LogSchema<TFields>\n): CompiledSchema<TFields> {\n return {\n fields,\n validate(payload: Partial<TFields>): string[] {\n if (isProduction()) return [];\n\n const warnings: string[] = [];\n\n for (const [key, def] of Object.entries(fields) as [keyof TFields & string, LogFieldDef][]) {\n const value = payload[key];\n\n if (def.required && (value === undefined || value === null)) {\n warnings.push(`Required field \"${key}\" is missing`);\n continue;\n }\n\n if (value !== undefined && value !== null) {\n const actualType = Array.isArray(value) ? 'array' : typeof value;\n if (actualType !== def.type) {\n warnings.push(`Field \"${key}\" expected type \"${def.type}\" but got \"${actualType}\"`);\n }\n\n if (def.validate) {\n const msg = def.validate(value);\n if (msg) warnings.push(`Field \"${key}\": ${msg}`);\n }\n }\n }\n\n return warnings;\n },\n };\n}\n\n// ── TypedLogger ──────────────────────────────────────────────────────────────\n\n/** IBaseLogger-compatible subset used by TypedLogger */\nexport interface LoggerLike {\n error(message: string | Error, data?: Record<string, unknown>): Promise<void>;\n warn(message: string, data?: Record<string, unknown>): Promise<void>;\n info(message: string, data?: Record<string, unknown>): Promise<void>;\n debug(message: string, data?: Record<string, unknown>): Promise<void>;\n verbose?(message: string, data?: Record<string, unknown>): Promise<void>;\n trace?(message: string, data?: Record<string, unknown>): Promise<void>;\n}\n\n/**\n * A logger whose metadata is typed to `TFields`.\n *\n * The `error` overload still accepts a plain `Error` object as the first arg\n * (with optional `TFields` data) so the typed logger remains a drop-in replacement.\n */\nexport interface TypedLogger<TFields extends object> {\n error(error: Error, data?: Partial<TFields>): Promise<void>;\n error(message: string, data?: Partial<TFields>): Promise<void>;\n warn(message: string, data?: Partial<TFields>): Promise<void>;\n info(message: string, data?: Partial<TFields>): Promise<void>;\n debug(message: string, data?: Partial<TFields>): Promise<void>;\n verbose(message: string, data?: Partial<TFields>): Promise<void>;\n trace(message: string, data?: Partial<TFields>): Promise<void>;\n /** Access the underlying untyped logger if needed. */\n readonly raw: LoggerLike;\n}\n\n/**\n * Wrap any logixia logger with a type-safe field interface.\n *\n * @param logger Any object that implements `IBaseLogger` (e.g. the result of `createLogger()`)\n * @param schema Optional schema for dev-time validation. Created with `defineLogSchema()`.\n */\nexport function createTypedLogger<TFields extends object>(\n logger: LoggerLike,\n schema?: CompiledSchema<TFields>\n): TypedLogger<TFields> {\n function withValidation(\n level: string,\n fn: (msg: string, data?: Record<string, unknown>) => Promise<void>,\n message: string,\n data?: Partial<TFields>\n ): Promise<void> {\n if (schema && data) {\n const warnings = schema.validate(data);\n for (const w of warnings) {\n internalWarn(`[logixia/schema] ${w} — level=${level} message=\"${message}\"`);\n }\n }\n return fn(message, data as Record<string, unknown> | undefined);\n }\n\n return {\n raw: logger,\n error(messageOrError: string | Error, data?: Partial<TFields>): Promise<void> {\n if (schema && data) {\n const warnings = schema.validate(data);\n const display = messageOrError instanceof Error ? messageOrError.message : messageOrError;\n for (const w of warnings) {\n internalWarn(`[logixia/schema] ${w} — level=error message=\"${display}\"`);\n }\n }\n return logger.error(messageOrError, data as Record<string, unknown> | undefined);\n },\n warn: (m, d) => withValidation('warn', logger.warn.bind(logger), m, d),\n info: (m, d) => withValidation('info', logger.info.bind(logger), m, d),\n debug: (m, d) => withValidation('debug', logger.debug.bind(logger), m, d),\n verbose: (m, d) =>\n withValidation('verbose', (logger.verbose ?? logger.debug).bind(logger), m, d),\n trace: (m, d) => withValidation('trace', (logger.trace ?? logger.debug).bind(logger), m, d),\n };\n}\n","/**\n * logixia — Canonical Log Lines / Wide Events.\n *\n * Emit ONE dense, structured event per unit of work (usually a request) instead\n * of scattering details across many narrow log lines. Fields are accumulated as\n * the request flows through middleware and business logic, then the whole event\n * is emitted ONCE — in a `finally`/teardown path so it fires even on errors.\n *\n * This is the \"canonical log line\" pattern (Stripe) / \"wide events\" /\n * \"Observability 2.0\" (Honeycomb): one pre-joined, queryable record per request,\n * so operators never JOIN across log lines during an incident. It composes with\n * logixia's existing trace correlation — when a trace is active, the event\n * carries `traceId`/`spanId`, making it OTel-friendly.\n *\n * @example Manual scope\n * ```ts\n * import { withWideEvent, addEventFields } from 'logixia';\n *\n * await withWideEvent(logger, { route: '/checkout' }, async () => {\n * addEventFields({ userId, planTier }); // from anywhere in the call tree\n * addEventFields({ dbQueries: 4, cacheHit });\n * // ...one wide event is emitted automatically when this callback settles,\n * // even if it throws.\n * });\n * ```\n *\n * @example Express middleware (auto-emit on response finish/close)\n * ```ts\n * import { wideEventMiddleware } from 'logixia';\n * app.use(wideEventMiddleware(logger));\n * app.get('/x', (req, res) => { addEventFields({ handled: 'x' }); res.json({}); });\n * ```\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { HttpRequestShape, HttpResponseShape } from './types/http-shapes';\nimport { buildNameSet, DEFAULT_REDACT_QUERY_PARAMS, redactUrlQuery } from './utils/sensitive-names';\nimport { getCurrentTraceId } from './utils/trace.utils';\n\n/** The accumulating event fields for the current scope. */\nexport type WideEventFields = Record<string, unknown>;\n\ninterface WideEventState {\n fields: WideEventFields;\n startMs: number;\n emitted: boolean;\n}\n\nconst _storage = new AsyncLocalStorage<WideEventState>();\n\n/** Minimal logger surface a wide event needs to emit itself. */\nexport interface WideEventLogger {\n logLevel(level: string, message: string, data?: Record<string, unknown>): Promise<void> | void;\n}\n\nexport interface WideEventOptions {\n /** Level the canonical event is logged at. Default: 'info'. */\n level?: string;\n /** Message for the canonical event line. Default: 'request'. */\n message?: string;\n /**\n * Attach `traceId` (and `spanId` when present) from the active trace context.\n * Default: true.\n */\n includeTrace?: boolean;\n /** Field name for the auto-computed duration in ms. Default: 'durationMs'. */\n durationField?: string;\n}\n\n/**\n * Merge fields into the wide event for the current async scope. No-op (with no\n * throw) when called outside a `withWideEvent` / middleware scope, so business\n * code can call it unconditionally.\n */\nexport function addEventFields(fields: WideEventFields): void {\n const state = _storage.getStore();\n if (!state || state.emitted) return;\n Object.assign(state.fields, fields);\n}\n\n/** Set a single field on the current wide event. */\nexport function setEventField(key: string, value: unknown): void {\n addEventFields({ [key]: value });\n}\n\n/** Read a shallow copy of the wide event accumulated so far, or undefined. */\nexport function getEventFields(): WideEventFields | undefined {\n const state = _storage.getStore();\n return state ? { ...state.fields } : undefined;\n}\n\nfunction emit(\n logger: WideEventLogger,\n state: WideEventState,\n options: WideEventOptions,\n extra?: WideEventFields\n): void {\n if (state.emitted) return;\n state.emitted = true;\n\n const level = options.level ?? 'info';\n const message = options.message ?? 'request';\n const durationField = options.durationField ?? 'durationMs';\n const includeTrace = options.includeTrace ?? true;\n\n const payload: WideEventFields = { ...state.fields };\n if (extra) Object.assign(payload, extra);\n payload[durationField] = Date.now() - state.startMs;\n\n if (includeTrace) {\n const traceId = getCurrentTraceId();\n if (traceId !== undefined && payload['traceId'] === undefined) payload['traceId'] = traceId;\n }\n\n // logLevel may be async (transport-backed); fire-and-forget so the wide-event\n // emit never blocks request teardown. Swallow rejections (the logger surfaces\n // its own transport errors) so this never becomes an unhandled rejection.\n const p = logger.logLevel(level, message, payload);\n if (p && typeof (p as Promise<void>).catch === 'function') {\n (p as Promise<void>).catch(() => {});\n }\n}\n\n/**\n * Run `callback` inside a wide-event scope. `addEventFields` calls anywhere in\n * the (async) call tree accumulate onto one event, which is emitted exactly once\n * when the callback settles — on success OR error (the canonical \"emit in\n * finally\" guarantee). On error, `error` + `errorMessage` fields are added.\n */\nexport async function withWideEvent<T>(\n logger: WideEventLogger,\n initialFields: WideEventFields,\n callback: () => Promise<T> | T,\n options: WideEventOptions = {}\n): Promise<T> {\n const state: WideEventState = {\n fields: { ...initialFields },\n startMs: Date.now(),\n emitted: false,\n };\n\n return _storage.run(state, async () => {\n try {\n const result = await callback();\n emit(logger, state, options);\n return result;\n } catch (error) {\n emit(logger, state, options, {\n error: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n });\n}\n\n// ── HTTP middleware ─────────────────────────────────────────────────────────\n\ntype MwReq = HttpRequestShape;\ntype MwRes = HttpResponseShape;\n\nexport interface WideEventMiddlewareOptions extends WideEventOptions {\n /** Derive extra initial fields from the request. */\n enrich?: (req: MwReq) => WideEventFields;\n /**\n * Additional query-string parameter names whose values are redacted from the\n * logged `url`. Merged with the defaults (token, access_token, refresh_token,\n * code, password, secret, api_key, apikey, key, signature, sig, auth).\n */\n redactQueryParams?: string[];\n /** Skip wide-event emission for a request (e.g. health checks). */\n skip?: (req: MwReq) => boolean;\n}\n\n/**\n * Express/Connect middleware that opens a wide-event scope per request and\n * emits ONE canonical event on response `finish`/`close` — even if the handler\n * throws or the client disconnects. Pre-populates method/url/ip; handlers add\n * more via `addEventFields`. The completion event includes `statusCode` and the\n * request duration.\n */\nexport function wideEventMiddleware(\n logger: WideEventLogger,\n options: WideEventMiddlewareOptions = {}\n): (req: MwReq, res: MwRes, next: () => void) => void {\n const redactParams = buildNameSet(DEFAULT_REDACT_QUERY_PARAMS, options.redactQueryParams);\n return function logixiaWideEventMiddleware(req: MwReq, res: MwRes, next: () => void): void {\n if (options.skip?.(req)) {\n next();\n return;\n }\n\n const rawUrl = req.originalUrl ?? req.url;\n const base: WideEventFields = {\n method: req.method,\n url: rawUrl === undefined ? undefined : redactUrlQuery(rawUrl, redactParams),\n ip: req.ip ?? req.socket?.remoteAddress,\n ...(options.enrich ? options.enrich(req) : {}),\n };\n\n const state: WideEventState = { fields: base, startMs: Date.now(), emitted: false };\n\n const finalize = (): void => {\n emit(logger, state, options, { statusCode: res.statusCode ?? 0 });\n };\n\n // Both 'finish' and 'close' may fire; emit() is idempotent (emitted guard),\n // so the canonical line is logged exactly once.\n res.once?.('finish', finalize);\n res.once?.('close', finalize);\n\n _storage.run(state, () => next());\n };\n}\n","/**\n * logixia — Metrics extraction → Prometheus\n *\n * Automatically extracts metrics from structured log fields and exposes them\n * in the Prometheus text exposition format (version 0.0.4).\n * No external dependency — the format is fully self-contained.\n *\n * Supported metric types:\n * - `counter` — incremented on each matching log entry\n * - `histogram` — observes a numeric payload field per entry\n * - `gauge` — tracks the most recent numeric value of a payload field\n *\n * Usage:\n * ```ts\n * import { createMetricsPlugin } from 'logixia';\n *\n * const metrics = createMetricsPlugin({\n * http_request_duration: {\n * type: 'histogram',\n * field: 'duration',\n * labels: ['method', 'statusCode'],\n * help: 'HTTP request duration in milliseconds',\n * },\n * error_count: {\n * type: 'counter',\n * levelFilter: 'error',\n * labels: ['context'],\n * help: 'Total error log entries',\n * },\n * active_connections: {\n * type: 'gauge',\n * field: 'connections',\n * help: 'Current active connection count',\n * },\n * });\n *\n * logger.use(metrics); // start collecting\n * app.get('/metrics', metrics.expressHandler()); // expose for Prometheus scrape\n * ```\n *\n * All metric names are automatically prefixed with `logixia_`.\n * Output follows https://prometheus.io/docs/instrumenting/exposition_formats/\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport type { LogixiaPlugin } from './plugin';\nimport type { LogEntry } from './types/index';\n\n// ── Metric config types ───────────────────────────────────────────────────────\n\n/**\n * Increment a counter on each matching log entry.\n *\n * @example Count every error entry, labelled by context:\n * ```ts\n * error_count: { type: 'counter', levelFilter: 'error', labels: ['context'] }\n * ```\n *\n * @example Count entries where payload.event === 'checkout':\n * ```ts\n * checkout_events: { type: 'counter', field: 'event', value: 'checkout' }\n * ```\n */\nexport interface CounterConfig {\n type: 'counter';\n /** Only increment when `entry.level` equals this value. Omit to count all entries. */\n levelFilter?: string;\n /**\n * Only increment when `entry.payload[field] === value`.\n * If omitted, every entry (matching `levelFilter`) is counted.\n */\n field?: string;\n value?: unknown;\n /** `entry.payload` fields used as Prometheus label dimensions. `'level'` is also valid. */\n labels?: string[];\n help?: string;\n}\n\n/**\n * Observe a numeric payload field and bucket it into a Prometheus histogram.\n *\n * @example Duration histogram labelled by HTTP method and status code:\n * ```ts\n * http_request_duration: {\n * type: 'histogram',\n * field: 'duration',\n * labels: ['method', 'statusCode'],\n * buckets: [10, 25, 50, 100, 250, 500, 1000],\n * }\n * ```\n */\nexport interface HistogramConfig {\n type: 'histogram';\n /** The `entry.payload` field containing the numeric value to observe. */\n field: string;\n /** `entry.payload` fields used as Prometheus label dimensions. */\n labels?: string[];\n help?: string;\n /**\n * Bucket upper bounds (inclusive). Sorted automatically.\n * Default: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000]\n */\n buckets?: number[];\n}\n\n/**\n * Track the most recent numeric value of a payload field as a gauge.\n *\n * @example Track live connection count:\n * ```ts\n * active_connections: { type: 'gauge', field: 'connections' }\n * ```\n */\nexport interface GaugeConfig {\n type: 'gauge';\n /** The `entry.payload` field containing the numeric value. */\n field: string;\n /** `entry.payload` fields used as Prometheus label dimensions. */\n labels?: string[];\n help?: string;\n}\n\nexport type MetricConfig = CounterConfig | HistogramConfig | GaugeConfig;\nexport type MetricsMap = Record<string, MetricConfig>;\n\n// ── Internal metric state ─────────────────────────────────────────────────────\n\ninterface CounterState {\n type: 'counter';\n values: Map<string, number>;\n}\n\ninterface HistogramState {\n type: 'histogram';\n buckets: number[];\n /** Parallel arrays; index = bucket index; last entry = +Inf cumulative count */\n counts: Map<string, number[]>;\n sums: Map<string, number>;\n observations: Map<string, number>;\n}\n\ninterface GaugeState {\n type: 'gauge';\n values: Map<string, number>;\n}\n\ntype MetricState = CounterState | HistogramState | GaugeState;\n\n// ── Defaults ──────────────────────────────────────────────────────────────────\n\nconst DEFAULT_BUCKETS: readonly number[] = [\n 1, 5, 10, 25, 50, 100, 250, 500, 1_000, 2_500, 5_000, 10_000,\n];\n\nconst MAX_LABEL_VALUE_LENGTH = 256;\nconst DEFAULT_MAX_LABEL_SETS = 1000;\n/** Label value used for the series that absorbs label sets beyond the cardinality cap. */\nexport const OVERFLOW_LABEL_VALUE = '__overflow__';\n\nexport interface MetricsPluginOptions {\n /**\n * Maximum number of distinct label sets tracked per metric. Once reached, new\n * label sets are folded into a single series whose label values are all\n * `__overflow__`, so payload-driven labels cannot grow memory or the scrape\n * output without bound.\n * @default 1000\n */\n maxLabelSets?: number;\n}\n\n// ── Label helpers ─────────────────────────────────────────────────────────────\n\nfunction buildLabelKey(config: MetricConfig, entry: LogEntry): string {\n const labelNames = config.labels ?? [];\n if (labelNames.length === 0) return '{}';\n const pairs: Record<string, string> = {};\n const payload = entry.payload ?? {};\n for (const name of labelNames) {\n const raw = name === 'level' ? entry.level : payload[name];\n // Sanitize the label NAME (the value is escaped at render time) so a label\n // like 'status code' can't emit unparseable Prometheus output.\n pairs[sanitizePromName(name)] =\n raw !== undefined && raw !== null ? String(raw).slice(0, MAX_LABEL_VALUE_LENGTH) : '';\n }\n return JSON.stringify(pairs);\n}\n\n/** Label key of the shared overflow series for a metric (all label values `__overflow__`). */\nfunction buildOverflowKey(config: MetricConfig): string {\n const names = config.labels ?? [];\n if (names.length === 0) return '{}';\n return JSON.stringify(\n Object.fromEntries(names.map((n) => [sanitizePromName(n), OVERFLOW_LABEL_VALUE]))\n );\n}\n\nfunction renderLabels(labelKey: string): string {\n if (labelKey === '{}') return '';\n const obj = JSON.parse(labelKey) as Record<string, string>;\n const parts = Object.entries(obj).map(([k, v]) => `${k}=\"${escapeLabel(v)}\"`);\n return `{${parts.join(',')}}`;\n}\n\nfunction escapeLabel(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n}\n\n/**\n * Coerce an arbitrary string into a valid Prometheus metric or label name\n * (`[a-zA-Z_][a-zA-Z0-9_]*`). Invalid characters become underscores and a\n * leading digit is prefixed with `_`. Without this, a user-supplied name like\n * `my-metric` or a label like `status code` would emit output Prometheus cannot\n * parse, breaking the ENTIRE scrape endpoint, not just that metric.\n */\nfunction sanitizePromName(name: string): string {\n let safe = name.replace(/\\W/g, '_');\n if (safe.length > 0 && /\\d/.test(safe[0]!)) safe = `_${safe}`;\n return safe.length > 0 ? safe : '_';\n}\n\n// ── MetricsPlugin ─────────────────────────────────────────────────────────────\n\n/**\n * A logixia plugin that extracts Prometheus-compatible metrics from log entries.\n *\n * Implements `LogixiaPlugin` — pass directly to `logger.use()`:\n * ```ts\n * const metrics = new MetricsPlugin({ ... });\n * logger.use(metrics);\n * ```\n *\n * Or use the `createMetricsPlugin()` factory (preferred):\n * ```ts\n * const metrics = createMetricsPlugin({ ... });\n * logger.use(metrics);\n * ```\n */\nexport class MetricsPlugin implements LogixiaPlugin {\n public readonly name = 'logixia-metrics';\n\n private readonly map: MetricsMap;\n private readonly metricState = new Map<string, MetricState>();\n private readonly overflowKeys = new Map<string, string>();\n\n private readonly maxLabelSets: number;\n\n constructor(map: MetricsMap, options: MetricsPluginOptions = {}) {\n this.map = map;\n const max = options.maxLabelSets;\n this.maxLabelSets =\n typeof max === 'number' && Number.isFinite(max) && max >= 1\n ? Math.floor(max)\n : DEFAULT_MAX_LABEL_SETS;\n this.initAllState();\n }\n\n // ── LogixiaPlugin lifecycle ────────────────────────────────────────────────\n\n onInit(): void {\n // State is initialised in the constructor; nothing extra needed here.\n }\n\n onLog(entry: LogEntry): LogEntry {\n const payload = entry.payload ?? {};\n\n for (const [rawName, config] of Object.entries(this.map)) {\n const state = this.metricState.get(rawName);\n if (!state) continue;\n\n const rawLabelKey = buildLabelKey(config, entry);\n const overflowKey = this.overflowKeys.get(rawName) ?? '{}';\n\n if (config.type === 'counter' && state.type === 'counter') {\n // Level filter\n if (config.levelFilter && entry.level !== config.levelFilter) continue;\n // Field/value filter\n if (config.field !== undefined && payload[config.field] !== config.value) continue;\n const labelKey = this.capLabelKey(state.values, rawLabelKey, overflowKey);\n state.values.set(labelKey, (state.values.get(labelKey) ?? 0) + 1);\n } else if (config.type === 'histogram' && state.type === 'histogram') {\n const raw = payload[config.field];\n if (raw === undefined || raw === null) continue;\n const val = Number(raw);\n if (Number.isNaN(val)) continue;\n const labelKey = this.capLabelKey(state.counts, rawLabelKey, overflowKey);\n\n // Initialise per-label arrays on first observation\n if (!state.counts.has(labelKey)) {\n state.counts.set(\n labelKey,\n Array.from<number>({ length: state.buckets.length + 1 }).fill(0)\n );\n state.sums.set(labelKey, 0);\n state.observations.set(labelKey, 0);\n }\n\n const bucketArr = state.counts.get(labelKey)!;\n for (let i = 0; i < state.buckets.length; i++) {\n if (val <= state.buckets[i]!) bucketArr[i]!++;\n }\n // The +Inf bucket (last slot) always increments\n bucketArr[state.buckets.length]!++;\n state.sums.set(labelKey, (state.sums.get(labelKey) ?? 0) + val);\n state.observations.set(labelKey, (state.observations.get(labelKey) ?? 0) + 1);\n } else if (config.type === 'gauge' && state.type === 'gauge') {\n const raw = payload[config.field];\n if (raw === undefined || raw === null) continue;\n const val = Number(raw);\n if (Number.isNaN(val)) continue;\n state.values.set(this.capLabelKey(state.values, rawLabelKey, overflowKey), val);\n }\n }\n\n // Always pass the entry through unchanged\n return entry;\n }\n\n // ── Output ─────────────────────────────────────────────────────────────────\n\n /**\n * Render all registered metrics in the Prometheus text exposition format\n * (version 0.0.4).\n *\n * All metric names are prefixed with `logixia_`.\n *\n * @example\n * ```\n * # HELP logixia_error_count Total error log entries\n * # TYPE logixia_error_count counter\n * logixia_error_count{context=\"OrderService\"} 7\n * ```\n */\n render(): string {\n const lines: string[] = [];\n\n for (const [rawName, config] of Object.entries(this.map)) {\n const metricName = `logixia_${sanitizePromName(rawName)}`;\n const state = this.metricState.get(rawName);\n if (!state) continue;\n\n const helpText = config.help ?? rawName.replace(/_/g, ' ');\n lines.push(`# HELP ${metricName} ${helpText}`);\n lines.push(`# TYPE ${metricName} ${config.type}`);\n\n if (state.type === 'counter') {\n if (state.values.size === 0) {\n lines.push(`${metricName} 0`);\n } else {\n for (const [labelKey, count] of state.values) {\n lines.push(`${metricName}${renderLabels(labelKey)} ${count}`);\n }\n }\n } else if (state.type === 'histogram') {\n for (const [labelKey, bucketCounts] of state.counts) {\n const labelSuffix = renderLabels(labelKey);\n const baseObj = labelKey === '{}' ? {} : (JSON.parse(labelKey) as Record<string, string>);\n\n // One line per finite bucket\n for (let i = 0; i < state.buckets.length; i++) {\n const leKey = JSON.stringify({ ...baseObj, le: String(state.buckets[i]) });\n lines.push(`${metricName}_bucket${renderLabels(leKey)} ${bucketCounts[i] ?? 0}`);\n }\n // +Inf bucket\n const infKey = JSON.stringify({ ...baseObj, le: '+Inf' });\n lines.push(\n `${metricName}_bucket${renderLabels(infKey)} ${bucketCounts[state.buckets.length] ?? 0}`\n );\n lines.push(`${metricName}_sum${labelSuffix} ${state.sums.get(labelKey) ?? 0}`);\n lines.push(`${metricName}_count${labelSuffix} ${state.observations.get(labelKey) ?? 0}`);\n }\n } else if (state.type === 'gauge') {\n if (state.values.size === 0) {\n lines.push(`${metricName} 0`);\n } else {\n for (const [labelKey, val] of state.values) {\n lines.push(`${metricName}${renderLabels(labelKey)} ${val}`);\n }\n }\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n }\n\n /**\n * Reset all metric counters and observations back to zero.\n * Useful between test runs or on a scheduled reset interval.\n */\n reset(): void {\n this.metricState.clear();\n this.initAllState();\n }\n\n /**\n * Express route handler — call `app.get('/metrics', metrics.expressHandler())`.\n *\n * @example\n * ```ts\n * import express from 'express';\n * const app = express();\n * app.get('/metrics', metrics.expressHandler());\n * ```\n */\n expressHandler(): (\n req: unknown,\n res: { set(k: string, v: string): unknown; end(body: string): void }\n ) => void {\n return (_req, res) => {\n res.set('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\n res.end(this.render());\n };\n }\n\n /**\n * Raw Node.js `http` server handler.\n * Responds to `GET /metrics` with the Prometheus text payload.\n *\n * @example Start a dedicated metrics server on the standard port:\n * ```ts\n * import http from 'node:http';\n * const server = http.createServer(metrics.httpHandler());\n * server.listen(9464); // Prometheus default port for custom exporters\n * ```\n */\n httpHandler(): (req: IncomingMessage, res: ServerResponse) => void {\n return (req, res) => {\n const isMetricsPath = req.url === '/metrics' || req.url === '/metrics/';\n if (!isMetricsPath) {\n res.writeHead(404).end('Not found');\n return;\n }\n const body = this.render();\n res.writeHead(200, {\n 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body),\n });\n res.end(body);\n };\n }\n\n // ── Private helpers ────────────────────────────────────────────────────────\n\n /**\n * Return `labelKey` when it is already tracked or there is room for it;\n * otherwise the shared overflow series key.\n */\n private capLabelKey(series: Map<string, unknown>, labelKey: string, overflowKey: string): string {\n if (series.has(labelKey) || series.size < this.maxLabelSets) return labelKey;\n return overflowKey;\n }\n\n private initAllState(): void {\n for (const [rawName, config] of Object.entries(this.map)) {\n this.initSingleState(rawName, config);\n }\n }\n\n private initSingleState(rawName: string, config: MetricConfig): void {\n this.overflowKeys.set(rawName, buildOverflowKey(config));\n if (config.type === 'counter') {\n this.metricState.set(rawName, { type: 'counter', values: new Map() });\n } else if (config.type === 'histogram') {\n const buckets = [...(config.buckets ?? DEFAULT_BUCKETS)].sort((a, b) => a - b);\n this.metricState.set(rawName, {\n type: 'histogram',\n buckets,\n counts: new Map(),\n sums: new Map(),\n observations: new Map(),\n });\n } else {\n this.metricState.set(rawName, { type: 'gauge', values: new Map() });\n }\n }\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Create a `MetricsPlugin` from a metrics map and return it ready for\n * `logger.use()`.\n *\n * @example\n * ```ts\n * import { createMetricsPlugin } from 'logixia';\n *\n * const metrics = createMetricsPlugin({\n * http_request_duration: {\n * type: 'histogram',\n * field: 'duration',\n * labels: ['method', 'statusCode'],\n * help: 'HTTP request duration in milliseconds',\n * },\n * error_count: {\n * type: 'counter',\n * levelFilter: 'error',\n * labels: ['context'],\n * help: 'Total error log entries',\n * },\n * });\n *\n * logger.use(metrics);\n * app.get('/metrics', metrics.expressHandler());\n * ```\n *\n * Pass `{ maxLabelSets }` to change the per-metric label cardinality cap (default 1000).\n */\nexport function createMetricsPlugin(\n map: MetricsMap,\n options?: MetricsPluginOptions\n): MetricsPlugin {\n return new MetricsPlugin(map, options);\n}\n","/**\n * Logixia - Advanced TypeScript Logger\n *\n * A comprehensive logging library with support for:\n * - Multiple output formats (console, file, JSON)\n * - Trace ID tracking\n * - Performance monitoring\n * - NestJS integration\n * - Customizable log levels and colors\n * - Intelligent log search and aggregation\n * - Natural language query processing\n * - Pattern recognition and anomaly detection\n */\n\nimport { DEFAULT_CONFIG } from './core/default-config';\nimport { createLogger as createLoggerFromCore, LogixiaLogger } from './core/logitron-logger';\n\n// Type exports\nexport * from './formatters';\nexport * from './types';\nexport type { ITransport, TransportConfig, TransportLogEntry } from './types/transport.types';\nexport * from './utils/error.utils';\nexport type { OtelBridgeOptions, OtelSpanContext } from './utils/otel';\nexport {\n disableOtelBridge,\n getActiveOtelContext,\n getOtelMetaFields,\n initOtelBridge,\n} from './utils/otel';\nexport { applyRedaction, redactObject } from './utils/redact.utils';\nexport type { LevelSignalOptions, ReconfigurableLogger } from './utils/runtime-control';\nexport { createLevelControlHandler, registerLevelSignal } from './utils/runtime-control';\nexport type { SafeStringifyOptions } from './utils/safe-stringify';\nexport { decycleValue, retrocycle, safeStringify, stringifyForLog } from './utils/safe-stringify';\nexport * from './utils/shutdown.utils';\nexport * from './utils/trace.utils';\nexport type {\n CompiledSchema,\n LogFieldDef,\n LogFieldType,\n LoggerLike,\n LogSchema,\n TypedLogger,\n} from './utils/typed-logger';\nexport { createTypedLogger, defineLogSchema } from './utils/typed-logger';\nexport type {\n WideEventFields,\n WideEventLogger,\n WideEventMiddlewareOptions,\n WideEventOptions,\n} from './wide-events';\nexport {\n addEventFields,\n getEventFields,\n setEventField,\n wideEventMiddleware,\n withWideEvent,\n} from './wide-events';\n\n// OTLP logs export transport (OpenTelemetry-native log emission)\nexport type { OtlpLogTransportConfig } from './transports/otlp.transport';\nexport { OtlpLogTransport, toOtelSeverity } from './transports/otlp.transport';\n\n// Chat webhook transports\nexport type { DiscordEmbed, DiscordTransportConfig } from './transports/discord.transport';\nexport { DiscordTransport } from './transports/discord.transport';\nexport type { SlackMessage, SlackTransportConfig } from './transports/slack.transport';\nexport { SlackTransport } from './transports/slack.transport';\n\n// Search module exports\nexport * from './search';\n\n// Context propagation (AsyncLocalStorage)\nexport type { LogContext } from './context/async-context';\nexport {\n createExpressContextMiddleware,\n createFastifyContextHook,\n LogixiaContext,\n} from './context/async-context';\n\n// Sampling stats (SamplingConfig is already exported via ./types)\nexport type { SamplingStats } from './utils/sampling.utils';\n\n// Plugin API (Feature 20)\nexport type { LogixiaPlugin } from './plugin';\nexport { globalPluginRegistry, PluginRegistry, usePlugin } from './plugin';\n\n// Exception system — typed LogixiaException + unified error response format\nexport type {\n BuildParams,\n ErrorDetail,\n LogixiaErrorResponse,\n LogixiaExceptionOptions,\n} from './exceptions';\nexport {\n ErrorResponseBuilder,\n generateRequestId,\n generateTraceId,\n isLogixiaException,\n LogixiaException,\n} from './exceptions';\n\n// Metrics extraction → Prometheus (Feature 21)\nexport type {\n CounterConfig,\n GaugeConfig,\n HistogramConfig,\n MetricConfig,\n MetricsMap,\n} from './metrics';\nexport type { MetricsPluginOptions } from './metrics';\nexport { createMetricsPlugin, MetricsPlugin, OVERFLOW_LABEL_VALUE } from './metrics';\n\n// Core exports\nexport { DEFAULT_CONFIG, LogixiaLogger };\n\n/**\n * Create a new Logixia logger instance with TypeScript support for custom levels\n * @param config - Logger configuration\n * @returns Typed logger instance\n */\nexport const createLogger = createLoggerFromCore;\n\n/**\n * Default logger instance\n */\nexport const logger = new LogixiaLogger(DEFAULT_CONFIG);\n\n/**\n * Export default configuration for reference\n */\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,12 +1,13 @@
1
- import { C as globalPluginRegistry, D as DEFAULT_LOG_LEVELS, E as DEFAULT_LOG_COLORS, O as LogLevel, S as PluginRegistry, T as DEFAULT_CONFIG, _ as getOtelMetaFields, a as isLogixiaException, b as normalizeError, c as _shutdownRegistrySize, d as registerForShutdown, f as resetShutdownHandlers, g as getActiveOtelContext, h as disableOtelBridge, i as LogixiaException, l as deregisterFromShutdown, m as redactObject, n as generateRequestId, o as LogixiaLogger, p as applyRedaction, r as generateTraceId, s as createLogger$1, t as ErrorResponseBuilder, u as flushOnExit, v as initOtelBridge, w as usePlugin, x as serializeError, y as isError } from "./builder-D70z6kjj.mjs";
2
- import { a as TRACE_CONTEXT_KEY, c as createTraceMiddleware, d as getTraceContextKey, f as runWithTraceId, h as traceStorage, i as MAX_INCOMING_ID_LENGTH, l as extractTraceId, m as setTraceId, o as TraceContext, p as sanitizeIncomingId, r as DEFAULT_TRACE_HEADERS, s as _setActiveContextKey, u as getCurrentTraceId } from "./request-trace-C_fvIDv4.mjs";
3
- import { n as createExpressContextMiddleware, r as createFastifyContextHook, t as LogixiaContext } from "./async-context-B05ArHgM.mjs";
4
- import { n as internalLog, r as internalWarn } from "./internal-log-uCSd1PMc.mjs";
1
+ import { C as DEFAULT_LOG_LEVELS, S as DEFAULT_LOG_COLORS, _ as serializeError, a as isLogixiaException, b as usePlugin, c as _shutdownRegistrySize, d as registerForShutdown, f as resetShutdownHandlers, g as normalizeError, h as isError, i as LogixiaException, l as deregisterFromShutdown, m as redactObject, n as generateRequestId, o as LogixiaLogger, p as applyRedaction, r as generateTraceId, s as createLogger$1, t as ErrorResponseBuilder, u as flushOnExit, v as PluginRegistry, w as LogLevel, x as DEFAULT_CONFIG, y as globalPluginRegistry } from "./builder-C_TgxEOW.mjs";
2
+ import { a as buildNameSet, l as assignOwn, n as DEFAULT_REDACT_QUERY_PARAMS, o as redactUrlQuery } from "./sensitive-names-o__1PUUR.mjs";
3
+ import { a as TRACE_CONTEXT_KEY, c as createTraceMiddleware, d as getTraceContextKey, f as runWithTraceId, h as traceStorage, i as MAX_INCOMING_ID_LENGTH, l as extractTraceId, m as setTraceId, o as TraceContext, p as sanitizeIncomingId, r as DEFAULT_TRACE_HEADERS, s as _setActiveContextKey, u as getCurrentTraceId } from "./request-trace-BgNykH9M.mjs";
4
+ import { n as createExpressContextMiddleware, r as createFastifyContextHook, t as LogixiaContext } from "./async-context-COuvmwsS.mjs";
5
+ import { n as internalLog, r as internalWarn } from "./internal-log-Cy5nF1ZL.mjs";
5
6
  import { t as safeToString } from "./coerce.utils-B_rEudCn.mjs";
6
- import { i as stringifyForLog, n as retrocycle, r as safeStringify, t as decycleValue } from "./safe-stringify-BMRl3EX3.mjs";
7
- import { d as stripControlChars } from "./transport.manager-eZ_EeC00.mjs";
8
- import { i as toOtelSeverity, n as DiscordTransport, r as OtlpLogTransport, t as SlackTransport } from "./slack.transport-Ce96JBDk.mjs";
9
- import { a as BasicSearchEngine, i as CorrelationEngine, n as PatternRecognitionEngine, o as BasicLogIndexer, r as NLPSearchEngine, t as SearchManager } from "./search-CWMVYC-R.mjs";
7
+ import { i as stringifyForLog, n as retrocycle, r as safeStringify, t as decycleValue } from "./safe-stringify--7gbe95n.mjs";
8
+ import { a as getActiveOtelContext, i as disableOtelBridge, o as getOtelMetaFields, s as initOtelBridge, v as stripControlChars } from "./otel-DOuwGPCd.mjs";
9
+ import { i as toOtelSeverity, n as DiscordTransport, r as OtlpLogTransport, t as SlackTransport } from "./slack.transport-CSj1j0_X.mjs";
10
+ import { a as BasicSearchEngine, i as CorrelationEngine, n as PatternRecognitionEngine, o as BasicLogIndexer, r as NLPSearchEngine, t as SearchManager } from "./search-DAXKE-P9.mjs";
10
11
  import { AsyncLocalStorage } from "node:async_hooks";
11
12
  // src/formatters/json.formatter.ts
12
13
  /**
@@ -56,18 +57,15 @@ var JsonFormatter = class {
56
57
  }
57
58
  serializePayload(payload) {
58
59
  const serialized = {};
59
- for (const [key, value] of Object.entries(payload)) {
60
- if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
61
- try {
62
- if (value instanceof Error) serialized[key] = serializeError(value);
63
- else if (value instanceof Date) serialized[key] = value.toISOString();
64
- else if (typeof value === "function") serialized[key] = "[Function]";
65
- else if (typeof value === "symbol") serialized[key] = value.toString();
66
- else if (value === void 0) serialized[key] = null;
67
- else serialized[key] = value;
68
- } catch {
69
- serialized[key] = "[Unserializable]";
70
- }
60
+ for (const [key, value] of Object.entries(payload)) try {
61
+ if (value instanceof Error) assignOwn(serialized, key, serializeError(value));
62
+ else if (value instanceof Date) assignOwn(serialized, key, value.toISOString());
63
+ else if (typeof value === "function") assignOwn(serialized, key, "[Function]");
64
+ else if (typeof value === "symbol") assignOwn(serialized, key, value.toString());
65
+ else if (value === void 0) assignOwn(serialized, key, null);
66
+ else assignOwn(serialized, key, value);
67
+ } catch {
68
+ assignOwn(serialized, key, "[Unserializable]");
71
69
  }
72
70
  return serialized;
73
71
  }
@@ -584,16 +582,18 @@ async function withWideEvent(logger, initialFields, callback, options = {}) {
584
582
  * request duration.
585
583
  */
586
584
  function wideEventMiddleware(logger, options = {}) {
585
+ const redactParams = buildNameSet(DEFAULT_REDACT_QUERY_PARAMS, options.redactQueryParams);
587
586
  return function logixiaWideEventMiddleware(req, res, next) {
588
587
  var _options$skip, _req$socket, _res$once, _res$once2;
589
588
  if ((_options$skip = options.skip) === null || _options$skip === void 0 ? void 0 : _options$skip.call(options, req)) {
590
589
  next();
591
590
  return;
592
591
  }
592
+ const rawUrl = req.originalUrl ?? req.url;
593
593
  const state = {
594
594
  fields: {
595
595
  method: req.method,
596
- url: req.originalUrl ?? req.url,
596
+ url: rawUrl === void 0 ? void 0 : redactUrlQuery(rawUrl, redactParams),
597
597
  ip: req.ip ?? ((_req$socket = req.socket) === null || _req$socket === void 0 ? void 0 : _req$socket.remoteAddress),
598
598
  ...options.enrich ? options.enrich(req) : {}
599
599
  },