@veryfront/ext-observability-opentelemetry 0.1.1032 → 0.1.1035

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 (227) hide show
  1. package/esm/_dnt.polyfills.d.ts +7 -0
  2. package/esm/_dnt.polyfills.d.ts.map +1 -0
  3. package/esm/_dnt.polyfills.js +1 -0
  4. package/esm/deno.d.ts +440 -0
  5. package/esm/deno.d.ts.map +1 -0
  6. package/esm/deno.js +526 -0
  7. package/esm/{index.d.ts → extensions/ext-observability-opentelemetry/src/index.d.ts} +21 -0
  8. package/esm/extensions/ext-observability-opentelemetry/src/index.d.ts.map +1 -0
  9. package/esm/{index.js → extensions/ext-observability-opentelemetry/src/index.js} +255 -28
  10. package/esm/src/config/defaults.d.ts +39 -0
  11. package/esm/src/config/defaults.d.ts.map +1 -0
  12. package/esm/src/config/defaults.js +65 -0
  13. package/esm/src/errors/error-registry/agent.d.ts +18 -0
  14. package/esm/src/errors/error-registry/agent.d.ts.map +1 -0
  15. package/esm/src/errors/error-registry/agent.js +60 -0
  16. package/esm/src/errors/error-registry/boundary.d.ts +16 -0
  17. package/esm/src/errors/error-registry/boundary.d.ts.map +1 -0
  18. package/esm/src/errors/error-registry/boundary.js +52 -0
  19. package/esm/src/errors/error-registry/build.d.ts +20 -0
  20. package/esm/src/errors/error-registry/build.d.ts.map +1 -0
  21. package/esm/src/errors/error-registry/build.js +68 -0
  22. package/esm/src/errors/error-registry/config.d.ts +22 -0
  23. package/esm/src/errors/error-registry/config.d.ts.map +1 -0
  24. package/esm/src/errors/error-registry/config.js +70 -0
  25. package/esm/src/errors/error-registry/deploy.d.ts +12 -0
  26. package/esm/src/errors/error-registry/deploy.d.ts.map +1 -0
  27. package/esm/src/errors/error-registry/deploy.js +36 -0
  28. package/esm/src/errors/error-registry/dev.d.ts +14 -0
  29. package/esm/src/errors/error-registry/dev.d.ts.map +1 -0
  30. package/esm/src/errors/error-registry/dev.js +44 -0
  31. package/esm/src/errors/error-registry/general.d.ts +29 -0
  32. package/esm/src/errors/error-registry/general.d.ts.map +1 -0
  33. package/esm/src/errors/error-registry/general.js +92 -0
  34. package/esm/src/errors/error-registry/module.d.ts +16 -0
  35. package/esm/src/errors/error-registry/module.d.ts.map +1 -0
  36. package/esm/src/errors/error-registry/module.js +52 -0
  37. package/esm/src/errors/error-registry/route.d.ts +16 -0
  38. package/esm/src/errors/error-registry/route.d.ts.map +1 -0
  39. package/esm/src/errors/error-registry/route.js +52 -0
  40. package/esm/src/errors/error-registry/runtime.d.ts +18 -0
  41. package/esm/src/errors/error-registry/runtime.d.ts.map +1 -0
  42. package/esm/src/errors/error-registry/runtime.js +60 -0
  43. package/esm/src/errors/error-registry/server.d.ts +39 -0
  44. package/esm/src/errors/error-registry/server.d.ts.map +1 -0
  45. package/esm/src/errors/error-registry/server.js +129 -0
  46. package/esm/src/errors/error-registry-helpers.d.ts +6 -0
  47. package/esm/src/errors/error-registry-helpers.d.ts.map +1 -0
  48. package/esm/src/errors/error-registry-helpers.js +9 -0
  49. package/esm/src/errors/error-registry.d.ts +114 -0
  50. package/esm/src/errors/error-registry.d.ts.map +1 -0
  51. package/esm/src/errors/error-registry.js +60 -0
  52. package/esm/src/errors/types.d.ts +84 -0
  53. package/esm/src/errors/types.d.ts.map +1 -0
  54. package/esm/src/errors/types.js +69 -0
  55. package/esm/src/errors/veryfront-error.d.ts +149 -0
  56. package/esm/src/errors/veryfront-error.d.ts.map +1 -0
  57. package/esm/src/errors/veryfront-error.js +61 -0
  58. package/esm/src/modules/react-loader/ssr-module-loader/concurrency/semaphore.d.ts +13 -0
  59. package/esm/src/modules/react-loader/ssr-module-loader/concurrency/semaphore.d.ts.map +1 -0
  60. package/esm/src/modules/react-loader/ssr-module-loader/concurrency/semaphore.js +55 -0
  61. package/esm/src/observability/tracing/api-shim.d.ts +191 -0
  62. package/esm/src/observability/tracing/api-shim.d.ts.map +1 -0
  63. package/esm/src/observability/tracing/api-shim.js +281 -0
  64. package/esm/src/observability/tracing/otlp-setup.d.ts +61 -0
  65. package/esm/src/observability/tracing/otlp-setup.d.ts.map +1 -0
  66. package/esm/src/observability/tracing/otlp-setup.js +213 -0
  67. package/esm/src/observability/tracing/telemetry-env.d.ts +3 -0
  68. package/esm/src/observability/tracing/telemetry-env.d.ts.map +1 -0
  69. package/esm/src/observability/tracing/telemetry-env.js +10 -0
  70. package/esm/src/platform/adapters/base.d.ts +193 -0
  71. package/esm/src/platform/adapters/base.d.ts.map +1 -0
  72. package/esm/src/platform/adapters/base.js +15 -0
  73. package/esm/src/platform/compat/constants.d.ts +13 -0
  74. package/esm/src/platform/compat/constants.d.ts.map +1 -0
  75. package/esm/src/platform/compat/constants.js +12 -0
  76. package/esm/src/platform/compat/dynamic-import.d.ts +11 -0
  77. package/esm/src/platform/compat/dynamic-import.d.ts.map +1 -0
  78. package/esm/src/platform/compat/dynamic-import.js +10 -0
  79. package/esm/src/platform/compat/fs.d.ts +71 -0
  80. package/esm/src/platform/compat/fs.d.ts.map +1 -0
  81. package/esm/src/platform/compat/fs.js +277 -0
  82. package/esm/src/platform/compat/path/resolution.d.ts +6 -0
  83. package/esm/src/platform/compat/path/resolution.d.ts.map +1 -0
  84. package/esm/src/platform/compat/path/resolution.js +121 -0
  85. package/esm/src/platform/compat/path/runtime.d.ts +8 -0
  86. package/esm/src/platform/compat/path/runtime.d.ts.map +1 -0
  87. package/esm/src/platform/compat/path/runtime.js +20 -0
  88. package/esm/src/platform/compat/path/types.d.ts +22 -0
  89. package/esm/src/platform/compat/path/types.d.ts.map +1 -0
  90. package/esm/src/platform/compat/path/types.js +1 -0
  91. package/esm/src/platform/compat/process/command.d.ts +31 -0
  92. package/esm/src/platform/compat/process/command.d.ts.map +1 -0
  93. package/esm/src/platform/compat/process/command.js +194 -0
  94. package/esm/src/platform/compat/process/env.d.ts +35 -0
  95. package/esm/src/platform/compat/process/env.d.ts.map +1 -0
  96. package/esm/src/platform/compat/process/env.js +194 -0
  97. package/esm/src/platform/compat/process/lifecycle.d.ts +99 -0
  98. package/esm/src/platform/compat/process/lifecycle.d.ts.map +1 -0
  99. package/esm/src/platform/compat/process/lifecycle.js +327 -0
  100. package/esm/src/platform/compat/process/runtime-process.d.ts +10 -0
  101. package/esm/src/platform/compat/process/runtime-process.d.ts.map +1 -0
  102. package/esm/src/platform/compat/process/runtime-process.js +25 -0
  103. package/esm/src/platform/compat/process.d.ts +5 -0
  104. package/esm/src/platform/compat/process.d.ts.map +1 -0
  105. package/esm/src/platform/compat/process.js +4 -0
  106. package/esm/src/platform/compat/runtime.d.ts +51 -0
  107. package/esm/src/platform/compat/runtime.d.ts.map +1 -0
  108. package/esm/src/platform/compat/runtime.js +101 -0
  109. package/esm/src/transforms/import-rewriter/url-builder.d.ts +70 -0
  110. package/esm/src/transforms/import-rewriter/url-builder.d.ts.map +1 -0
  111. package/esm/src/transforms/import-rewriter/url-builder.js +152 -0
  112. package/esm/src/utils/base64url.d.ts +6 -0
  113. package/esm/src/utils/base64url.d.ts.map +1 -0
  114. package/esm/src/utils/base64url.js +12 -0
  115. package/esm/src/utils/bundle-manifest.d.ts +63 -0
  116. package/esm/src/utils/bundle-manifest.d.ts.map +1 -0
  117. package/esm/src/utils/bundle-manifest.js +96 -0
  118. package/esm/src/utils/constants/buffers.d.ts +24 -0
  119. package/esm/src/utils/constants/buffers.d.ts.map +1 -0
  120. package/esm/src/utils/constants/buffers.js +23 -0
  121. package/esm/src/utils/constants/build.d.ts +8 -0
  122. package/esm/src/utils/constants/build.d.ts.map +1 -0
  123. package/esm/src/utils/constants/build.js +7 -0
  124. package/esm/src/utils/constants/cache.d.ts +74 -0
  125. package/esm/src/utils/constants/cache.d.ts.map +1 -0
  126. package/esm/src/utils/constants/cache.js +133 -0
  127. package/esm/src/utils/constants/cdn.d.ts +29 -0
  128. package/esm/src/utils/constants/cdn.d.ts.map +1 -0
  129. package/esm/src/utils/constants/cdn.js +58 -0
  130. package/esm/src/utils/constants/crypto.d.ts +10 -0
  131. package/esm/src/utils/constants/crypto.d.ts.map +1 -0
  132. package/esm/src/utils/constants/crypto.js +9 -0
  133. package/esm/src/utils/constants/env.d.ts +16 -0
  134. package/esm/src/utils/constants/env.d.ts.map +1 -0
  135. package/esm/src/utils/constants/env.js +20 -0
  136. package/esm/src/utils/constants/hash.d.ts +5 -0
  137. package/esm/src/utils/constants/hash.d.ts.map +1 -0
  138. package/esm/src/utils/constants/hash.js +4 -0
  139. package/esm/src/utils/constants/hmr.d.ts +24 -0
  140. package/esm/src/utils/constants/hmr.d.ts.map +1 -0
  141. package/esm/src/utils/constants/hmr.js +26 -0
  142. package/esm/src/utils/constants/html.d.ts +13 -0
  143. package/esm/src/utils/constants/html.d.ts.map +1 -0
  144. package/esm/src/utils/constants/html.js +12 -0
  145. package/esm/src/utils/constants/http.d.ts +77 -0
  146. package/esm/src/utils/constants/http.d.ts.map +1 -0
  147. package/esm/src/utils/constants/http.js +76 -0
  148. package/esm/src/utils/constants/index.d.ts +23 -0
  149. package/esm/src/utils/constants/index.d.ts.map +1 -0
  150. package/esm/src/utils/constants/index.js +22 -0
  151. package/esm/src/utils/constants/limits.d.ts +27 -0
  152. package/esm/src/utils/constants/limits.d.ts.map +1 -0
  153. package/esm/src/utils/constants/limits.js +26 -0
  154. package/esm/src/utils/constants/metrics.d.ts +10 -0
  155. package/esm/src/utils/constants/metrics.d.ts.map +1 -0
  156. package/esm/src/utils/constants/metrics.js +34 -0
  157. package/esm/src/utils/constants/network.d.ts +23 -0
  158. package/esm/src/utils/constants/network.d.ts.map +1 -0
  159. package/esm/src/utils/constants/network.js +27 -0
  160. package/esm/src/utils/constants/priorities.d.ts +31 -0
  161. package/esm/src/utils/constants/priorities.d.ts.map +1 -0
  162. package/esm/src/utils/constants/priorities.js +30 -0
  163. package/esm/src/utils/constants/retry.d.ts +14 -0
  164. package/esm/src/utils/constants/retry.d.ts.map +1 -0
  165. package/esm/src/utils/constants/retry.js +13 -0
  166. package/esm/src/utils/constants/security.d.ts +16 -0
  167. package/esm/src/utils/constants/security.d.ts.map +1 -0
  168. package/esm/src/utils/constants/security.js +15 -0
  169. package/esm/src/utils/constants/server.d.ts +107 -0
  170. package/esm/src/utils/constants/server.d.ts.map +1 -0
  171. package/esm/src/utils/constants/server.js +120 -0
  172. package/esm/src/utils/feature-flags.d.ts +7 -0
  173. package/esm/src/utils/feature-flags.d.ts.map +1 -0
  174. package/esm/src/utils/feature-flags.js +8 -0
  175. package/esm/src/utils/hash-utils.d.ts +19 -0
  176. package/esm/src/utils/hash-utils.d.ts.map +1 -0
  177. package/esm/src/utils/hash-utils.js +42 -0
  178. package/esm/src/utils/import-lockfile.d.ts +52 -0
  179. package/esm/src/utils/import-lockfile.d.ts.map +1 -0
  180. package/esm/src/utils/import-lockfile.js +187 -0
  181. package/esm/src/utils/index.d.ts +27 -0
  182. package/esm/src/utils/index.d.ts.map +1 -0
  183. package/esm/src/utils/index.js +25 -0
  184. package/esm/src/utils/logger/components.d.ts +73 -0
  185. package/esm/src/utils/logger/components.d.ts.map +1 -0
  186. package/esm/src/utils/logger/components.js +81 -0
  187. package/esm/src/utils/logger/core.d.ts +73 -0
  188. package/esm/src/utils/logger/core.d.ts.map +1 -0
  189. package/esm/src/utils/logger/core.js +143 -0
  190. package/esm/src/utils/logger/index.d.ts +10 -0
  191. package/esm/src/utils/logger/index.d.ts.map +1 -0
  192. package/esm/src/utils/logger/index.js +9 -0
  193. package/esm/src/utils/logger/logger.d.ts +179 -0
  194. package/esm/src/utils/logger/logger.d.ts.map +1 -0
  195. package/esm/src/utils/logger/logger.js +490 -0
  196. package/esm/src/utils/logger/redact.d.ts +74 -0
  197. package/esm/src/utils/logger/redact.d.ts.map +1 -0
  198. package/esm/src/utils/logger/redact.js +294 -0
  199. package/esm/src/utils/logger/request-context.d.ts +27 -0
  200. package/esm/src/utils/logger/request-context.d.ts.map +1 -0
  201. package/esm/src/utils/logger/request-context.js +28 -0
  202. package/esm/src/utils/memoize.d.ts +19 -0
  203. package/esm/src/utils/memoize.d.ts.map +1 -0
  204. package/esm/src/utils/memoize.js +72 -0
  205. package/esm/src/utils/parallel.d.ts +25 -0
  206. package/esm/src/utils/parallel.d.ts.map +1 -0
  207. package/esm/src/utils/parallel.js +91 -0
  208. package/esm/src/utils/path-utils.d.ts +34 -0
  209. package/esm/src/utils/path-utils.d.ts.map +1 -0
  210. package/esm/src/utils/path-utils.js +138 -0
  211. package/esm/src/utils/perf-timer.d.ts +11 -0
  212. package/esm/src/utils/perf-timer.d.ts.map +1 -0
  213. package/esm/src/utils/perf-timer.js +114 -0
  214. package/esm/src/utils/platform.d.ts +9 -0
  215. package/esm/src/utils/platform.d.ts.map +1 -0
  216. package/esm/src/utils/platform.js +20 -0
  217. package/esm/src/utils/runtime-guards.d.ts +29 -0
  218. package/esm/src/utils/runtime-guards.d.ts.map +1 -0
  219. package/esm/src/utils/runtime-guards.js +23 -0
  220. package/esm/src/utils/version-constant.d.ts +3 -0
  221. package/esm/src/utils/version-constant.d.ts.map +1 -0
  222. package/esm/src/utils/version-constant.js +4 -0
  223. package/esm/src/utils/version.d.ts +17 -0
  224. package/esm/src/utils/version.d.ts.map +1 -0
  225. package/esm/src/utils/version.js +36 -0
  226. package/package.json +25 -7
  227. package/esm/index.d.ts.map +0 -1
