brass-runtime 1.15.0 → 1.16.1

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 (209) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +673 -136
  3. package/dist/agent/cli/main.cjs +40 -35
  4. package/dist/agent/cli/main.js +9 -4
  5. package/dist/agent/cli/main.mjs +9 -4
  6. package/dist/agent/index.cjs +8 -4
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +7 -3
  9. package/dist/agent/index.mjs +7 -3
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/chunk-3AYM6WPJ.js +1629 -0
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3RG5ZIWI.js +10 -0
  15. package/dist/chunk-3Y2RIUMM.js +300 -0
  16. package/dist/{chunk-VEZNF5GZ.cjs → chunk-4ROBZFL6.cjs} +130 -126
  17. package/dist/{chunk-3QMOKAS5.js → chunk-52OB2ROS.js} +9 -5
  18. package/dist/chunk-52PPNNI4.cjs +416 -0
  19. package/dist/chunk-5EC274J5.cjs +2874 -0
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/chunk-5VRJNBLZ.mjs +2874 -0
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-74ZTY6CP.js +2871 -0
  25. package/dist/chunk-76YMRMH2.cjs +777 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-4NHES7VK.mjs → chunk-7JIJOVCT.js} +27 -13
  28. package/dist/chunk-A2OM6NEH.mjs +194 -0
  29. package/dist/chunk-AGR5B2BC.cjs +683 -0
  30. package/dist/chunk-AVNQLJ5V.js +777 -0
  31. package/dist/chunk-B33ICAKP.js +313 -0
  32. package/dist/{chunk-ELOOF35R.mjs → chunk-B5JD23U7.mjs} +1 -1
  33. package/dist/chunk-BABBZK4Y.js +2024 -0
  34. package/dist/chunk-C3MDXTRZ.js +354 -0
  35. package/dist/chunk-CIZFIMK5.js +2193 -0
  36. package/dist/chunk-CZIVE6NT.cjs +354 -0
  37. package/dist/chunk-DNFJLJMW.mjs +354 -0
  38. package/dist/chunk-DNFO2EIZ.mjs +777 -0
  39. package/dist/chunk-EJ6BPYVR.mjs +416 -0
  40. package/dist/chunk-ENKODRU3.cjs +2193 -0
  41. package/dist/chunk-EOC4UHBS.mjs +229 -0
  42. package/dist/{chunk-BMH5AV44.js → chunk-FH2X7BVP.js} +756 -440
  43. package/dist/{chunk-PPUXIH5R.js → chunk-FHQGHPMO.mjs} +27 -13
  44. package/dist/{chunk-TGIFUAK4.cjs → chunk-GLE2WY7Z.cjs} +951 -635
  45. package/dist/{chunk-BDF4AMWX.mjs → chunk-GYM3LLGS.mjs} +756 -440
  46. package/dist/chunk-HLWLMW2F.mjs +2024 -0
  47. package/dist/chunk-JF5WGYJJ.cjs +194 -0
  48. package/dist/chunk-KH4SYAOS.mjs +1629 -0
  49. package/dist/chunk-KN32XNTH.mjs +313 -0
  50. package/dist/chunk-KQLYONSE.cjs +2871 -0
  51. package/dist/{chunk-STVLQ3XD.cjs → chunk-KZJQ723N.cjs} +92 -78
  52. package/dist/chunk-L2SYFEBS.js +194 -0
  53. package/dist/chunk-L6VB5N7Q.cjs +104 -0
  54. package/dist/{chunk-K6M7MDZ4.mjs → chunk-MBEJI5HF.mjs} +9 -5
  55. package/dist/chunk-MIIYDLGM.js +2874 -0
  56. package/dist/chunk-MOO4L7F4.mjs +104 -0
  57. package/dist/chunk-MT3OWDPC.mjs +2193 -0
  58. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  59. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  60. package/dist/chunk-PD4EJTQC.cjs +229 -0
  61. package/dist/chunk-PWC3RBQE.mjs +300 -0
  62. package/dist/chunk-Q2I37RP3.cjs +1629 -0
  63. package/dist/chunk-RKGKFN2A.js +416 -0
  64. package/dist/{chunk-R3R2FVLG.cjs → chunk-SA6HUJVI.cjs} +5 -5
  65. package/dist/chunk-TRM4JUZQ.js +104 -0
  66. package/dist/chunk-UB4B6OFY.js +370 -0
  67. package/dist/{chunk-TO7IKXYT.js → chunk-UCUBNWM2.js} +1 -1
  68. package/dist/chunk-VN44DYYT.cjs +2024 -0
  69. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  70. package/dist/client-CZHU674n.d.ts +820 -0
  71. package/dist/core/index.cjs +198 -4
  72. package/dist/core/index.d.ts +311 -212
  73. package/dist/core/index.js +237 -43
  74. package/dist/core/index.mjs +237 -43
  75. package/dist/{effect-CMOQKX8y.d.ts → effect-DIUHZ9IN.d.ts} +195 -1
  76. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  77. package/dist/effectRunner-L4S7IPT3.js +8 -0
  78. package/dist/effectRunner-NNGG75QA.mjs +8 -0
  79. package/dist/http/index.cjs +1227 -2971
  80. package/dist/http/index.d.ts +826 -280
  81. package/dist/http/index.js +1089 -2833
  82. package/dist/http/index.mjs +1089 -2833
  83. package/dist/http/testing.cjs +161 -0
  84. package/dist/http/testing.d.ts +43 -0
  85. package/dist/http/testing.js +161 -0
  86. package/dist/http/testing.mjs +161 -0
  87. package/dist/index.cjs +486 -250
  88. package/dist/index.d.ts +87 -95
  89. package/dist/index.js +391 -155
  90. package/dist/index.mjs +391 -155
  91. package/dist/observability/index.cjs +162 -0
  92. package/dist/observability/index.d.ts +152 -0
  93. package/dist/observability/index.js +162 -0
  94. package/dist/observability/index.mjs +162 -0
  95. package/dist/perf/cli.cjs +401 -0
  96. package/dist/perf/cli.d.ts +1 -0
  97. package/dist/perf/cli.js +401 -0
  98. package/dist/perf/cli.mjs +401 -0
  99. package/dist/perf/index.cjs +141 -0
  100. package/dist/perf/index.d.ts +483 -0
  101. package/dist/perf/index.js +141 -0
  102. package/dist/perf/index.mjs +141 -0
  103. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  104. package/dist/schema/index.cjs +29 -0
  105. package/dist/schema/index.d.ts +179 -0
  106. package/dist/schema/index.js +29 -0
  107. package/dist/schema/index.mjs +29 -0
  108. package/dist/server-GJPg8ZSG.d.ts +675 -0
  109. package/dist/{stream-FQm9h4Mg.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  110. package/dist/tracer-Hwt1cl7h.d.ts +189 -0
  111. package/dist/tracing-DqbTKGcf.d.ts +148 -0
  112. package/docs/ARCHITECTURE.md +292 -0
  113. package/docs/README.md +63 -0
  114. package/docs/adr/0001-ai-context-pack.md +32 -0
  115. package/docs/agent-apply-mode.md +104 -0
  116. package/docs/agent-approvals.md +110 -0
  117. package/docs/agent-batch.md +185 -0
  118. package/docs/agent-boundaries.md +112 -0
  119. package/docs/agent-chat-sessions.md +160 -0
  120. package/docs/agent-ci.md +17 -0
  121. package/docs/agent-cli.md +405 -0
  122. package/docs/agent-config.md +480 -0
  123. package/docs/agent-context-discovery.md +159 -0
  124. package/docs/agent-copilot-like-dx.md +126 -0
  125. package/docs/agent-declarative-optimized-planning.md +138 -0
  126. package/docs/agent-dx.md +224 -0
  127. package/docs/agent-env-files.md +126 -0
  128. package/docs/agent-follow-up-context.md +43 -0
  129. package/docs/agent-global-usage.md +180 -0
  130. package/docs/agent-init.md +109 -0
  131. package/docs/agent-install-and-configure.md +516 -0
  132. package/docs/agent-language-workspace-ux.md +99 -0
  133. package/docs/agent-llm-adapters.md +123 -0
  134. package/docs/agent-local-install.md +190 -0
  135. package/docs/agent-local-tests.md +51 -0
  136. package/docs/agent-observability.md +155 -0
  137. package/docs/agent-patch-quality-loop.md +162 -0
  138. package/docs/agent-presets.md +22 -0
  139. package/docs/agent-project-commands.md +237 -0
  140. package/docs/agent-project-intelligence.md +156 -0
  141. package/docs/agent-redaction.md +18 -0
  142. package/docs/agent-release-readiness.md +76 -0
  143. package/docs/agent-rollback-safety.md +162 -0
  144. package/docs/agent-rollback.md +23 -0
  145. package/docs/agent-run-artifacts.md +16 -0
  146. package/docs/agent-vscode-auto-discovery.md +137 -0
  147. package/docs/agent-vscode-batch-runner.md +100 -0
  148. package/docs/agent-vscode-chat-layout.md +90 -0
  149. package/docs/agent-vscode-clean-install.md +147 -0
  150. package/docs/agent-vscode-code-actions.md +70 -0
  151. package/docs/agent-vscode-diff-preview.md +45 -0
  152. package/docs/agent-vscode-inline-assist.md +56 -0
  153. package/docs/agent-vscode-install.md +186 -0
  154. package/docs/agent-vscode-model-setup.md +97 -0
  155. package/docs/agent-vscode-patch-preview.md +92 -0
  156. package/docs/agent-vscode-problems.md +79 -0
  157. package/docs/agent-vscode-project-dashboard.md +106 -0
  158. package/docs/agent-vscode-run-history.md +92 -0
  159. package/docs/agent-vscode-ux.md +73 -0
  160. package/docs/ai/INVARIANTS.md +84 -0
  161. package/docs/ai/PROJECT_MAP.md +338 -0
  162. package/docs/ai/PUBLIC_API.md +336 -0
  163. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  164. package/docs/api-polish.md +37 -0
  165. package/docs/cancellation.md +162 -0
  166. package/docs/coverage.md +46 -0
  167. package/docs/getting-started.md +159 -0
  168. package/docs/guides/README.md +40 -0
  169. package/docs/guides/circuit-breaker.md +89 -0
  170. package/docs/guides/error-handling.md +91 -0
  171. package/docs/guides/getting-started.md +107 -0
  172. package/docs/guides/layers.md +189 -0
  173. package/docs/guides/metrics.md +101 -0
  174. package/docs/guides/resource-management.md +141 -0
  175. package/docs/guides/retry.md +215 -0
  176. package/docs/guides/semaphore.md +66 -0
  177. package/docs/guides/streams.md +117 -0
  178. package/docs/guides/supervisors.md +98 -0
  179. package/docs/guides/testing.md +162 -0
  180. package/docs/guides/tracing.md +71 -0
  181. package/docs/http-recipes.md +399 -0
  182. package/docs/http.md +749 -0
  183. package/docs/modules.md +285 -0
  184. package/docs/observability-collector-smoke.md +31 -0
  185. package/docs/observability-framework-examples.md +98 -0
  186. package/docs/observability.md +542 -0
  187. package/docs/otel-collector-smoke.yaml +27 -0
  188. package/docs/performance-profiler.md +199 -0
  189. package/docs/production-readiness.md +73 -0
  190. package/docs/recipes/README.md +12 -0
  191. package/docs/recipes/http-server.md +45 -0
  192. package/docs/recipes/layers.md +44 -0
  193. package/docs/recipes/performance.md +47 -0
  194. package/docs/recipes/runtime.md +41 -0
  195. package/docs/recipes/testing.md +41 -0
  196. package/docs/release.md +53 -0
  197. package/docs/wasm-bounded-queues.md +44 -0
  198. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  199. package/docs/wasm-fiber-engine.md +117 -0
  200. package/docs/wasm-scheduler-state-machine.md +122 -0
  201. package/docs/wasm-stream-chunks.md +54 -0
  202. package/package.json +48 -2
  203. package/dist/chunk-AR22SXML.js +0 -1043
  204. package/dist/chunk-BDYEENHT.js +0 -224
  205. package/dist/chunk-JFPU5GQI.mjs +0 -1043
  206. package/dist/chunk-MS34J5LY.cjs +0 -224
  207. package/dist/chunk-UMAZLXAB.mjs +0 -224
  208. package/dist/chunk-XPZNXSVN.cjs +0 -1043
  209. package/dist/tracing-DNT9jEbr.d.ts +0 -106
@@ -0,0 +1,777 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+ var _chunkENKODRU3cjs = require('./chunk-ENKODRU3.cjs');
13
+
14
+
15
+
16
+
17
+ var _chunk3LOYJFRRcjs = require('./chunk-3LOYJFRR.cjs');
18
+
19
+
20
+ var _chunkGLE2WY7Zcjs = require('./chunk-GLE2WY7Z.cjs');
21
+
22
+
23
+
24
+
25
+
26
+
27
+ var _chunkMVGUEJ5Zcjs = require('./chunk-MVGUEJ5Z.cjs');
28
+
29
+ // src/observability/http.ts
30
+ var DEFAULT_DURATION_BUCKETS = [1, 5, 10, 25, 50, 100, 250, 500, 1e3, 2500, 5e3, 1e4];
31
+ var POLICY_LABEL_NAMES = {
32
+ preset: "policy",
33
+ lane: "lane",
34
+ poolKey: "pool_key",
35
+ dedupKey: "dedup_key",
36
+ priority: "priority",
37
+ retry: "retry"
38
+ };
39
+ var HTTP_OBSERVABILITY_CONTRACT = Object.freeze({
40
+ metrics: Object.freeze({
41
+ requestsTotal: "brass_http_client_requests_total",
42
+ durationMs: "brass_http_client_duration_ms",
43
+ inFlight: "brass_http_client_in_flight",
44
+ adaptiveLimiterLimit: "brass_http_adaptive_limiter_limit",
45
+ adaptiveLimiterInFlight: "brass_http_adaptive_limiter_in_flight",
46
+ adaptiveLimiterQueueDepth: "brass_http_adaptive_limiter_queue_depth",
47
+ adaptiveLimiterStateCount: "brass_http_adaptive_limiter_state_count",
48
+ adaptiveLimiterUtilization: "brass_http_adaptive_limiter_utilization",
49
+ adaptiveLimiterErrorRate: "brass_http_adaptive_limiter_error_rate",
50
+ adaptiveLimiterRequestsPerSecond: "brass_http_adaptive_limiter_requests_per_second",
51
+ adaptiveLimiterCompletionsPerSecond: "brass_http_adaptive_limiter_completions_per_second",
52
+ adaptiveLimiterRejectionRate: "brass_http_adaptive_limiter_rejection_rate"
53
+ }),
54
+ labels: Object.freeze({
55
+ method: "method",
56
+ host: "host",
57
+ route: "route",
58
+ outcome: "outcome",
59
+ status: "status",
60
+ adaptiveLimiterKey: "key",
61
+ lane: "lane",
62
+ poolKey: "pool_key",
63
+ dedupKey: "dedup_key",
64
+ priority: "priority",
65
+ retry: "retry",
66
+ policy: "policy"
67
+ }),
68
+ spanAttributes: Object.freeze({
69
+ method: "http.request.method",
70
+ url: "url.full",
71
+ route: "http.route",
72
+ host: "server.address",
73
+ durationMs: "http.duration_ms",
74
+ outcome: "http.outcome",
75
+ statusCode: "http.status_code",
76
+ retryable: "http.retryable",
77
+ policyLane: "http.request.policy.lane",
78
+ policyPreset: "http.request.policy.preset",
79
+ policyPoolKey: "http.request.policy.pool_key",
80
+ policyDedupKey: "http.request.policy.dedup_key",
81
+ policyPriority: "http.request.policy.priority",
82
+ policyRetry: "http.request.policy.retry"
83
+ }),
84
+ logMessages: Object.freeze({
85
+ request: "http.client.request",
86
+ response: "http.client.response",
87
+ error: "http.client.error"
88
+ }),
89
+ logFields: Object.freeze({
90
+ method: "method",
91
+ url: "url",
92
+ host: "host",
93
+ route: "route",
94
+ status: "status",
95
+ outcome: "outcome",
96
+ durationMs: "durationMs",
97
+ retryable: "retryable",
98
+ policy: "policy"
99
+ })
100
+ });
101
+ function withHttpObservability(options) {
102
+ if (!isObservabilityInstance(options)) {
103
+ _chunkENKODRU3cjs.validateHttpObservabilityOptions.call(void 0, _nullishCoalesce(options, () => ( {})));
104
+ }
105
+ const resolved = resolveHttpObservabilityOptions(options);
106
+ return (next) => {
107
+ return (req) => {
108
+ const run = _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
109
+ beginHttpObservation(req, resolved),
110
+ (state) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
111
+ logHttpRequest(req, resolved),
112
+ () => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
113
+ prepareHttpRequest(req, resolved),
114
+ (wireReq) => _chunkMVGUEJ5Zcjs.asyncFold.call(void 0,
115
+ next(wireReq),
116
+ (error) => {
117
+ const finish = state.finishWithError(error);
118
+ const adaptiveLimiterAttrs = observeAdaptiveLimiter(wireReq, next, resolved);
119
+ return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
120
+ _chunkENKODRU3cjs.spanEvent.call(void 0, "http.client.error", {
121
+ ...finish.spanAttributes,
122
+ ...adaptiveLimiterAttrs,
123
+ "error.type": error._tag
124
+ }),
125
+ () => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, logHttpError(req, error, finish, resolved), () => _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, error))
126
+ );
127
+ },
128
+ (res) => {
129
+ const finish = state.finishWithResponse(res);
130
+ const adaptiveLimiterAttrs = observeAdaptiveLimiter(wireReq, next, resolved);
131
+ return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
132
+ _chunkENKODRU3cjs.spanEvent.call(void 0, "http.client.response", {
133
+ ...finish.spanAttributes,
134
+ ...adaptiveLimiterAttrs
135
+ }),
136
+ () => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, logHttpResponse(req, res, finish, resolved), () => _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, res))
137
+ );
138
+ }
139
+ )
140
+ )
141
+ )
142
+ );
143
+ if (resolved.spans === false) return run;
144
+ return _chunkENKODRU3cjs.withSpan.call(void 0, spanName(req, resolved.spans), run, spanStartAttributes(req, resolved));
145
+ };
146
+ };
147
+ }
148
+ var makeHttpObservabilityMiddleware = withHttpObservability;
149
+ function beginHttpObservation(req, options) {
150
+ return _chunkMVGUEJ5Zcjs.asyncSync.call(void 0, () => {
151
+ const startedAt = options.clock();
152
+ let finished = false;
153
+ const inFlight = _optionalChain([options, 'access', _ => _.metrics, 'optionalAccess', _2 => _2.gauge, 'call', _3 => _3("brass_http_client_in_flight", requestBaseLabels(req, options))]);
154
+ _optionalChain([inFlight, 'optionalAccess', _4 => _4.increment, 'call', _5 => _5()]);
155
+ const finish = (outcome, status, extra = {}) => {
156
+ const durationMs = Math.max(0, options.clock() - startedAt);
157
+ const labels = requestFinishLabels(req, outcome, status, options);
158
+ if (!finished) {
159
+ finished = true;
160
+ if (inFlight && inFlight.value() > 0) inFlight.decrement();
161
+ _optionalChain([options, 'access', _6 => _6.metrics, 'optionalAccess', _7 => _7.counter, 'call', _8 => _8("brass_http_client_requests_total", labels), 'access', _9 => _9.increment, 'call', _10 => _10()]);
162
+ _optionalChain([options, 'access', _11 => _11.metrics, 'optionalAccess', _12 => _12.histogram, 'call', _13 => _13("brass_http_client_duration_ms", [..._nullishCoalesce(options.durationBuckets, () => ( DEFAULT_DURATION_BUCKETS))], labels), 'access', _14 => _14.observe, 'call', _15 => _15(durationMs, currentTraceExemplar(durationMs, startedAt + durationMs))]);
163
+ }
164
+ return {
165
+ durationMs,
166
+ outcome,
167
+ labels,
168
+ spanAttributes: {
169
+ "http.duration_ms": durationMs,
170
+ "http.outcome": outcome,
171
+ ...status ? { "http.status_code": Number(status) } : {},
172
+ ...status ? { "http.response.status_code": Number(status) } : {},
173
+ ...extra
174
+ }
175
+ };
176
+ };
177
+ const fiber = _chunkGLE2WY7Zcjs.getCurrentFiber.call(void 0, );
178
+ _optionalChain([fiber, 'optionalAccess', _16 => _16.addFinalizer, 'optionalCall', _17 => _17(() => {
179
+ finish("abort", void 0, { "http.cancelled": true });
180
+ })]);
181
+ return {
182
+ finishWithResponse: (res) => finish(httpStatusOutcome(res.status), String(res.status)),
183
+ finishWithError: (error) => {
184
+ const status = _chunk3LOYJFRRcjs.httpErrorStatus.call(void 0, error);
185
+ return finish(httpErrorOutcome(error), status !== void 0 ? String(status) : void 0, {
186
+ "error.type": error._tag,
187
+ "http.retryable": _chunk3LOYJFRRcjs.isRetryableHttpError.call(void 0, error)
188
+ });
189
+ }
190
+ };
191
+ });
192
+ }
193
+ function prepareHttpRequest(req, options) {
194
+ if (!options.injectTraceHeaders) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, req);
195
+ return _chunkMVGUEJ5Zcjs.asyncSync.call(void 0, () => injectCurrentTraceContext(req));
196
+ }
197
+ function logHttpRequest(req, options) {
198
+ const level = options.logs === false ? false : _nullishCoalesce(options.logs.requestLevel, () => ( false));
199
+ if (!level) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0);
200
+ return _chunkENKODRU3cjs.logEffect.call(void 0, level, "http.client.request", requestLogFields(req, options));
201
+ }
202
+ function logHttpResponse(req, res, finish, options) {
203
+ const configured = options.logs === false ? false : _nullishCoalesce(options.logs.responseLevel, () => ( false));
204
+ const level = configured || (finish.outcome === "error" ? options.logs !== false ? _nullishCoalesce(options.logs.errorLevel, () => ( "warn")) : false : false);
205
+ if (!level) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0);
206
+ return _chunkENKODRU3cjs.logEffect.call(void 0, level, "http.client.response", {
207
+ ...requestLogFields(req, options),
208
+ status: res.status,
209
+ statusText: res.statusText,
210
+ outcome: finish.outcome,
211
+ durationMs: finish.durationMs
212
+ });
213
+ }
214
+ function logHttpError(req, error, finish, options) {
215
+ const level = options.logs === false ? false : _nullishCoalesce(options.logs.errorLevel, () => ( "error"));
216
+ if (!level) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0);
217
+ const status = _chunk3LOYJFRRcjs.httpErrorStatus.call(void 0, error);
218
+ const statusText = httpErrorStatusText(error);
219
+ return _chunkENKODRU3cjs.logEffect.call(void 0, level, "http.client.error", {
220
+ ...requestLogFields(req, options),
221
+ outcome: finish.outcome,
222
+ durationMs: finish.durationMs,
223
+ ...status !== void 0 ? { status } : {},
224
+ ...statusText ? { statusText } : {},
225
+ retryable: _chunk3LOYJFRRcjs.isRetryableHttpError.call(void 0, error),
226
+ errorTag: error._tag,
227
+ message: httpErrorMessage(error)
228
+ });
229
+ }
230
+ function resolveHttpObservabilityOptions(options) {
231
+ const maybeObservability = isObservabilityInstance(options) ? options : void 0;
232
+ const raw = maybeObservability ? { metrics: maybeObservability.metrics } : options;
233
+ return {
234
+ metrics: _optionalChain([raw, 'optionalAccess', _18 => _18.metrics]) === false ? void 0 : _optionalChain([raw, 'optionalAccess', _19 => _19.metrics]),
235
+ logs: _nullishCoalesce(_optionalChain([raw, 'optionalAccess', _20 => _20.logs]), () => ( {})),
236
+ spans: _nullishCoalesce(_optionalChain([raw, 'optionalAccess', _21 => _21.spans]), () => ( {})),
237
+ adaptiveLimiter: resolveAdaptiveLimiterObservabilityOptions(_optionalChain([raw, 'optionalAccess', _22 => _22.adaptiveLimiter])),
238
+ policy: resolveHttpPolicyObservabilityOptions(_optionalChain([raw, 'optionalAccess', _23 => _23.policy])),
239
+ injectTraceHeaders: _nullishCoalesce(_optionalChain([raw, 'optionalAccess', _24 => _24.injectTraceHeaders]), () => ( true)),
240
+ includeHostLabel: _nullishCoalesce(_optionalChain([raw, 'optionalAccess', _25 => _25.includeHostLabel]), () => ( true)),
241
+ route: _optionalChain([raw, 'optionalAccess', _26 => _26.route]),
242
+ clock: _nullishCoalesce(_optionalChain([raw, 'optionalAccess', _27 => _27.clock]), () => ( Date.now)),
243
+ durationBuckets: _optionalChain([raw, 'optionalAccess', _28 => _28.durationBuckets])
244
+ };
245
+ }
246
+ function isObservabilityInstance(options) {
247
+ return Boolean(
248
+ options && typeof options === "object" && "eventBus" in options && "prometheus" in options
249
+ );
250
+ }
251
+ function resolveAdaptiveLimiterObservabilityOptions(options) {
252
+ if (options === false) return { enabled: false, includeKeyLabel: false };
253
+ if (options === true || options === void 0) return { enabled: true, includeKeyLabel: false };
254
+ return {
255
+ enabled: _nullishCoalesce(options.enabled, () => ( true)),
256
+ includeKeyLabel: _nullishCoalesce(options.includeKeyLabel, () => ( false))
257
+ };
258
+ }
259
+ function resolveHttpPolicyObservabilityOptions(options) {
260
+ if (options === false) return { enabled: false, labelKeys: [] };
261
+ if (options === true || options === void 0) return { enabled: true, labelKeys: [] };
262
+ return {
263
+ enabled: _nullishCoalesce(options.enabled, () => ( true)),
264
+ labelKeys: _nullishCoalesce(options.labelKeys, () => ( []))
265
+ };
266
+ }
267
+ function observeAdaptiveLimiter(req, next, options) {
268
+ if (!options.adaptiveLimiter.enabled) return {};
269
+ const limiter = adaptiveLimiterOf(next);
270
+ if (!limiter || !options.metrics && options.spans === false) return {};
271
+ const stats = limiter.stats();
272
+ const labels = adaptiveLimiterLabels(req, stats, options);
273
+ setGauge(options.metrics, "brass_http_adaptive_limiter_limit", stats.limit, labels);
274
+ setGauge(options.metrics, "brass_http_adaptive_limiter_in_flight", stats.inFlight, labels);
275
+ setGauge(options.metrics, "brass_http_adaptive_limiter_queue_depth", stats.queueDepth, labels);
276
+ setGauge(options.metrics, "brass_http_adaptive_limiter_state_count", stats.stateCount, labels);
277
+ setGauge(options.metrics, "brass_http_adaptive_limiter_utilization", stats.utilization, labels);
278
+ setGauge(options.metrics, "brass_http_adaptive_limiter_error_rate", stats.errorRate, labels);
279
+ setGauge(options.metrics, "brass_http_adaptive_limiter_requests_per_second", stats.requestsPerSecond, labels);
280
+ setGauge(options.metrics, "brass_http_adaptive_limiter_completions_per_second", stats.completionsPerSecond, labels);
281
+ setGauge(options.metrics, "brass_http_adaptive_limiter_rejection_rate", stats.rejectionRate, labels);
282
+ return compactSpanAttributes({
283
+ "http.adaptive_limiter.limit": stats.limit,
284
+ "http.adaptive_limiter.in_flight": stats.inFlight,
285
+ "http.adaptive_limiter.queue_depth": stats.queueDepth,
286
+ "http.adaptive_limiter.state_count": stats.stateCount,
287
+ "http.adaptive_limiter.utilization": stats.utilization,
288
+ "http.adaptive_limiter.error_rate": stats.errorRate,
289
+ "http.adaptive_limiter.requests_per_second": stats.requestsPerSecond,
290
+ "http.adaptive_limiter.completions_per_second": stats.completionsPerSecond,
291
+ "http.adaptive_limiter.rejection_rate": stats.rejectionRate
292
+ });
293
+ }
294
+ function adaptiveLimiterOf(next) {
295
+ const limiter = next.adaptiveLimiter;
296
+ return limiter && typeof limiter.stats === "function" ? limiter : void 0;
297
+ }
298
+ function adaptiveLimiterLabels(req, stats, options) {
299
+ const key = options.adaptiveLimiter.includeKeyLabel ? inferAdaptiveLimiterKey(req, stats) : void 0;
300
+ return compactLabels({
301
+ ...requestBaseLabels(req, options),
302
+ key
303
+ });
304
+ }
305
+ function inferAdaptiveLimiterKey(req, stats) {
306
+ const policy = _chunk3LOYJFRRcjs.getHttpRequestPolicy.call(void 0, req);
307
+ if (policy.poolKey) return policy.poolKey;
308
+ const host = requestHost(req);
309
+ if (host) return host;
310
+ return _optionalChain([stats, 'access', _29 => _29.keys, 'optionalAccess', _30 => _30.length]) === 1 ? stats.keys[0] : void 0;
311
+ }
312
+ function setGauge(metrics, name, value, labels) {
313
+ if (!metrics || value === void 0 || !Number.isFinite(value)) return;
314
+ metrics.gauge(name, labels).set(value);
315
+ }
316
+ function compactSpanAttributes(attrs) {
317
+ const out = {};
318
+ for (const [key, value] of Object.entries(attrs)) {
319
+ if (typeof value === "number") {
320
+ if (Number.isFinite(value)) out[key] = value;
321
+ } else if (value !== void 0) {
322
+ out[key] = value;
323
+ }
324
+ }
325
+ return out;
326
+ }
327
+ function spanName(req, options) {
328
+ if (options && options.name) {
329
+ return typeof options.name === "function" ? options.name(req) : options.name;
330
+ }
331
+ return `HTTP ${req.method}`;
332
+ }
333
+ function spanStartAttributes(req, options) {
334
+ const spanOptions = options.spans === false ? {} : options.spans.attributes;
335
+ const custom = typeof spanOptions === "function" ? spanOptions(req) : _nullishCoalesce(spanOptions, () => ( {}));
336
+ const host = requestHost(req);
337
+ const route = requestRoute(req, options);
338
+ const sanitizedUrl = sanitizeUrl(req.url);
339
+ const scheme = urlScheme(req.url);
340
+ const path = urlPath(req.url);
341
+ return {
342
+ "span.kind": "client",
343
+ "http.method": req.method,
344
+ "http.request.method": req.method,
345
+ "http.url": sanitizedUrl,
346
+ "url.full": sanitizedUrl,
347
+ ...scheme ? { "url.scheme": scheme } : {},
348
+ ...path ? { "url.path": path } : {},
349
+ ...host ? { "server.address": host } : {},
350
+ ...route ? { "http.route": route } : {},
351
+ ...requestPolicySpanAttributes(req, options),
352
+ ...custom
353
+ };
354
+ }
355
+ function requestBaseLabels(req, options) {
356
+ const route = requestRoute(req, options);
357
+ return compactLabels({
358
+ method: req.method,
359
+ ...options.includeHostLabel ? { host: requestHost(req) } : {},
360
+ ...route ? { route } : {},
361
+ ...requestPolicyMetricLabels(req, options)
362
+ });
363
+ }
364
+ function requestFinishLabels(req, outcome, status, options) {
365
+ return {
366
+ ...requestBaseLabels(req, options),
367
+ outcome,
368
+ status: _nullishCoalesce(status, () => ( "none"))
369
+ };
370
+ }
371
+ function requestLogFields(req, options) {
372
+ const host = requestHost(req);
373
+ const route = requestRoute(req, options);
374
+ const policy = requestPolicyLogFields(req, options);
375
+ return {
376
+ method: req.method,
377
+ url: sanitizeUrl(req.url),
378
+ ...host ? { host } : {},
379
+ ...route ? { route } : {},
380
+ ...policy ? { policy } : {}
381
+ };
382
+ }
383
+ function requestPolicyLogFields(req, options) {
384
+ if (!options.policy.enabled) return void 0;
385
+ const policy = _chunk3LOYJFRRcjs.getHttpRequestPolicy.call(void 0, req);
386
+ const fields = {
387
+ ...policy.preset ? { preset: policy.preset } : {},
388
+ ...policy.lane ? { lane: policy.lane } : {},
389
+ ...policy.poolKey ? { poolKey: policy.poolKey } : {},
390
+ ...policy.dedupKey ? { dedupKey: policy.dedupKey } : {},
391
+ ...policy.priority !== void 0 ? { priority: policy.priority } : {},
392
+ ...policy.retry !== void 0 ? { retry: retryPolicyLogValue(policy.retry) } : {}
393
+ };
394
+ return Object.keys(fields).length > 0 ? fields : void 0;
395
+ }
396
+ function requestPolicySpanAttributes(req, options) {
397
+ if (!options.policy.enabled) return {};
398
+ const policy = _chunk3LOYJFRRcjs.getHttpRequestPolicy.call(void 0, req);
399
+ return {
400
+ ...compactSpanAttributes({
401
+ "http.request.policy.lane": policy.lane,
402
+ "http.request.policy.preset": policy.preset,
403
+ "http.request.policy.pool_key": policy.poolKey,
404
+ "http.request.policy.dedup_key": policy.dedupKey,
405
+ "http.request.policy.priority": policy.priority
406
+ }),
407
+ ...retryPolicySpanAttributes(policy.retry)
408
+ };
409
+ }
410
+ function requestPolicyMetricLabels(req, options) {
411
+ if (!options.policy.enabled || options.policy.labelKeys.length === 0) return {};
412
+ const policy = _chunk3LOYJFRRcjs.getHttpRequestPolicy.call(void 0, req);
413
+ const values = {
414
+ preset: policy.preset,
415
+ lane: policy.lane,
416
+ poolKey: policy.poolKey,
417
+ dedupKey: policy.dedupKey,
418
+ priority: policy.priority !== void 0 ? String(policy.priority) : void 0,
419
+ retry: retryPolicyMetricValue(policy.retry)
420
+ };
421
+ const labels = {};
422
+ for (const key of options.policy.labelKeys) {
423
+ labels[POLICY_LABEL_NAMES[key]] = values[key];
424
+ }
425
+ return compactLabels(labels);
426
+ }
427
+ function retryPolicyLogValue(retry) {
428
+ if (retry === false) return "disabled";
429
+ return {
430
+ mode: "override",
431
+ ...retry.maxRetries !== void 0 ? { maxRetries: retry.maxRetries } : {},
432
+ ...retry.baseDelayMs !== void 0 ? { baseDelayMs: retry.baseDelayMs } : {},
433
+ ...retry.maxDelayMs !== void 0 ? { maxDelayMs: retry.maxDelayMs } : {},
434
+ ...retry.schedule ? { schedule: "custom" } : {},
435
+ ...retry.retryOnStatus ? { retryOnStatus: "custom" } : {}
436
+ };
437
+ }
438
+ function retryPolicySpanAttributes(retry) {
439
+ if (retry === void 0) return {};
440
+ if (retry === false) return { "http.request.policy.retry": "disabled" };
441
+ return compactSpanAttributes({
442
+ "http.request.policy.retry": "override",
443
+ "http.request.policy.retry.max_retries": retry.maxRetries,
444
+ "http.request.policy.retry.base_delay_ms": retry.baseDelayMs,
445
+ "http.request.policy.retry.max_delay_ms": retry.maxDelayMs,
446
+ "http.request.policy.retry.custom_schedule": retry.schedule ? true : void 0,
447
+ "http.request.policy.retry.custom_status": retry.retryOnStatus ? true : void 0
448
+ });
449
+ }
450
+ function retryPolicyMetricValue(retry) {
451
+ if (retry === void 0) return void 0;
452
+ return retry === false ? "disabled" : "override";
453
+ }
454
+ function requestRoute(req, options) {
455
+ if (typeof options.route === "function") return options.route(req);
456
+ return options.route;
457
+ }
458
+ function httpStatusOutcome(status) {
459
+ return status >= 400 ? "error" : "success";
460
+ }
461
+ function httpErrorOutcome(error) {
462
+ switch (error._tag) {
463
+ case "Abort":
464
+ return "abort";
465
+ case "BadUrl":
466
+ return "bad_url";
467
+ case "FetchError":
468
+ return "fetch_error";
469
+ case "Timeout":
470
+ return "timeout";
471
+ case "PoolRejected":
472
+ return "pool_rejected";
473
+ case "PoolTimeout":
474
+ return "pool_timeout";
475
+ case "PoolClosed":
476
+ return "pool_closed";
477
+ case "BatchSplitError":
478
+ return "batch_split_error";
479
+ }
480
+ }
481
+ function httpErrorMessage(error) {
482
+ return "message" in error ? error.message : void 0;
483
+ }
484
+ function httpErrorStatusText(error) {
485
+ return error._tag === "FetchError" ? error.statusText : void 0;
486
+ }
487
+ function injectCurrentTraceContext(req) {
488
+ const fiber = _chunkGLE2WY7Zcjs.getCurrentFiber.call(void 0, );
489
+ const trace = _optionalChain([fiber, 'optionalAccess', _31 => _31.fiberContext, 'optionalAccess', _32 => _32.trace]);
490
+ if (!_optionalChain([trace, 'optionalAccess', _33 => _33.traceId]) || !_optionalChain([trace, 'optionalAccess', _34 => _34.spanId])) return req;
491
+ return {
492
+ ...req,
493
+ headers: _chunkENKODRU3cjs.injectTraceContext.call(void 0, req.headers, trace)
494
+ };
495
+ }
496
+ function currentTraceExemplar(value, timestamp) {
497
+ const fiber = _chunkGLE2WY7Zcjs.getCurrentFiber.call(void 0, );
498
+ return _chunkENKODRU3cjs.exemplarFromTraceContext.call(void 0, _optionalChain([fiber, 'optionalAccess', _35 => _35.fiberContext, 'optionalAccess', _36 => _36.trace]), value, timestamp);
499
+ }
500
+ function requestHost(req) {
501
+ if (!isAbsoluteUrl(req.url)) return void 0;
502
+ try {
503
+ return new URL(req.url).host;
504
+ } catch (e) {
505
+ return void 0;
506
+ }
507
+ }
508
+ function urlScheme(url) {
509
+ if (url.startsWith("https://")) return "https";
510
+ if (url.startsWith("http://")) return "http";
511
+ if (!isAbsoluteUrl(url)) return void 0;
512
+ try {
513
+ return new URL(url).protocol.replace(/:$/, "");
514
+ } catch (e2) {
515
+ return void 0;
516
+ }
517
+ }
518
+ function urlPath(url) {
519
+ if (!isAbsoluteUrl(url)) {
520
+ const path = stripQueryAndHash(url);
521
+ return path.startsWith("/") ? path : void 0;
522
+ }
523
+ try {
524
+ return new URL(url).pathname;
525
+ } catch (e3) {
526
+ return void 0;
527
+ }
528
+ }
529
+ function sanitizeUrl(url) {
530
+ if (!isAbsoluteUrl(url)) return stripQueryAndHash(url);
531
+ try {
532
+ const parsed = new URL(url);
533
+ parsed.search = "";
534
+ parsed.hash = "";
535
+ return parsed.toString();
536
+ } catch (e4) {
537
+ const [withoutHash] = url.split("#", 1);
538
+ const [withoutQuery] = withoutHash.split("?", 1);
539
+ return withoutQuery;
540
+ }
541
+ }
542
+ function isAbsoluteUrl(url) {
543
+ const schemeIdx = url.indexOf("://");
544
+ if (schemeIdx <= 0) return false;
545
+ const firstSlash = url.indexOf("/");
546
+ return firstSlash === -1 || schemeIdx < firstSlash;
547
+ }
548
+ function stripQueryAndHash(url) {
549
+ const hashIdx = url.indexOf("#");
550
+ const queryIdx = url.indexOf("?");
551
+ let end = url.length;
552
+ if (hashIdx >= 0) end = Math.min(end, hashIdx);
553
+ if (queryIdx >= 0) end = Math.min(end, queryIdx);
554
+ return url.slice(0, end);
555
+ }
556
+ function compactLabels(labels) {
557
+ const out = {};
558
+ for (const [key, value] of Object.entries(labels)) {
559
+ if (value !== void 0 && value !== "") out[key] = value;
560
+ }
561
+ return out;
562
+ }
563
+
564
+ // src/observability/adapters.ts
565
+ function makeFetchRequestObservabilityContext(observability, request, input = {}) {
566
+ return _chunkENKODRU3cjs.makeRequestObservabilityContext.call(void 0, observability, {
567
+ headers: request.headers,
568
+ method: request.method,
569
+ target: _chunkENKODRU3cjs.sanitizeHttpTarget.call(void 0, request.url),
570
+ route: _nullishCoalesce(input.route, () => ( _chunkENKODRU3cjs.normalizeHttpRoute.call(void 0, urlPathname(request.url)))),
571
+ ...input
572
+ });
573
+ }
574
+ function makeNodeRequestObservabilityContext(observability, request, input = {}) {
575
+ return _chunkENKODRU3cjs.makeRequestObservabilityContext.call(void 0, observability, {
576
+ headers: request.headers,
577
+ method: request.method,
578
+ target: _chunkENKODRU3cjs.sanitizeHttpTarget.call(void 0, request.url),
579
+ route: _nullishCoalesce(input.route, () => ( _chunkENKODRU3cjs.normalizeHttpRoute.call(void 0, request.url))),
580
+ ...input
581
+ });
582
+ }
583
+ function makeExpressRequestObservabilityContext(observability, request, input = {}) {
584
+ return _chunkENKODRU3cjs.makeRequestObservabilityContext.call(void 0, observability, {
585
+ headers: request.headers,
586
+ method: request.method,
587
+ target: _chunkENKODRU3cjs.sanitizeHttpTarget.call(void 0, _nullishCoalesce(request.originalUrl, () => ( request.url))),
588
+ route: _nullishCoalesce(_nullishCoalesce(input.route, () => ( _optionalChain([request, 'access', _37 => _37.route, 'optionalAccess', _38 => _38.path]))), () => ( _chunkENKODRU3cjs.normalizeHttpRoute.call(void 0, _nullishCoalesce(request.path, () => ( request.url))))),
589
+ ...input
590
+ });
591
+ }
592
+ function makeFastifyRequestObservabilityContext(observability, request, input = {}) {
593
+ return _chunkENKODRU3cjs.makeRequestObservabilityContext.call(void 0, observability, {
594
+ headers: request.headers,
595
+ method: request.method,
596
+ target: _chunkENKODRU3cjs.sanitizeHttpTarget.call(void 0, request.url),
597
+ route: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(input.route, () => ( _optionalChain([request, 'access', _39 => _39.routeOptions, 'optionalAccess', _40 => _40.url]))), () => ( request.routerPath)), () => ( _chunkENKODRU3cjs.normalizeHttpRoute.call(void 0, request.url))),
598
+ ...input
599
+ });
600
+ }
601
+ function withFetchRequestObservability(observability, handler, input = {}) {
602
+ return async (request) => handler(makeFetchRequestObservabilityContext(observability, request, input), request);
603
+ }
604
+ function withNodeRequestObservability(observability, handler, input = {}) {
605
+ return async (request) => handler(makeNodeRequestObservabilityContext(observability, request, input), request);
606
+ }
607
+ function urlPathname(url) {
608
+ if (!url) return void 0;
609
+ try {
610
+ return new URL(url, "http://local").pathname;
611
+ } catch (e5) {
612
+ return url;
613
+ }
614
+ }
615
+
616
+ // src/observability/config.ts
617
+ function makeNoopObservability() {
618
+ return _chunkENKODRU3cjs.makeObservability.call(void 0, {
619
+ metrics: false,
620
+ logs: false,
621
+ traces: false,
622
+ autoStart: false
623
+ });
624
+ }
625
+ function makeObservabilityPreset(preset, overrides = {}) {
626
+ if (preset === "disabled") return makeNoopObservability();
627
+ return _chunkENKODRU3cjs.makeObservability.call(void 0, mergeObservabilityOptions(observabilityOptionsForPreset(preset), overrides));
628
+ }
629
+ function makeObservabilityFromEnv(env = readProcessEnv(), overrides = {}) {
630
+ const preset = env.BRASS_OBSERVABILITY === "disabled" ? "disabled" : parsePreset(_nullishCoalesce(env.BRASS_OBSERVABILITY_PRESET, () => ( env.NODE_ENV)));
631
+ if (preset === "disabled") return makeNoopObservability();
632
+ return _chunkENKODRU3cjs.makeObservability.call(void 0, mergeObservabilityOptions(observabilityOptionsFromEnv(env, preset), overrides));
633
+ }
634
+ function observabilityOptionsForPreset(preset) {
635
+ switch (preset) {
636
+ case "production":
637
+ return {
638
+ logs: { minLevel: "info" },
639
+ sampling: { ratio: 1, respectRemoteSampled: true, forceSampleOnError: true },
640
+ redaction: {},
641
+ cardinality: { maxValuesPerLabel: 100 },
642
+ otlp: {
643
+ timeoutMs: 1e4,
644
+ retry: { attempts: 3, initialDelayMs: 100, maxDelayMs: 2e3 },
645
+ pipeline: {
646
+ maxQueueSize: 1e4,
647
+ batchSize: 512,
648
+ dropPolicy: "drop-oldest",
649
+ shutdownTimeoutMs: 1e4
650
+ }
651
+ },
652
+ flushIntervalMs: 1e4,
653
+ autoStart: true
654
+ };
655
+ case "test":
656
+ return {
657
+ logs: false,
658
+ sampling: 1,
659
+ redaction: {},
660
+ otlp: {
661
+ timeoutMs: 1e3,
662
+ retry: { attempts: 1 },
663
+ pipeline: { maxQueueSize: 1e3, batchSize: 256, shutdownTimeoutMs: 1e3 }
664
+ },
665
+ autoStart: false
666
+ };
667
+ case "development":
668
+ return {
669
+ logs: { minLevel: "debug" },
670
+ sampling: 1,
671
+ redaction: {},
672
+ cardinality: { maxValuesPerLabel: 100 },
673
+ autoStart: false
674
+ };
675
+ }
676
+ }
677
+ function observabilityOptionsFromEnv(env = readProcessEnv(), preset = parsePreset(_nullishCoalesce(env.BRASS_OBSERVABILITY_PRESET, () => ( env.NODE_ENV)))) {
678
+ const base = observabilityOptionsForPreset(preset);
679
+ const serviceName = _nullishCoalesce(env.OTEL_SERVICE_NAME, () => ( env.BRASS_SERVICE_NAME));
680
+ const serviceVersion = _nullishCoalesce(env.OTEL_SERVICE_VERSION, () => ( env.BRASS_SERVICE_VERSION));
681
+ const endpoint = trimTrailingSlash(env.OTEL_EXPORTER_OTLP_ENDPOINT);
682
+ const metricsUrl = _nullishCoalesce(env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, () => ( (endpoint ? `${endpoint}/v1/metrics` : void 0)));
683
+ const tracesUrl = _nullishCoalesce(env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, () => ( (endpoint ? `${endpoint}/v1/traces` : void 0)));
684
+ const logsUrl = _nullishCoalesce(env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, () => ( (endpoint ? `${endpoint}/v1/logs` : void 0)));
685
+ const headers = parseHeaders(env.OTEL_EXPORTER_OTLP_HEADERS);
686
+ const flushIntervalMs = parsePositiveInt(env.BRASS_OBSERVABILITY_FLUSH_INTERVAL_MS);
687
+ const timeoutMs = parsePositiveInt(env.BRASS_OBSERVABILITY_EXPORT_TIMEOUT_MS);
688
+ const sampleRatio = parseRatio(_nullishCoalesce(env.BRASS_TRACE_SAMPLE_RATIO, () => ( env.OTEL_TRACES_SAMPLER_ARG)));
689
+ const minLevel = env.BRASS_OBSERVABILITY_LOG_LEVEL;
690
+ const otlp = {
691
+ ..._nullishCoalesce(base.otlp, () => ( {})),
692
+ ...metricsUrl ? { metricsUrl } : {},
693
+ ...tracesUrl ? { tracesUrl } : {},
694
+ ...logsUrl ? { logsUrl } : {},
695
+ ...headers ? { headers } : {},
696
+ ...timeoutMs ? { timeoutMs } : {}
697
+ };
698
+ return mergeObservabilityOptions(base, {
699
+ ...serviceName ? { serviceName } : {},
700
+ ...serviceVersion ? { serviceVersion } : {},
701
+ ...Object.keys(otlp).length > 0 ? { otlp } : {},
702
+ ...flushIntervalMs ? { flushIntervalMs, autoStart: true } : {},
703
+ ...sampleRatio !== void 0 ? { sampling: { ratio: sampleRatio, respectRemoteSampled: true, forceSampleOnError: true } } : {},
704
+ ...minLevel === "debug" || minLevel === "info" || minLevel === "warn" || minLevel === "error" ? { logs: { minLevel } } : {}
705
+ });
706
+ }
707
+ function mergeObservabilityOptions(base, overrides) {
708
+ return {
709
+ ...base,
710
+ ...overrides,
711
+ metrics: _nullishCoalesce(overrides.metrics, () => ( base.metrics)),
712
+ logs: _nullishCoalesce(overrides.logs, () => ( base.logs)),
713
+ otlp: {
714
+ ..._nullishCoalesce(base.otlp, () => ( {})),
715
+ ..._nullishCoalesce(overrides.otlp, () => ( {})),
716
+ retry: _nullishCoalesce(_optionalChain([overrides, 'access', _41 => _41.otlp, 'optionalAccess', _42 => _42.retry]), () => ( _optionalChain([base, 'access', _43 => _43.otlp, 'optionalAccess', _44 => _44.retry]))),
717
+ pipeline: {
718
+ ..._nullishCoalesce(_optionalChain([base, 'access', _45 => _45.otlp, 'optionalAccess', _46 => _46.pipeline]), () => ( {})),
719
+ ..._nullishCoalesce(_optionalChain([overrides, 'access', _47 => _47.otlp, 'optionalAccess', _48 => _48.pipeline]), () => ( {}))
720
+ }
721
+ }
722
+ };
723
+ }
724
+ function parsePreset(value) {
725
+ if (value === "production" || value === "prod") return "production";
726
+ if (value === "test") return "test";
727
+ return "development";
728
+ }
729
+ function parseHeaders(value) {
730
+ if (!value) return void 0;
731
+ const out = {};
732
+ for (const part of value.split(",")) {
733
+ const index = part.indexOf("=");
734
+ if (index <= 0) continue;
735
+ const key = part.slice(0, index).trim();
736
+ const headerValue = part.slice(index + 1).trim();
737
+ if (key) out[key] = headerValue;
738
+ }
739
+ return Object.keys(out).length > 0 ? out : void 0;
740
+ }
741
+ function parsePositiveInt(value) {
742
+ if (!value) return void 0;
743
+ const parsed = Number.parseInt(value, 10);
744
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
745
+ }
746
+ function parseRatio(value) {
747
+ if (!value) return void 0;
748
+ const parsed = Number.parseFloat(value);
749
+ if (!Number.isFinite(parsed)) return void 0;
750
+ return Math.max(0, Math.min(1, parsed));
751
+ }
752
+ function trimTrailingSlash(value) {
753
+ if (!value) return void 0;
754
+ let out = value;
755
+ while (out.endsWith("/")) out = out.slice(0, -1);
756
+ return out || void 0;
757
+ }
758
+ function readProcessEnv() {
759
+ return typeof process !== "undefined" ? process.env : {};
760
+ }
761
+
762
+
763
+
764
+
765
+
766
+
767
+
768
+
769
+
770
+
771
+
772
+
773
+
774
+
775
+
776
+
777
+ exports.HTTP_OBSERVABILITY_CONTRACT = HTTP_OBSERVABILITY_CONTRACT; exports.withHttpObservability = withHttpObservability; exports.makeHttpObservabilityMiddleware = makeHttpObservabilityMiddleware; exports.makeFetchRequestObservabilityContext = makeFetchRequestObservabilityContext; exports.makeNodeRequestObservabilityContext = makeNodeRequestObservabilityContext; exports.makeExpressRequestObservabilityContext = makeExpressRequestObservabilityContext; exports.makeFastifyRequestObservabilityContext = makeFastifyRequestObservabilityContext; exports.withFetchRequestObservability = withFetchRequestObservability; exports.withNodeRequestObservability = withNodeRequestObservability; exports.makeNoopObservability = makeNoopObservability; exports.makeObservabilityPreset = makeObservabilityPreset; exports.makeObservabilityFromEnv = makeObservabilityFromEnv; exports.observabilityOptionsForPreset = observabilityOptionsForPreset; exports.observabilityOptionsFromEnv = observabilityOptionsFromEnv;