@@ -0,0 +1,490 @@
1
+ import { getEnv, isStdoutTTY } from "../../platform/compat/process.js";
2
+ import { RUNTIME_VERSION } from "../version.js";
3
+ import { ANSI, colorize, formatContextText, formatTimestamp, LEVEL_COLORS, LEVEL_GLYPHS, padTag, serializeError, } from "./core.js";
4
+ import { redactSensitive, sanitizeSerializedError, sanitizeUrlCredentials } from "./redact.js";
5
+ export var LogLevel;
6
+ (function (LogLevel) {
7
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
8
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
9
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
10
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
11
+ })(LogLevel || (LogLevel = {}));
12
+ // ---- Config helpers (must be declared before the eager init below) ----
13
+ const LOG_LEVEL_MAP = {
14
+ DEBUG: LogLevel.DEBUG,
15
+ INFO: LogLevel.INFO,
16
+ WARN: LogLevel.WARN,
17
+ ERROR: LogLevel.ERROR,
18
+ };
19
+ function parseLogLevel(levelString) {
20
+ if (!levelString)
21
+ return undefined;
22
+ return LOG_LEVEL_MAP[levelString.toUpperCase()];
23
+ }
24
+ /**
25
+ * Determine the log level based on environment variables.
26
+ * Exported for testing purposes.
27
+ * @internal
28
+ */
29
+ export function getDefaultLevel(envLevel = getEnv("LOG_LEVEL"), debugFlag = getEnv("VERYFRONT_DEBUG")) {
30
+ const parsedLevel = parseLogLevel(envLevel);
31
+ if (parsedLevel !== undefined)
32
+ return parsedLevel;
33
+ if (debugFlag === "1" || debugFlag === "true")
34
+ return LogLevel.DEBUG;
35
+ return LogLevel.INFO;
36
+ }
37
+ /**
38
+ * Determine log format from environment.
39
+ * Defaults to JSON in production for Grafana compatibility.
40
+ */
41
+ function getDefaultFormat(envFormat = getEnv("LOG_FORMAT"), envMode = getEnv("NODE_ENV")) {
42
+ if (envFormat === "json" || envFormat === "text")
43
+ return envFormat;
44
+ return envMode === "production" ? "json" : "text";
45
+ }
46
+ // ---- Eager config resolution ----
47
+ /**
48
+ * Eagerly resolved at module load time so the config is captured from
49
+ * host process env vars BEFORE any per-request project env overlay is
50
+ * active. The project overlay blocks access to host env (for security),
51
+ * which would cause the logger to fall back to "text" format during SSR.
52
+ */
53
+ let loggerConfig = {
54
+ level: getDefaultLevel(),
55
+ format: getDefaultFormat(),
56
+ };
57
+ let logRecordEmitter = null;
58
+ /**
59
+ * Re-read logger configuration from environment variables.
60
+ * Call after loading .env files so the logger picks up any overrides.
61
+ */
62
+ export function refreshLoggerConfig() {
63
+ loggerConfig = {
64
+ level: getDefaultLevel(),
65
+ format: getDefaultFormat(),
66
+ };
67
+ }
68
+ /** @internal Alias kept for tests. */
69
+ export const __resetLoggerConfigForTests = refreshLoggerConfig;
70
+ /** Register a process-level structured log emitter, for example an OTel bridge. */
71
+ export function __registerLogRecordEmitter(emitter) {
72
+ logRecordEmitter = emitter;
73
+ }
74
+ /** Reset the process-level structured log emitter. Only intended for tests. */
75
+ export function __resetLogRecordEmitterForTests() {
76
+ logRecordEmitter = null;
77
+ }
78
+ function resolveLoggerConfig() {
79
+ return loggerConfig;
80
+ }
81
+ /**
82
+ * Extract context from variadic args.
83
+ * First object argument becomes context, errors are handled specially.
84
+ */
85
+ function extractContext(args) {
86
+ let context;
87
+ let error;
88
+ for (const arg of args) {
89
+ if (arg instanceof Error) {
90
+ error = serializeError(arg);
91
+ continue;
92
+ }
93
+ if (typeof arg === "object" && arg !== null && !Array.isArray(arg)) {
94
+ const contextArg = arg;
95
+ if (contextArg.error instanceof Error) {
96
+ const { error: contextError, ...rest } = contextArg;
97
+ error = serializeError(contextError);
98
+ if (Object.keys(rest).length > 0) {
99
+ context = { ...context, ...rest };
100
+ }
101
+ continue;
102
+ }
103
+ context = { ...context, ...contextArg };
104
+ }
105
+ }
106
+ return { context, error };
107
+ }
108
+ const TAG_COLORS = {
109
+ CLI: ANSI.green,
110
+ SERVER: ANSI.blue,
111
+ RENDERER: ANSI.magenta,
112
+ BUNDLER: ANSI.yellow,
113
+ AGENT: ANSI.cyan,
114
+ PROXY: ANSI.cyan,
115
+ VERYFRONT: ANSI.cyan,
116
+ };
117
+ function isTty() {
118
+ try {
119
+ return isStdoutTTY();
120
+ }
121
+ catch (_) {
122
+ /* expected: TTY detection may fail in restricted environments */
123
+ return false;
124
+ }
125
+ }
126
+ function shouldUseColor() {
127
+ const noColor = getEnv("NO_COLOR");
128
+ const forceColor = getEnv("FORCE_COLOR");
129
+ const logColor = getEnv("LOG_COLOR");
130
+ if (forceColor === "0" || logColor === "0")
131
+ return false;
132
+ if (noColor !== undefined)
133
+ return false;
134
+ if (getEnv("CI") !== undefined)
135
+ return false;
136
+ if (forceColor || logColor === "1" || logColor === "true")
137
+ return true;
138
+ return isTty();
139
+ }
140
+ function extractToEntryField(entry, context, key, coerce) {
141
+ if (!(key in context))
142
+ return;
143
+ entry[key] = coerce(context[key]);
144
+ delete context[key];
145
+ }
146
+ function extractAliasToEntryField(entry, context, sourceKey, targetKey, coerce) {
147
+ if (entry[targetKey] !== undefined || !(sourceKey in context))
148
+ return;
149
+ entry[targetKey] = coerce(context[sourceKey]);
150
+ delete context[sourceKey];
151
+ }
152
+ class ConsoleLogger {
153
+ prefix;
154
+ options;
155
+ boundContext;
156
+ componentName;
157
+ constructor(prefix, boundContext, componentName, options = {}) {
158
+ this.prefix = prefix;
159
+ this.options = options;
160
+ this.boundContext = boundContext ?? {};
161
+ this.componentName = componentName;
162
+ }
163
+ child(context) {
164
+ return new ConsoleLogger(this.prefix, { ...this.boundContext, ...context }, this.componentName, this.options);
165
+ }
166
+ component(name) {
167
+ return new ConsoleLogger(this.prefix, { ...this.boundContext }, name, this.options);
168
+ }
169
+ createEntry(level, message, args) {
170
+ const { context, error } = extractContext(args);
171
+ const mergedContext = { ...this.boundContext, ...context };
172
+ const entry = {
173
+ timestamp: new Date().toISOString(),
174
+ level,
175
+ service: this.prefix.toLowerCase(),
176
+ veryfrontVersion: RUNTIME_VERSION,
177
+ message,
178
+ };
179
+ if (this.componentName)
180
+ entry.component = this.componentName;
181
+ // Extract known fields to top level for easier Grafana filtering
182
+ extractToEntryField(entry, mergedContext, "requestId", (v) => String(v));
183
+ extractToEntryField(entry, mergedContext, "traceId", (v) => String(v));
184
+ extractToEntryField(entry, mergedContext, "spanId", (v) => String(v));
185
+ extractToEntryField(entry, mergedContext, "projectSlug", (v) => String(v));
186
+ extractToEntryField(entry, mergedContext, "durationMs", (v) => Number(v));
187
+ // Auto-inject trace context from OTel when not already set
188
+ if ((this.options.injectTraceContext ?? true) && traceContextGetter && !entry.traceId) {
189
+ const traceCtx = traceContextGetter();
190
+ if (traceCtx.traceId) {
191
+ entry.traceId = traceCtx.traceId;
192
+ entry.spanId = traceCtx.spanId;
193
+ }
194
+ }
195
+ // Extract standard snake_case fields for Loki filtering
196
+ extractToEntryField(entry, mergedContext, "request_id", (v) => String(v));
197
+ extractToEntryField(entry, mergedContext, "trace_id", (v) => String(v));
198
+ extractToEntryField(entry, mergedContext, "span_id", (v) => String(v));
199
+ extractToEntryField(entry, mergedContext, "project_slug", (v) => String(v));
200
+ // request_url / domain are URL-shaped and lifted out of mergedContext
201
+ // *before* redactSensitive runs, so they bypass the key-based redactor.
202
+ // Scrub embedded credentials (userinfo, ?access_token=, …) here (#1989).
203
+ extractToEntryField(entry, mergedContext, "request_url", (v) => sanitizeUrlCredentials(String(v)));
204
+ extractToEntryField(entry, mergedContext, "domain", (v) => sanitizeUrlCredentials(String(v)));
205
+ extractToEntryField(entry, mergedContext, "project_id", (v) => String(v));
206
+ extractToEntryField(entry, mergedContext, "release_id", (v) => String(v));
207
+ extractToEntryField(entry, mergedContext, "branch_id", (v) => String(v));
208
+ extractToEntryField(entry, mergedContext, "branch_name", (v) => String(v));
209
+ extractToEntryField(entry, mergedContext, "run_execution_id", (v) => String(v));
210
+ extractToEntryField(entry, mergedContext, "run_id", (v) => String(v));
211
+ extractToEntryField(entry, mergedContext, "agent_id", (v) => String(v));
212
+ extractToEntryField(entry, mergedContext, "thread_id", (v) => String(v));
213
+ extractToEntryField(entry, mergedContext, "schedule_id", (v) => String(v));
214
+ extractToEntryField(entry, mergedContext, "schedule_name", (v) => String(v));
215
+ extractToEntryField(entry, mergedContext, "tool_name", (v) => String(v));
216
+ extractToEntryField(entry, mergedContext, "tool_call_id", (v) => String(v));
217
+ extractToEntryField(entry, mergedContext, "batch_id", (v) => String(v));
218
+ extractToEntryField(entry, mergedContext, "run_target", (v) => String(v));
219
+ extractToEntryField(entry, mergedContext, "task", (v) => String(v));
220
+ extractToEntryField(entry, mergedContext, "event_kind", (v) => String(v));
221
+ extractToEntryField(entry, mergedContext, "user_visible", (v) => String(v));
222
+ extractToEntryField(entry, mergedContext, "duration_ms", (v) => Number(v));
223
+ extractToEntryField(entry, mergedContext, "user_id", (v) => String(v));
224
+ extractToEntryField(entry, mergedContext, "conversation_id", (v) => String(v));
225
+ // Also extract camelCase variants so callers can use either convention
226
+ extractToEntryField(entry, mergedContext, "userId", (v) => String(v));
227
+ extractToEntryField(entry, mergedContext, "conversationId", (v) => String(v));
228
+ extractAliasToEntryField(entry, mergedContext, "runId", "run_id", (v) => String(v));
229
+ extractAliasToEntryField(entry, mergedContext, "agentId", "agent_id", (v) => String(v));
230
+ extractAliasToEntryField(entry, mergedContext, "threadId", "thread_id", (v) => String(v));
231
+ extractAliasToEntryField(entry, mergedContext, "scheduleId", "schedule_id", (v) => String(v));
232
+ extractAliasToEntryField(entry, mergedContext, "scheduleName", "schedule_name", (v) => String(v));
233
+ extractAliasToEntryField(entry, mergedContext, "toolName", "tool_name", (v) => String(v));
234
+ extractAliasToEntryField(entry, mergedContext, "toolCallId", "tool_call_id", (v) => String(v));
235
+ // Emit snake_case aliases for camelCase fields (transition period)
236
+ if (entry.requestId && !entry.request_id)
237
+ entry.request_id = entry.requestId;
238
+ if (entry.traceId && !entry.trace_id)
239
+ entry.trace_id = entry.traceId;
240
+ if (entry.spanId && !entry.span_id)
241
+ entry.span_id = entry.spanId;
242
+ if (entry.projectSlug && !entry.project_slug)
243
+ entry.project_slug = entry.projectSlug;
244
+ if (entry.durationMs != null && entry.duration_ms == null)
245
+ entry.duration_ms = entry.durationMs;
246
+ if (entry.userId && !entry.user_id)
247
+ entry.user_id = entry.userId;
248
+ if (entry.conversationId && !entry.conversation_id) {
249
+ entry.conversation_id = entry.conversationId;
250
+ }
251
+ // Redact credential-like keys from the free-form context bag before
252
+ // serialization (the deliberate top-level fields above are already
253
+ // extracted out of mergedContext, so they are unaffected).
254
+ if (Object.keys(mergedContext).length > 0)
255
+ entry.context = redactSensitive(mergedContext);
256
+ // The serialized error (name/message/stack) bypasses the key-based
257
+ // redactor; scrub credentials embedded in its message/stack (DSNs, Mongo
258
+ // URIs, ?access_token= URLs, userinfo) before emission (#1989).
259
+ if (error)
260
+ entry.error = sanitizeSerializedError(error);
261
+ return entry;
262
+ }
263
+ formatJson(level, message, args) {
264
+ const entry = this.createEntry(level, message, args);
265
+ return JSON.stringify(entry);
266
+ }
267
+ formatTextLine(level, message, args) {
268
+ const { context, error } = extractContext(args);
269
+ const mergedContext = { ...this.boundContext, ...context };
270
+ const enableColor = shouldUseColor();
271
+ const timestamp = colorize(formatTimestamp(), ANSI.dim, enableColor);
272
+ const tag = colorize(padTag(this.prefix), TAG_COLORS[this.prefix] ?? ANSI.cyan, enableColor);
273
+ const glyph = colorize(LEVEL_GLYPHS[level], LEVEL_COLORS[level], enableColor);
274
+ const componentTag = this.componentName
275
+ ? ` ${colorize(`[${this.componentName}]`, ANSI.dim, enableColor)}`
276
+ : "";
277
+ const contextText = formatContextText(redactSensitive(mergedContext), sanitizeSerializedError(error), enableColor);
278
+ return `${timestamp} ${tag} ${glyph}${componentTag} ${message}${contextText}`;
279
+ }
280
+ log(level, logLevel, consoleFn, message, args) {
281
+ const { level: resolvedLevel, format: resolvedFormat } = resolveLoggerConfig();
282
+ if (resolvedLevel > logLevel)
283
+ return;
284
+ let entry;
285
+ const line = resolvedFormat === "json"
286
+ ? (() => {
287
+ entry = this.createEntry(level, message, args);
288
+ return JSON.stringify(entry);
289
+ })()
290
+ : this.formatTextLine(level, message, args);
291
+ if (logRecordEmitter) {
292
+ try {
293
+ logRecordEmitter(entry ?? this.createEntry(level, message, args));
294
+ }
295
+ catch (_) {
296
+ /* do not let telemetry export failures affect application logging */
297
+ }
298
+ }
299
+ consoleFn(line);
300
+ }
301
+ debug(message, ...args) {
302
+ this.log("debug", LogLevel.DEBUG, console.debug, message, args);
303
+ }
304
+ info(message, ...args) {
305
+ this.log("info", LogLevel.INFO, console.log, message, args);
306
+ }
307
+ warn(message, ...args) {
308
+ this.log("warn", LogLevel.WARN, console.warn, message, args);
309
+ }
310
+ error(message, ...args) {
311
+ this.log("error", LogLevel.ERROR, console.error, message, args);
312
+ }
313
+ async time(label, fn) {
314
+ const start = performance.now();
315
+ try {
316
+ const result = await fn();
317
+ const durationMs = performance.now() - start;
318
+ this.debug(`${label} completed`, { durationMs: Math.round(durationMs) });
319
+ return result;
320
+ }
321
+ catch (error) {
322
+ const durationMs = performance.now() - start;
323
+ this.error(`${label} failed`, { durationMs: Math.round(durationMs) }, error);
324
+ throw error;
325
+ }
326
+ }
327
+ }
328
+ function createLogger(prefix, options) {
329
+ return new ConsoleLogger(prefix, undefined, undefined, options);
330
+ }
331
+ // Base loggers without request context
332
+ const baseCliLogger = createLogger("CLI");
333
+ const baseServerLogger = createLogger("SERVER");
334
+ const baseRendererLogger = createLogger("RENDERER");
335
+ const baseBundlerLogger = createLogger("BUNDLER");
336
+ const baseAgentLogger = createLogger("AGENT");
337
+ const baseProxyLogger = createLogger("PROXY");
338
+ const baseLogger = createLogger("VERYFRONT");
339
+ const BASE_LOGGER_MAP = {
340
+ CLI: baseCliLogger,
341
+ SERVER: baseServerLogger,
342
+ RENDERER: baseRendererLogger,
343
+ BUNDLER: baseBundlerLogger,
344
+ AGENT: baseAgentLogger,
345
+ PROXY: baseProxyLogger,
346
+ };
347
+ /**
348
+ * Request context getter - set by request-context.ts to avoid circular imports.
349
+ * This pattern allows the logger module to be imported first without
350
+ * depending on request-context.ts.
351
+ */
352
+ let requestContextGetter = null;
353
+ /**
354
+ * Register the request context getter.
355
+ * Called by request-context.ts during module initialization.
356
+ * @internal
357
+ */
358
+ export function __registerRequestContextGetter(getter) {
359
+ requestContextGetter = getter;
360
+ }
361
+ /**
362
+ * Trace context getter - set by trace-bridge.ts to avoid importing OTel
363
+ * directly in the logger module. Returns the active span's traceId/spanId
364
+ * when OTel is initialized.
365
+ */
366
+ let traceContextGetter = null;
367
+ /**
368
+ * Register the trace context getter.
369
+ * Called by trace-bridge.ts after OTLP initialization.
370
+ * @internal
371
+ */
372
+ export function __registerTraceContextGetter(getter) {
373
+ traceContextGetter = getter;
374
+ }
375
+ /**
376
+ * Reset the trace context getter.
377
+ * Only intended for testing purposes.
378
+ * @internal
379
+ */
380
+ export function __resetTraceContextGetterForTests() {
381
+ traceContextGetter = null;
382
+ }
383
+ function withRequestLogger(base) {
384
+ const ctx = requestContextGetter?.();
385
+ return ctx?.logger ?? base;
386
+ }
387
+ /**
388
+ * Create a context-aware logger proxy that automatically uses
389
+ * request-scoped context from AsyncLocalStorage when available.
390
+ */
391
+ function createContextAwareLogger(base) {
392
+ return {
393
+ debug(message, ...args) {
394
+ withRequestLogger(base).debug(message, ...args);
395
+ },
396
+ info(message, ...args) {
397
+ withRequestLogger(base).info(message, ...args);
398
+ },
399
+ warn(message, ...args) {
400
+ withRequestLogger(base).warn(message, ...args);
401
+ },
402
+ error(message, ...args) {
403
+ withRequestLogger(base).error(message, ...args);
404
+ },
405
+ time(label, fn) {
406
+ return withRequestLogger(base).time(label, fn);
407
+ },
408
+ child(context) {
409
+ return withRequestLogger(base).child(context);
410
+ },
411
+ component(name) {
412
+ return createComponentAwareLogger(base, name);
413
+ },
414
+ };
415
+ }
416
+ /**
417
+ * Create a component-scoped logger that still defers request-context
418
+ * resolution to call time. This avoids eagerly binding to whatever
419
+ * context exists at module load — critical because component loggers
420
+ * are typically created as top-level constants.
421
+ */
422
+ function createComponentAwareLogger(base, componentName) {
423
+ return {
424
+ debug(message, ...args) {
425
+ withRequestLogger(base).component(componentName).debug(message, ...args);
426
+ },
427
+ info(message, ...args) {
428
+ withRequestLogger(base).component(componentName).info(message, ...args);
429
+ },
430
+ warn(message, ...args) {
431
+ withRequestLogger(base).component(componentName).warn(message, ...args);
432
+ },
433
+ error(message, ...args) {
434
+ withRequestLogger(base).component(componentName).error(message, ...args);
435
+ },
436
+ time(label, fn) {
437
+ return withRequestLogger(base).component(componentName).time(label, fn);
438
+ },
439
+ child(context) {
440
+ return withRequestLogger(base).component(componentName).child(context);
441
+ },
442
+ component(name) {
443
+ return createComponentAwareLogger(base, name);
444
+ },
445
+ };
446
+ }
447
+ // Context-aware loggers that automatically include request context
448
+ export const cliLogger = createContextAwareLogger(baseCliLogger);
449
+ /** Shared server logger value. */
450
+ export const serverLogger = createContextAwareLogger(baseServerLogger);
451
+ /** Shared renderer logger value. */
452
+ export const rendererLogger = createContextAwareLogger(baseRendererLogger);
453
+ /** Shared bundler logger value. */
454
+ export const bundlerLogger = createContextAwareLogger(baseBundlerLogger);
455
+ /** Shared agent logger value. */
456
+ export const agentLogger = createContextAwareLogger(baseAgentLogger);
457
+ export const proxyLogger = createContextAwareLogger(baseProxyLogger);
458
+ /** Shared logger value. */
459
+ export const logger = createContextAwareLogger(baseLogger);
460
+ /**
461
+ * Get the base logger without request context awareness.
462
+ * Use this when you need to create a request-scoped logger in middleware.
463
+ */
464
+ export function getBaseLogger(prefix, options) {
465
+ const resolvedPrefix = prefix.toUpperCase();
466
+ const validPrefix = resolvedPrefix in BASE_LOGGER_MAP ? resolvedPrefix : "VERYFRONT";
467
+ if (options?.injectTraceContext === false) {
468
+ return createLogger(validPrefix, options);
469
+ }
470
+ return BASE_LOGGER_MAP[resolvedPrefix] ?? baseLogger;
471
+ }
472
+ /**
473
+ * Create a logger for a specific request context.
474
+ * Useful for binding request-specific metadata to all logs.
475
+ */
476
+ export function createRequestLogger(baseLogger, requestContext) {
477
+ return baseLogger.child(requestContext);
478
+ }
479
+ /** Create run user logger. */
480
+ export function createRunUserLogger(baseLogger, runContext) {
481
+ return baseLogger.child({
482
+ project_id: runContext.projectId,
483
+ run_execution_id: runContext.runExecutionId,
484
+ ...(runContext.batchId ? { batch_id: runContext.batchId } : {}),
485
+ ...(runContext.runTarget ? { run_target: runContext.runTarget } : {}),
486
+ task: runContext.task,
487
+ event_kind: runContext.eventKind ?? "run_user_log",
488
+ user_visible: "true",
489
+ });
490
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Secret / credential redaction for structured log context.
3
+ *
4
+ * Defense-in-depth (#1989): the logger, the error-logging path, and the
5
+ * observability log buffer all accept arbitrary `context`/`data` objects from
6
+ * callers and serialize them to log sinks. There is no guarantee a caller
7
+ * never hands us a tokens object, an `Authorization` header bag, or a request
8
+ * body with a password field. This pass masks values whose *key* looks like a
9
+ * credential before serialization, so an accidental
10
+ * `logger.info("...", { authorization: token })` cannot leak the secret.
11
+ *
12
+ * Scope is intentionally key-based: we do not attempt to find secrets embedded
13
+ * in free-form message strings (too lossy). The deny-list errs toward
14
+ * over-redaction — masking a benign `tokenCount` is acceptable; leaking a real
15
+ * token is not. The traversal fails *closed*: on a cycle, depth overflow, or a
16
+ * throwing getter it returns {@link REDACTED} rather than risk emitting an
17
+ * unredacted object.
18
+ */
19
+ /** Replacement value substituted for any sensitive field. */
20
+ export declare const REDACTED = "[REDACTED]";
21
+ /**
22
+ * Whether a context key names a credential and should have its value masked.
23
+ *
24
+ * Uses substring matching on a normalized key, so `clientSecret`,
25
+ * `x-api-key`, and `refresh_token` all match while benign words that merely
26
+ * *contain* a pattern as a separate token (e.g. `author`) do not — `author`
27
+ * normalizes to `author`, which contains none of the patterns.
28
+ */
29
+ export declare function isSensitiveKey(key: string): boolean;
30
+ /**
31
+ * Returns a redacted deep copy of `context`. Any property whose key is
32
+ * {@link isSensitiveKey} has its value replaced with {@link REDACTED}; nested
33
+ * plain objects, class instances, and arrays are traversed. The input is never
34
+ * mutated, and the pass fails closed (returns {@link REDACTED}) on cycles,
35
+ * depth overflow, or a throwing getter.
36
+ */
37
+ export declare function redactSensitive<T>(context: T): T;
38
+ /**
39
+ * Strip credentials from URL-shaped strings so they can be safely emitted in
40
+ * free-form text (error messages, stacks, lifted `request_url` fields). Unlike
41
+ * {@link redactSensitive}, which is key-based, this scrubs secrets embedded in
42
+ * the *value* itself:
43
+ *
44
+ * - URL userinfo: `http://user:pass@host` → `http://user:[REDACTED]@host`
45
+ * - sensitive query params: `?access_token=abc` → `?access_token=[REDACTED]`
46
+ *
47
+ * It is intentionally tolerant: it operates on any string (a DSN, a Mongo URI,
48
+ * an axios error message containing a URL) via regex rather than requiring a
49
+ * parseable URL, so malformed or partial URLs in error text are still scrubbed.
50
+ * Non-URL strings pass through unchanged.
51
+ */
52
+ export declare function sanitizeUrlCredentials(input: string): string;
53
+ /**
54
+ * Return the URL form safe to attach to observability span attributes.
55
+ *
56
+ * Span attributes bypass the logger's structured redaction pass, so `http.url`
57
+ * must not include query strings, fragments, or URL userinfo. This intentionally
58
+ * strips every query parameter instead of selectively redacting credential-like
59
+ * names because cache keys and callback state can be sensitive even when the
60
+ * parameter name is not obviously a credential.
61
+ */
62
+ export declare function sanitizeUrlForSpan(input: string): string;
63
+ /**
64
+ * Apply {@link sanitizeUrlCredentials} to the `message` and `stack` of a
65
+ * serialized-error-shaped object, returning a new object. Used by the logger's
66
+ * JSON and text paths so errors carrying DSNs, Mongo URIs, or
67
+ * `?access_token=`-bearing URLs do not leak credentials (the serialized error
68
+ * bypasses the key-based redactor). Returns the input unchanged when falsy.
69
+ */
70
+ export declare function sanitizeSerializedError<T extends {
71
+ message?: unknown;
72
+ stack?: unknown;
73
+ } | undefined>(error: T): T;
74
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../../../src/src/utils/logger/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,6DAA6D;AAC7D,eAAO,MAAM,QAAQ,eAAe,CAAC;AA8CrC;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAcnD;AA6ED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAEhD;AA2BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA4B5D;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBxD;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,CAAC,SAAS;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EAC5D,KAAK,EAAE,CAAC,GAAG,CAAC,CAMb"}