@smthrs/observability 0.35.0 → 1.0.0-rc.12

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 (363) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +1 -1
  3. package/README.md +87 -0
  4. package/dist/cjs/BrowserOtel.d.ts +37 -0
  5. package/dist/cjs/BrowserOtel.d.ts.map +1 -0
  6. package/dist/cjs/BrowserOtel.js +47 -0
  7. package/dist/cjs/BrowserOtel.js.map +7 -0
  8. package/dist/cjs/Endpoint.d.ts +70 -0
  9. package/dist/cjs/Endpoint.d.ts.map +1 -0
  10. package/dist/cjs/Endpoint.js +85 -0
  11. package/dist/cjs/Endpoint.js.map +7 -0
  12. package/dist/cjs/JournalLogger.d.ts +232 -0
  13. package/dist/cjs/JournalLogger.d.ts.map +1 -0
  14. package/dist/cjs/JournalLogger.js +415 -0
  15. package/dist/cjs/JournalLogger.js.map +7 -0
  16. package/dist/cjs/Logger.d.ts +56 -0
  17. package/dist/cjs/Logger.d.ts.map +1 -0
  18. package/dist/cjs/Logger.js +72 -0
  19. package/dist/cjs/Logger.js.map +7 -0
  20. package/dist/cjs/Metric.d.ts +67 -0
  21. package/dist/cjs/Metric.d.ts.map +1 -0
  22. package/dist/cjs/Metric.js +68 -0
  23. package/dist/cjs/Metric.js.map +7 -0
  24. package/dist/cjs/NodeOtel.d.ts +42 -0
  25. package/dist/cjs/NodeOtel.d.ts.map +1 -0
  26. package/dist/cjs/NodeOtel.js +78 -0
  27. package/dist/cjs/NodeOtel.js.map +7 -0
  28. package/dist/cjs/Otel.d.ts +63 -0
  29. package/dist/cjs/Otel.d.ts.map +1 -0
  30. package/dist/cjs/Otel.js +75 -0
  31. package/dist/cjs/Otel.js.map +7 -0
  32. package/dist/cjs/Otlp.d.ts +203 -0
  33. package/dist/cjs/Otlp.d.ts.map +1 -0
  34. package/dist/cjs/Otlp.js +251 -0
  35. package/dist/cjs/Otlp.js.map +7 -0
  36. package/dist/cjs/Resource.d.ts +163 -0
  37. package/dist/cjs/Resource.d.ts.map +1 -0
  38. package/dist/cjs/Resource.js +186 -0
  39. package/dist/cjs/Resource.js.map +7 -0
  40. package/dist/cjs/index.d.ts +61 -0
  41. package/dist/cjs/index.d.ts.map +1 -0
  42. package/dist/cjs/index.js +47 -0
  43. package/dist/cjs/index.js.map +7 -0
  44. package/dist/cjs/internal/schemaIssuePath.d.ts +31 -0
  45. package/dist/cjs/internal/schemaIssuePath.d.ts.map +1 -0
  46. package/dist/cjs/internal/schemaIssuePath.js +49 -0
  47. package/dist/cjs/internal/schemaIssuePath.js.map +7 -0
  48. package/dist/cjs/package.json +1 -0
  49. package/dist/esm/BrowserOtel.d.ts +37 -0
  50. package/dist/esm/BrowserOtel.d.ts.map +1 -0
  51. package/dist/esm/BrowserOtel.js +24 -0
  52. package/dist/esm/BrowserOtel.js.map +1 -0
  53. package/dist/esm/Endpoint.d.ts +70 -0
  54. package/dist/esm/Endpoint.d.ts.map +1 -0
  55. package/dist/esm/Endpoint.js +110 -0
  56. package/dist/esm/Endpoint.js.map +1 -0
  57. package/dist/esm/JournalLogger.d.ts +232 -0
  58. package/dist/esm/JournalLogger.d.ts.map +1 -0
  59. package/dist/esm/JournalLogger.js +520 -0
  60. package/dist/esm/JournalLogger.js.map +1 -0
  61. package/dist/esm/Logger.d.ts +56 -0
  62. package/dist/esm/Logger.d.ts.map +1 -0
  63. package/dist/esm/Logger.js +61 -0
  64. package/dist/esm/Logger.js.map +1 -0
  65. package/dist/esm/Metric.d.ts +67 -0
  66. package/dist/esm/Metric.d.ts.map +1 -0
  67. package/dist/esm/Metric.js +80 -0
  68. package/dist/esm/Metric.js.map +1 -0
  69. package/dist/esm/NodeOtel.d.ts +42 -0
  70. package/dist/esm/NodeOtel.d.ts.map +1 -0
  71. package/dist/esm/NodeOtel.js +56 -0
  72. package/dist/esm/NodeOtel.js.map +1 -0
  73. package/dist/esm/Otel.d.ts +63 -0
  74. package/dist/esm/Otel.d.ts.map +1 -0
  75. package/dist/esm/Otel.js +52 -0
  76. package/dist/esm/Otel.js.map +1 -0
  77. package/dist/esm/Otlp.d.ts +203 -0
  78. package/dist/esm/Otlp.d.ts.map +1 -0
  79. package/dist/esm/Otlp.js +384 -0
  80. package/dist/esm/Otlp.js.map +1 -0
  81. package/dist/esm/Resource.d.ts +163 -0
  82. package/dist/esm/Resource.d.ts.map +1 -0
  83. package/dist/esm/Resource.js +238 -0
  84. package/dist/esm/Resource.js.map +1 -0
  85. package/dist/esm/index.d.ts +61 -0
  86. package/dist/esm/index.d.ts.map +1 -0
  87. package/dist/esm/index.js +61 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/internal/schemaIssuePath.d.ts +31 -0
  90. package/dist/esm/internal/schemaIssuePath.d.ts.map +1 -0
  91. package/dist/esm/internal/schemaIssuePath.js +59 -0
  92. package/dist/esm/internal/schemaIssuePath.js.map +1 -0
  93. package/docs/README.md +164 -0
  94. package/docs/api.md +780 -0
  95. package/docs/concepts/instrumentation-and-export.md +98 -0
  96. package/docs/concepts/layer-map.md +73 -0
  97. package/docs/concepts/validated-acquisition.md +106 -0
  98. package/docs/guides/export-to-a-collector.md +190 -0
  99. package/docs/guides/forward-logs-to-the-journal.md +226 -0
  100. package/docs/guides/install-a-logger.md +111 -0
  101. package/docs/guides/read-runtime-metrics.md +83 -0
  102. package/docs/guides/testing.md +134 -0
  103. package/docs/guides/wire-an-opentelemetry-sdk.md +226 -0
  104. package/docs/installation.md +102 -0
  105. package/docs/quickstart.md +145 -0
  106. package/docs/troubleshooting.md +168 -0
  107. package/package.json +221 -32
  108. package/src/BrowserOtel.ts +51 -0
  109. package/src/Endpoint.ts +131 -0
  110. package/src/JournalLogger.ts +635 -0
  111. package/src/Logger.ts +107 -0
  112. package/src/Metric.ts +88 -0
  113. package/src/NodeOtel.ts +90 -0
  114. package/src/Otel.ts +118 -0
  115. package/src/Otlp.ts +514 -0
  116. package/src/Resource.ts +325 -0
  117. package/src/index.ts +67 -0
  118. package/src/internal/schemaIssuePath.ts +65 -0
  119. package/docker-compose.otel.yml +0 -104
  120. package/grafana/dashboards/smithers-dashboard.json +0 -453
  121. package/grafana/provisioning/dashboards/dashboards.yml +0 -12
  122. package/grafana/provisioning/datasources/datasources.yml +0 -49
  123. package/loki/loki-config.yaml +0 -35
  124. package/otel-collector-config.yml +0 -38
  125. package/prometheus/prometheus.yml +0 -8
  126. package/src/MetricName.ts +0 -1
  127. package/src/MetricsServiceLive.js +0 -9
  128. package/src/README.md +0 -28
  129. package/src/ResolvedSmithersObservabilityOptions.ts +0 -12
  130. package/src/SmithersEvent.ts +0 -843
  131. package/src/SmithersLogFormat.ts +0 -1
  132. package/src/SmithersMetricDefinition.ts +0 -15
  133. package/src/SmithersMetricType.ts +0 -1
  134. package/src/SmithersMetricUnit.ts +0 -1
  135. package/src/SmithersObservability.js +0 -15
  136. package/src/SmithersObservabilityOptions.ts +0 -12
  137. package/src/SmithersObservabilityService.ts +0 -13
  138. package/src/_coreCorrelation/CorrelationContext.ts +0 -10
  139. package/src/_coreCorrelation/CorrelationContextLive.js +0 -11
  140. package/src/_coreCorrelation/CorrelationContextService.js +0 -15
  141. package/src/_coreCorrelation/CorrelationContextServiceShape.ts +0 -12
  142. package/src/_coreCorrelation/CorrelationPatch.ts +0 -3
  143. package/src/_coreCorrelation/README.md +0 -20
  144. package/src/_coreCorrelation/_correlationStorage.js +0 -4
  145. package/src/_coreCorrelation/correlationContextFiberRef.js +0 -5
  146. package/src/_coreCorrelation/correlationContextToLogAnnotations.js +0 -18
  147. package/src/_coreCorrelation/getCurrentCorrelationContext.js +0 -9
  148. package/src/_coreCorrelation/getCurrentCorrelationContextEffect.js +0 -11
  149. package/src/_coreCorrelation/index.js +0 -14
  150. package/src/_coreCorrelation/mergeCorrelationContext.js +0 -51
  151. package/src/_coreCorrelation/runWithCorrelationContext.js +0 -14
  152. package/src/_coreCorrelation/updateCurrentCorrelationContext.js +0 -17
  153. package/src/_coreCorrelation/withCorrelationContext.js +0 -38
  154. package/src/_coreCorrelation/withCurrentCorrelationContext.js +0 -11
  155. package/src/_coreMetrics.js +0 -14
  156. package/src/_coreMetricsShape.ts +0 -44
  157. package/src/_corePrometheus.js +0 -91
  158. package/src/_corePrometheusShape.ts +0 -11
  159. package/src/_coreTracing.js +0 -132
  160. package/src/_coreTracingShape.ts +0 -17
  161. package/src/_otelLogBuilders.js +0 -102
  162. package/src/_sessionFileResolvers.js +0 -164
  163. package/src/_smithersSpanAttributeAliases.js +0 -19
  164. package/src/_smithersTraceSpanStorage.js +0 -3
  165. package/src/_traceEventNormalizers.js +0 -499
  166. package/src/_traceRedaction.js +0 -162
  167. package/src/agentSessionEventToOtelLogRecord.js +0 -55
  168. package/src/agentTrace.ts +0 -144
  169. package/src/agentTraceCapabilities.js +0 -151
  170. package/src/annotateSmithersTrace.js +0 -11
  171. package/src/canonicalTraceEventToOtelLogRecord.js +0 -55
  172. package/src/correlation.js +0 -56
  173. package/src/createSmithersObservabilityLayer.js +0 -59
  174. package/src/createSmithersOtelLayer.js +0 -23
  175. package/src/createSmithersRuntimeLayer.js +0 -2
  176. package/src/detectAgentFamily.js +0 -26
  177. package/src/detectCaptureMode.js +0 -29
  178. package/src/emitOtelLogRecord.js +0 -19
  179. package/src/getCurrentSmithersTraceAnnotations.js +0 -14
  180. package/src/getCurrentSmithersTraceSpan.js +0 -7
  181. package/src/index.d.ts +0 -1392
  182. package/src/index.js +0 -137
  183. package/src/kindPhase.js +0 -17
  184. package/src/logging.js +0 -264
  185. package/src/makeSmithersSpanAttributes.js +0 -20
  186. package/src/metrics/README.md +0 -22
  187. package/src/metrics/SmithersMetricDefinition.ts +0 -17
  188. package/src/metrics/SmithersMetricType.ts +0 -1
  189. package/src/metrics/SmithersMetricUnit.ts +0 -1
  190. package/src/metrics/_asyncExternalWaitCounts.js +0 -4
  191. package/src/metrics/_buckets.js +0 -37
  192. package/src/metrics/_incrementGauge.js +0 -11
  193. package/src/metrics/_processStartMs.js +0 -1
  194. package/src/metrics/activeNodes.js +0 -2
  195. package/src/metrics/activeRuns.js +0 -2
  196. package/src/metrics/agentActionsTotal.js +0 -2
  197. package/src/metrics/agentDurationMs.js +0 -3
  198. package/src/metrics/agentErrorsTotal.js +0 -2
  199. package/src/metrics/agentEventsTotal.js +0 -2
  200. package/src/metrics/agentInvocationsTotal.js +0 -2
  201. package/src/metrics/agentRetriesTotal.js +0 -2
  202. package/src/metrics/agentSessionsTotal.js +0 -2
  203. package/src/metrics/agentTokensTotal.js +0 -2
  204. package/src/metrics/alertDeliveriesAttempted.js +0 -2
  205. package/src/metrics/alertDeliveriesSuppressed.js +0 -2
  206. package/src/metrics/alertsAcknowledgedTotal.js +0 -2
  207. package/src/metrics/alertsActive.js +0 -2
  208. package/src/metrics/alertsEscalatedTotal.js +0 -2
  209. package/src/metrics/alertsFiredTotal.js +0 -2
  210. package/src/metrics/alertsReopenedTotal.js +0 -2
  211. package/src/metrics/alertsResolvedTotal.js +0 -2
  212. package/src/metrics/alertsSilencedTotal.js +0 -2
  213. package/src/metrics/approvalPending.js +0 -2
  214. package/src/metrics/approvalWaitDuration.js +0 -5
  215. package/src/metrics/approvalsDenied.js +0 -2
  216. package/src/metrics/approvalsGranted.js +0 -2
  217. package/src/metrics/approvalsRequested.js +0 -2
  218. package/src/metrics/attemptDuration.js +0 -3
  219. package/src/metrics/attentionBacklog.js +0 -2
  220. package/src/metrics/cacheHits.js +0 -2
  221. package/src/metrics/cacheMisses.js +0 -2
  222. package/src/metrics/dbQueryDuration.js +0 -3
  223. package/src/metrics/dbRetries.js +0 -2
  224. package/src/metrics/dbTransactionDuration.js +0 -3
  225. package/src/metrics/dbTransactionRetries.js +0 -2
  226. package/src/metrics/dbTransactionRollbacks.js +0 -2
  227. package/src/metrics/devtoolsActiveSubscribers.js +0 -2
  228. package/src/metrics/devtoolsBackpressureDisconnectTotal.js +0 -2
  229. package/src/metrics/devtoolsDeltaBuildMs.js +0 -3
  230. package/src/metrics/devtoolsEventBytes.js +0 -3
  231. package/src/metrics/devtoolsEventTotal.js +0 -2
  232. package/src/metrics/devtoolsSnapshotBuildMs.js +0 -5
  233. package/src/metrics/devtoolsSubscribeTotal.js +0 -2
  234. package/src/metrics/errorsTotal.js +0 -2
  235. package/src/metrics/eventsEmittedTotal.js +0 -2
  236. package/src/metrics/externalWaitAsyncPending.js +0 -2
  237. package/src/metrics/gatewayApprovalDecisionsTotal.js +0 -2
  238. package/src/metrics/gatewayAuthEventsTotal.js +0 -2
  239. package/src/metrics/gatewayConnectionsActive.js +0 -2
  240. package/src/metrics/gatewayConnectionsClosedTotal.js +0 -2
  241. package/src/metrics/gatewayConnectionsTotal.js +0 -2
  242. package/src/metrics/gatewayCronTriggersTotal.js +0 -2
  243. package/src/metrics/gatewayErrorsTotal.js +0 -2
  244. package/src/metrics/gatewayHeartbeatTicksTotal.js +0 -2
  245. package/src/metrics/gatewayMessagesReceivedTotal.js +0 -2
  246. package/src/metrics/gatewayMessagesSentTotal.js +0 -2
  247. package/src/metrics/gatewayRpcCallsTotal.js +0 -2
  248. package/src/metrics/gatewayRpcDuration.js +0 -3
  249. package/src/metrics/gatewayRunEventBackpressureDisconnectTotal.js +0 -4
  250. package/src/metrics/gatewayRunsCompletedTotal.js +0 -2
  251. package/src/metrics/gatewayRunsStartedTotal.js +0 -2
  252. package/src/metrics/gatewaySignalsTotal.js +0 -2
  253. package/src/metrics/gatewayWebhooksReceivedTotal.js +0 -2
  254. package/src/metrics/gatewayWebhooksRejectedTotal.js +0 -2
  255. package/src/metrics/gatewayWebhooksVerifiedTotal.js +0 -2
  256. package/src/metrics/heartbeatDataSizeBytes.js +0 -5
  257. package/src/metrics/heartbeatIntervalMs.js +0 -3
  258. package/src/metrics/hotReloadDuration.js +0 -3
  259. package/src/metrics/hotReloadFailures.js +0 -2
  260. package/src/metrics/hotReloads.js +0 -2
  261. package/src/metrics/httpRequestDuration.js +0 -3
  262. package/src/metrics/httpRequests.js +0 -2
  263. package/src/metrics/index.d.ts +0 -1222
  264. package/src/metrics/index.js +0 -168
  265. package/src/metrics/memoryFactReads.js +0 -3
  266. package/src/metrics/memoryFactWrites.js +0 -3
  267. package/src/metrics/memoryMessageSaves.js +0 -3
  268. package/src/metrics/memoryRecallDuration.js +0 -11
  269. package/src/metrics/memoryRecallQueries.js +0 -3
  270. package/src/metrics/metricsServiceAdapter.js +0 -181
  271. package/src/metrics/nodeDuration.js +0 -3
  272. package/src/metrics/nodeRetriesTotal.js +0 -2
  273. package/src/metrics/nodesFailed.js +0 -2
  274. package/src/metrics/nodesFinished.js +0 -2
  275. package/src/metrics/nodesStarted.js +0 -2
  276. package/src/metrics/openApiToolCallErrorsTotal.js +0 -3
  277. package/src/metrics/openApiToolCallsTotal.js +0 -3
  278. package/src/metrics/openApiToolDuration.js +0 -9
  279. package/src/metrics/processHeapUsedBytes.js +0 -2
  280. package/src/metrics/processMemoryRssBytes.js +0 -2
  281. package/src/metrics/processUptimeSeconds.js +0 -2
  282. package/src/metrics/promptSizeBytes.js +0 -3
  283. package/src/metrics/replaysStarted.js +0 -3
  284. package/src/metrics/responseSizeBytes.js +0 -3
  285. package/src/metrics/rewindDurationMs.js +0 -3
  286. package/src/metrics/rewindFramesDeleted.js +0 -3
  287. package/src/metrics/rewindRollbackTotal.js +0 -2
  288. package/src/metrics/rewindSandboxesReverted.js +0 -3
  289. package/src/metrics/rewindTotal.js +0 -2
  290. package/src/metrics/runDuration.js +0 -3
  291. package/src/metrics/runForksCreated.js +0 -3
  292. package/src/metrics/runsAncestryDepth.js +0 -3
  293. package/src/metrics/runsCancelledTotal.js +0 -2
  294. package/src/metrics/runsCarriedStateBytes.js +0 -5
  295. package/src/metrics/runsContinuedTotal.js +0 -2
  296. package/src/metrics/runsFailedTotal.js +0 -2
  297. package/src/metrics/runsFinishedTotal.js +0 -2
  298. package/src/metrics/runsResumedTotal.js +0 -2
  299. package/src/metrics/runsTotal.js +0 -2
  300. package/src/metrics/sandboxActive.js +0 -2
  301. package/src/metrics/sandboxBundleSizeBytes.js +0 -5
  302. package/src/metrics/sandboxCompletedTotal.js +0 -2
  303. package/src/metrics/sandboxCreatedTotal.js +0 -2
  304. package/src/metrics/sandboxDurationMs.js +0 -3
  305. package/src/metrics/sandboxPatchCount.js +0 -3
  306. package/src/metrics/sandboxTransportDurationMs.js +0 -5
  307. package/src/metrics/schedulerConcurrencyUtilization.js +0 -2
  308. package/src/metrics/schedulerQueueDepth.js +0 -2
  309. package/src/metrics/schedulerWaitDuration.js +0 -5
  310. package/src/metrics/scorerDuration.js +0 -9
  311. package/src/metrics/scorerEventsFailed.js +0 -2
  312. package/src/metrics/scorerEventsFinished.js +0 -2
  313. package/src/metrics/scorerEventsStarted.js +0 -2
  314. package/src/metrics/scorersFailed.js +0 -3
  315. package/src/metrics/scorersFinished.js +0 -3
  316. package/src/metrics/scorersStarted.js +0 -3
  317. package/src/metrics/smithersMetricCatalog.js +0 -893
  318. package/src/metrics/smithersMetricCatalogByKey.js +0 -2
  319. package/src/metrics/smithersMetricCatalogByName.js +0 -2
  320. package/src/metrics/smithersMetricCatalogByPrometheusName.js +0 -4
  321. package/src/metrics/snapshotDuration.js +0 -9
  322. package/src/metrics/snapshotsCaptured.js +0 -3
  323. package/src/metrics/supervisorPollDuration.js +0 -5
  324. package/src/metrics/supervisorPollsTotal.js +0 -2
  325. package/src/metrics/supervisorResumeLag.js +0 -5
  326. package/src/metrics/supervisorResumedTotal.js +0 -2
  327. package/src/metrics/supervisorSkippedTotal.js +0 -2
  328. package/src/metrics/supervisorStaleDetected.js +0 -2
  329. package/src/metrics/taskHeartbeatTimeoutTotal.js +0 -2
  330. package/src/metrics/taskHeartbeatsTotal.js +0 -2
  331. package/src/metrics/timerDelayDuration.js +0 -3
  332. package/src/metrics/timersCancelled.js +0 -2
  333. package/src/metrics/timersCreated.js +0 -2
  334. package/src/metrics/timersFired.js +0 -2
  335. package/src/metrics/timersPending.js +0 -2
  336. package/src/metrics/toPrometheusMetricName.js +0 -8
  337. package/src/metrics/tokensCacheReadTotal.js +0 -2
  338. package/src/metrics/tokensCacheWriteTotal.js +0 -2
  339. package/src/metrics/tokensContextWindowBucketTotal.js +0 -2
  340. package/src/metrics/tokensContextWindowPerCall.js +0 -5
  341. package/src/metrics/tokensInputPerCall.js +0 -3
  342. package/src/metrics/tokensInputTotal.js +0 -2
  343. package/src/metrics/tokensOutputPerCall.js +0 -3
  344. package/src/metrics/tokensOutputTotal.js +0 -2
  345. package/src/metrics/tokensReasoningTotal.js +0 -2
  346. package/src/metrics/toolCallErrorsTotal.js +0 -2
  347. package/src/metrics/toolCallsTotal.js +0 -2
  348. package/src/metrics/toolDuration.js +0 -3
  349. package/src/metrics/toolOutputTruncatedTotal.js +0 -2
  350. package/src/metrics/trackEvent.js +0 -608
  351. package/src/metrics/updateAsyncExternalWaitPending.js +0 -18
  352. package/src/metrics/updateProcessMetrics.js +0 -20
  353. package/src/metrics/vcsDuration.js +0 -3
  354. package/src/normalizeStructuredEvent.js +0 -15
  355. package/src/prometheusContentType.js +0 -1
  356. package/src/renderPrometheusMetrics.js +0 -212
  357. package/src/resolveAgentTraceCapabilities.js +0 -59
  358. package/src/resolveSmithersObservabilityOptions.js +0 -109
  359. package/src/smithersMetrics.js +0 -2
  360. package/src/smithersSpanNames.js +0 -6
  361. package/src/unsupportedKindsForCapabilities.js +0 -32
  362. package/src/withSmithersSpan.js +0 -17
  363. package/tempo/tempo.yml +0 -17
package/docs/api.md ADDED
@@ -0,0 +1,780 @@
1
+ ---
2
+ title: "API reference"
3
+ description: "Every public export of @smthrs/observability: the Otlp exporter layers, endpoint and resource validation, the logger layers, the journal forwarder and its durable schema, the runtime metric handles, and the three OpenTelemetry SDK bridges."
4
+ ---
5
+
6
+ `@smthrs/observability` exports seven modules from its root entry point, and
7
+ each is also importable from `@smthrs/observability/<Module>`:
8
+
9
+ ```ts
10
+ import { Endpoint, JournalLogger, Logger, Metric, Otel, Otlp, Resource } from "@smthrs/observability"
11
+ // or
12
+ import * as Otlp from "@smthrs/observability/Otlp"
13
+ ```
14
+
15
+ Two more modules are subpath-only, because each binds a host-specific
16
+ OpenTelemetry SDK. `@smthrs/observability/package.json` is exported.
17
+
18
+ | Import | Source | Platform |
19
+ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -------- |
20
+ | `@smthrs/observability` | [src/index.ts](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/observability/src/index.ts) | any |
21
+ | `@smthrs/observability/NodeOtel` | [src/NodeOtel.ts](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/observability/src/NodeOtel.ts) | Node |
22
+ | `@smthrs/observability/BrowserOtel` | [src/BrowserOtel.ts](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/observability/src/BrowserOtel.ts) | browser |
23
+
24
+ The package is tested with `effect@4.0.4` and accepts `^4.0.4`. Layers, services, and schemas
25
+ are Effect constructs: a `Layer` provides services, a scoped layer releases on
26
+ scope close, and a schema decodes to an `Effect`.
27
+
28
+ ## Example
29
+
30
+ ```ts
31
+ import * as Otlp from "@smthrs/observability/Otlp"
32
+
33
+ const telemetry = Otlp.layerFetch({ baseUrl: "http://localhost:4318", serviceName: "deploy-status" })
34
+ const program = Effect.logInfo("deploying the API").pipe(Effect.withSpan("deploy"))
35
+
36
+ await Effect.runPromise(program.pipe(Effect.provide(telemetry), Effect.orDie, Effect.scoped))
37
+ ```
38
+
39
+ ## Otlp
40
+
41
+ The default exporter. `Otlp` composes `effect/observability/Otlp` and
42
+ nothing else, so it allocates no OpenTelemetry SDK and never resolves a `node:`
43
+ built-in. All three signals are JSON-serialized and posted below the configured
44
+ base URL at `/v1/logs`, `/v1/metrics`, and `/v1/traces`.
45
+
46
+ ### Otlp.Options
47
+
48
+ ```ts
49
+ interface Options {
50
+ readonly baseUrl: string
51
+ readonly serviceName?: string | undefined
52
+ readonly serviceVersion?: string | undefined
53
+ readonly attributes?: Record<string, unknown> | undefined
54
+ readonly headers?: Headers.Input | undefined
55
+ readonly exportInterval?: Duration.Input | undefined
56
+ readonly shutdownTimeout?: Duration.Input | undefined
57
+ }
58
+ ```
59
+
60
+ - `baseUrl`: the collector base URL, for example `http://localhost:4318`. It
61
+ must be an absolute `http://` or `https://` URL without credentials, query,
62
+ fragment, backslashes, spaces, or controls; anything else fails acquisition with
63
+ `Endpoint.InvalidExporterEndpoint` on path `baseUrl`.
64
+ - `serviceName`, `serviceVersion`: the `service.name` and `service.version`
65
+ resource attributes. Default to `defaultServiceName` and
66
+ `defaultServiceVersion`.
67
+ - `attributes`: additional resource attributes attached to every exported
68
+ signal, decoded by `Resource.Attributes`.
69
+ - `headers`: sent with every export request, which is where vendor
70
+ authentication goes. A header whose name names a credential
71
+ (`authorization`, `x-api-key`, `x-honeycomb-team`, any name
72
+ `Redaction.isSensitiveKey` recognizes) requires an `https://` `baseUrl` unless the host is `localhost`,
73
+ `127.0.0.0/8`, or `[::1]`; otherwise acquisition fails with
74
+ `Endpoint.InvalidExporterEndpoint` on path `baseUrl`. The check reads
75
+ header names only: a credential under any other name is sent as given, so
76
+ use `https://` for every remote collector.
77
+ - `exportInterval`: the export cadence applied to all three signals. Omitted,
78
+ each signal keeps Effect's own default.
79
+ - `shutdownTimeout`: upper bound on the flush performed when the layer's scope
80
+ closes.
81
+
82
+ ### Otlp.layer
83
+
84
+ ```ts
85
+ const layer: (options: Options) => Layer.Layer<
86
+ never,
87
+ Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint,
88
+ HttpClient.HttpClient
89
+ >
90
+ ```
91
+
92
+ Installs the OTLP logs, metrics, and traces exporters with the flows resource
93
+ defaults filled in. It requires an Effect `HttpClient`, which is how it stays
94
+ platform-neutral: a Node host may provide Undici, a browser or a test provides
95
+ something else. Both configuration inputs are decoded during acquisition, so
96
+ the returned layer either exports or refuses. Ambient `OTEL_RESOURCE_ATTRIBUTES`
97
+ cannot add unvalidated metadata to these explicit resources.
98
+
99
+ Requests over `maxRequestBytes` (1 MiB), stalled for ten seconds, or exceeding
100
+ four in-flight requests are discarded locally. Each discard increments
101
+ `flows_observability_otlp_dropped`. A `Warn` diagnostic with code
102
+ `otlp_export_discarded` reports `reason` (`oversized`, `stalled`, or `saturated`),
103
+ `bytes`, `limit`, and cumulative `dropped` at most once per minute per transport.
104
+ It uses the logger set captured before this exporter is installed, so it cannot
105
+ re-enter this exporter. Request bodies, headers, URLs, and ambient log
106
+ annotations are omitted. Keep an ambient sink outside OTLP at level `Warn` or
107
+ lower to observe loss independently; empty or filtered loggers cannot report it.
108
+
109
+ ### Otlp transport constants
110
+
111
+ ```ts
112
+ const maxRequestBytes: number // 1048576 (1 MiB)
113
+ const maximumEnvelopeBytes: number // 8192 (8 KiB)
114
+ const reservedBatchBytes: number // 909312 (888 KiB)
115
+ ```
116
+
117
+ The resource ceiling is 128 KiB. Another 8 KiB covers JSON wrappers and the
118
+ instrumentation scope. A metrics request repeats the service name as its scope
119
+ name (at most 6 KiB after escaping). Log and trace requests name their scope
120
+ `effect` with the Effect version. The remaining 888 KiB gives each record in the upstream 1,000-record
121
+ log or span batch about 909 bytes, several times a bare record. This guarantees
122
+ room for ordinary signal batches, not arbitrary record sizes or metric registry
123
+ cardinality.
124
+
125
+ ### Otlp.layerFetch
126
+
127
+ ```ts
128
+ const layerFetch: (options: Options) => Layer.Layer<
129
+ never,
130
+ Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint
131
+ >
132
+ ```
133
+
134
+ `layer` with `FetchHttpClient.layer` already provided, which binds the host's
135
+ global `fetch`. This is the default wiring on Node 26 and the only one that is
136
+ browser-safe by construction.
137
+
138
+ ```ts
139
+ const Telemetry = Otlp.layerFetch({ baseUrl: "http://localhost:4318" })
140
+ ```
141
+
142
+ ### Otlp.layerEnvironment
143
+
144
+ ```ts
145
+ const layerEnvironment: (
146
+ environment: Readonly<Record<string, string | undefined>>,
147
+ options?: Omit<Options, "baseUrl" | "headers">
148
+ ) => Layer.Layer<never, Otlp.LayerError>
149
+ ```
150
+
151
+ `layerFetch` against `OTEL_EXPORTER_OTLP_ENDPOINT` with the headers
152
+ `Otlp.parseHeaders` reads from `OTEL_EXPORTER_OTLP_HEADERS`. An unset or blank
153
+ endpoint returns `layerNoop`, so no exporter is installed. `LayerError` is
154
+ `Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint`.
155
+
156
+ ### Otlp.parseHeaders
157
+
158
+ ```ts
159
+ const parseHeaders: (value: string | undefined) => Record<string, string>
160
+ ```
161
+
162
+ Reads the OpenTelemetry `key=value,key=value` header list and percent-decodes
163
+ each value. Pairs without `=` or with an empty key are skipped; a malformed
164
+ escape is kept verbatim.
165
+
166
+ ### Otlp.layerNoop
167
+
168
+ ```ts
169
+ const layerNoop: Layer.Layer<never>
170
+ ```
171
+
172
+ Provides nothing and exports nothing. The explicit stand-in for a host with no
173
+ collector, so wiring code switches layers rather than branching.
174
+
175
+ ### Otlp.defaultServiceName
176
+
177
+ ```ts
178
+ const defaultServiceName: string // "flows"
179
+ ```
180
+
181
+ The `service.name` attribute installed when the caller supplies none.
182
+
183
+ ### Otlp.defaultServiceVersion
184
+
185
+ ```ts
186
+ const defaultServiceVersion: string // "1.0.0-rc.0"
187
+ ```
188
+
189
+ The `service.version` attribute installed when the caller supplies none. It
190
+ mirrors this package's release version, held as a literal because a published
191
+ package cannot read its own manifest on every runtime it supports.
192
+
193
+ ### Delivery behavior
194
+
195
+ Effect's exporter retries a transient failure three times, honoring a
196
+ `retry-after` response header on any retried status when one is present, then
197
+ disables that exporter for 60 seconds and logs a `Debug` record. Export failure
198
+ never fails the application effect and never surfaces as an unhandled
199
+ rejection. Closing the layer's scope performs the final flush, bounded by
200
+ `shutdownTimeout`.
201
+
202
+ The exporter acts on a response's status and `retry-after` header only. It
203
+ never reads the response body: each exchange ends when the status arrives, so
204
+ a collector that never finishes its answer cannot stall a signal.
205
+
206
+ The shape of what a collector receives is in
207
+ [Export to an OTLP collector](./guides/export-to-a-collector.md#what-the-collector-receives).
208
+
209
+ ## Endpoint
210
+
211
+ Validated collector endpoints, shared by every OTLP builder. The endpoint is
212
+ the field an operator most often gets wrong, and a wrong one is invisible after
213
+ acquisition, so it is decoded before any exporter exists.
214
+
215
+ ### Endpoint.Endpoint
216
+
217
+ ```ts
218
+ const Endpoint: Schema.String.check(...)
219
+ ```
220
+
221
+ Runtime schema for an absolute `http:` or `https:` collector endpoint of at
222
+ most `maximumEndpointLength` characters that carries no credentials, query,
223
+ fragment, backslashes, spaces, or controls. A base path is allowed;
224
+ authentication belongs in exporter headers. Query and fragment suffixes are
225
+ rejected because appending `/v1/traces` to them does not change the request
226
+ path. A value the WHATWG URL parser would repair rather
227
+ than parse as written is refused, because the repaired URL is not the one the
228
+ exporter would post to.
229
+
230
+ ### Endpoint.maximumEndpointLength
231
+
232
+ ```ts
233
+ const maximumEndpointLength: number // 2048
234
+ ```
235
+
236
+ Largest collector endpoint accepted by a builder.
237
+
238
+ ### Endpoint.decode
239
+
240
+ ```ts
241
+ const decode: (endpoint: unknown, path: string) => Effect.Effect<string, InvalidExporterEndpoint>
242
+ ```
243
+
244
+ Decodes one endpoint into its normalized form. `path` names the option the
245
+ endpoint arrived on, so the refusal points at the caller's own field rather
246
+ than at a shared internal name. The rejected value is not retained in the
247
+ error.
248
+
249
+ ### Endpoint.InvalidExporterEndpoint
250
+
251
+ ```ts
252
+ class InvalidExporterEndpoint {
253
+ readonly code: "invalid_exporter_endpoint"
254
+ readonly path: string
255
+ readonly message: string
256
+ }
257
+ ```
258
+
259
+ The stable exporter-endpoint refusal shared by `Otlp.layer`,
260
+ `Otlp.layerFetch` (`path` is `baseUrl`), and `NodeOtel.layerOtel` (`path` is
261
+ `endpoint`).
262
+
263
+ ### Endpoint.normalize
264
+
265
+ ```ts
266
+ const normalize: (endpoint: string) => string
267
+ ```
268
+
269
+ Removes repeated trailing separators, so `http://host//` and `http://host` both
270
+ produce one signal URL.
271
+
272
+ ### Endpoint.signalUrl
273
+
274
+ ```ts
275
+ const signalUrl: (endpoint: string, signal: "traces" | "metrics" | "logs") => string
276
+ ```
277
+
278
+ Builds the OTLP/HTTP URL one signal is posted to below a decoded endpoint:
279
+ `signalUrl("http://host", "traces")` is `http://host/v1/traces`.
280
+
281
+ ## Resource
282
+
283
+ Explicit, validated OpenTelemetry resource metadata. Every public OTEL builder
284
+ in this package decodes the same `Configuration`. Resource metadata comes from
285
+ the caller and the SDK's fixed telemetry fields. Neither the default exporter
286
+ nor the Node SDK layer merges ambient resource configuration after validation.
287
+
288
+ ### Resource.Configuration
289
+
290
+ ```ts
291
+ const Configuration: Schema.Struct<{
292
+ serviceName: Schema.String
293
+ serviceVersion: Schema.optional<Schema.String>
294
+ attributes: Schema.optional<typeof Attributes>
295
+ }>
296
+ type Configuration = typeof Configuration.Type
297
+ ```
298
+
299
+ The service identity attached to exported telemetry. `serviceName` and
300
+ `serviceVersion` are non-empty, well formed, and at most
301
+ `maximumIdentityLength` UTF-16 code units.
302
+
303
+ ### Resource.Attributes and Resource.AttributeValue
304
+
305
+ ```ts
306
+ const AttributeValue: Schema.Union<[...]>
307
+ const Attributes: Schema.Record<Schema.String, typeof AttributeValue>
308
+ ```
309
+
310
+ `AttributeValue` accepts a string of at most `maximumAttributeStringLength`
311
+ code units, a finite number, a boolean, or a homogeneous array of one of those
312
+ scalar types, with at most `maximumAttributeArrayLength` elements. `Attributes` bounds the record at `maximumAttributes` entries
313
+ with non-empty, well formed keys of at most `maximumAttributeKeyLength` code
314
+ units. NUL and unpaired UTF-16 surrogates are refused in keys and in values;
315
+ valid astral Unicode is preserved.
316
+
317
+ ### Resource constants
318
+
319
+ ```ts
320
+ const maximumIdentityLength: number // 1024
321
+ const maximumAttributeKeyLength: number // 1024
322
+ const maximumAttributeStringLength: number // 65536
323
+ const maximumAttributes: number // 256
324
+ const maximumAttributeArrayLength: number // 256
325
+ const maximumResourceBytes: number // 131072 (128 KiB)
326
+ ```
327
+
328
+ The resource byte limit counts the complete OTLP JSON resource, including
329
+ identity, SDK-added `telemetry.sdk.name`, `telemetry.sdk.language` and
330
+ `telemetry.sdk.version`, attribute keys, scalar and array wrappers, escaping,
331
+ and UTF-8. The SDK's own values are reserved even for the default Effect
332
+ exporter, and a caller attribute that replaces one of them is conservatively
333
+ counted beside it.
334
+ Counting stops at the first fragment over budget to bound intermediate
335
+ allocations; the error reports the measured lower bound and byte limit at path
336
+ `attributes`. Array-length errors report the measured element count and limit
337
+ at the attribute path. No rejected attribute values are retained.
338
+
339
+ All resource-accepting layers and `decode`, `decodeSync`, and
340
+ `configToAttributes` enforce these bounds before exporter acquisition.
341
+ Explicit `serviceName` and `serviceVersion` take precedence over attributes
342
+ with those keys. Admission conservatively counts those redundant attributes.
343
+
344
+ ### Resource.decode
345
+
346
+ ```ts
347
+ const decode: (configuration: unknown) => Effect.Effect<Configuration, InvalidResourceConfiguration>
348
+ ```
349
+
350
+ Decodes one resource configuration without retaining rejected values.
351
+
352
+ ### Resource.decodeSync
353
+
354
+ ```ts
355
+ const decodeSync: (configuration: unknown) => Configuration
356
+ ```
357
+
358
+ The same decoding for the package's pure projection API. Throws
359
+ `InvalidResourceConfiguration` rather than failing an effect.
360
+
361
+ ### Resource.InvalidResourceConfiguration
362
+
363
+ ```ts
364
+ class InvalidResourceConfiguration {
365
+ readonly code: "invalid_resource_configuration"
366
+ readonly path: string
367
+ readonly message: string
368
+ }
369
+ ```
370
+
371
+ The stable resource refusal shared by every layer here. `path` is a dotted
372
+ route into the offending field, such as `serviceName` or `attributes.region`,
373
+ and is the bare `resource` when the whole configuration was malformed.
374
+
375
+ ### Resource.toOpenTelemetryConfiguration
376
+
377
+ ```ts
378
+ const toOpenTelemetryConfiguration: (configuration: Configuration) => {
379
+ readonly serviceName: string
380
+ readonly serviceVersion?: string
381
+ readonly attributes?: Attributes
382
+ }
383
+ ```
384
+
385
+ Projects a decoded resource into the exact optional-property shape the
386
+ OpenTelemetry SDK expects, omitting absent optional fields rather than setting
387
+ them to `undefined`.
388
+
389
+ ### Resource.configToAttributes
390
+
391
+ ```ts
392
+ const configToAttributes: (configuration: Configuration) => Attributes
393
+ ```
394
+
395
+ Converts explicit service metadata into OpenTelemetry resource attributes.
396
+ Invalid metadata throws the same typed `InvalidResourceConfiguration` a layer
397
+ returns during acquisition.
398
+
399
+ ### Resource.layer
400
+
401
+ ```ts
402
+ const layer: (configuration: Configuration) => Layer.Layer<Resource, InvalidResourceConfiguration>
403
+ ```
404
+
405
+ Provides an explicitly validated OpenTelemetry resource, for a composition that
406
+ assembles the rest of the SDK itself.
407
+
408
+ ### Resource.Resource
409
+
410
+ The OpenTelemetry resource service tag, re-exported from
411
+ `@effect/opentelemetry/Resource`.
412
+
413
+ ## Logger
414
+
415
+ Effect logger layers. All four follow two rules: `mergeWithExisting` defaults
416
+ to `false`, so installing one replaces the ambient logger set, and
417
+ `minimumLogLevel` is applied only when the caller names it.
418
+
419
+ ### Logger.Options
420
+
421
+ ```ts
422
+ interface Options {
423
+ readonly minimumLogLevel?: LogLevel.LogLevel | undefined
424
+ readonly mergeWithExisting?: boolean | undefined
425
+ }
426
+ ```
427
+
428
+ - `minimumLogLevel`: pins `References.MinimumLogLevel` for the whole
429
+ application. Omitted, the layer leaves that reference alone and Effect's own
430
+ `Info` default applies.
431
+ - `mergeWithExisting`: keeps the ambient loggers alongside this one. Defaults
432
+ to `false`.
433
+
434
+ ### Logger.layerPrettyDev
435
+
436
+ ```ts
437
+ const layerPrettyDev: (options?: Options) => Layer.Layer<never>
438
+ ```
439
+
440
+ A human-readable development logger, with colors and mode chosen from the
441
+ output it finds.
442
+
443
+ ### Logger.layerStructuredJson
444
+
445
+ ```ts
446
+ const layerStructuredJson: (options?: Options) => Layer.Layer<never>
447
+ ```
448
+
449
+ One structured JSON object per log line.
450
+
451
+ ### Logger.layerNoop
452
+
453
+ ```ts
454
+ const layerNoop: (options?: Pick<Options, "minimumLogLevel">) => Layer.Layer<never>
455
+ ```
456
+
457
+ Removes the active logger set. This is the one exception to the second rule:
458
+ silencing is its purpose, so it pins `None` unless the caller names another
459
+ level.
460
+
461
+ ### Logger.layer
462
+
463
+ ```ts
464
+ const layer: (logger: Logger.Logger<unknown, unknown>, options?: Options) => Layer.Layer<never>
465
+ ```
466
+
467
+ Installs a caller-supplied logger under the same two rules.
468
+
469
+ ## JournalLogger
470
+
471
+ Non-blocking forwarding of bounded operational logs to the durable journal. The
472
+ callback reads the queue's remaining room, snapshots and redacts a bounded
473
+ record synchronously only when a slot is free, then performs only queue
474
+ admission; a forked worker drains the queue into the journal. A record a full
475
+ queue cannot take is counted and discarded without being snapshotted.
476
+
477
+ ### JournalLogger.Options
478
+
479
+ ```ts
480
+ interface Options {
481
+ readonly runId: JournalEvent.RunId
482
+ readonly capacity?: number | undefined
483
+ readonly minimumLogLevel?: LogLevel.LogLevel | undefined
484
+ readonly mergeWithExisting?: boolean | undefined
485
+ }
486
+ ```
487
+
488
+ - `runId`: the run every forwarded record is attributed to.
489
+ - `capacity`: queue depth, 1 through `maximumCapacity`. Defaults to 256.
490
+ - `minimumLogLevel` and `mergeWithExisting`: as on `Logger.Options`.
491
+
492
+ ### JournalLogger.layerJournalForwarding
493
+
494
+ ```ts
495
+ const layerJournalForwarding: (
496
+ options: Options
497
+ ) => Layer.Layer<never, InvalidJournalLoggerOptions, Journal.Journal>
498
+ ```
499
+
500
+ Installs a bounded, drop-on-overflow forwarder for one explicit run.
501
+ Configuration is decoded before a worker starts, so an invalid run id or
502
+ capacity fails acquisition rather than being routed through the lossy worker.
503
+
504
+ Each record becomes one journal entry on the lossy channel, with `eventType`
505
+ `telemetry.log`, source `flows/observability/logger`, and a `TelemetryLog`
506
+ payload. The durable journal allocates the per-source sequence, so a rebuilt or
507
+ concurrently running layer for one run cannot reuse an identity.
508
+
509
+ Overflow, journal delivery failures, and journal defects are telemetry losses
510
+ rather than application failures. Each advances `Metric.droppedLogRecords`; the
511
+ two failure paths also log a warning annotated with the run id, and the worker
512
+ keeps draining. Interruption stays fatal, and closing the scope may drop
513
+ records queued behind an in-flight write.
514
+
515
+ ### JournalLogger.TelemetryLog
516
+
517
+ ```ts
518
+ const TelemetryLog: Schema.Struct<{
519
+ version: Schema.Literal<1>
520
+ level: Schema.Literals<["All", "Fatal", "Error", "Warn", "Info", "Debug", "Trace", "None"]>
521
+ message: Schema.Unknown
522
+ annotations: Schema.Record<Schema.String, Schema.Unknown>
523
+ cause: typeof TelemetryCause
524
+ fiberId: Schema.Int
525
+ traceId: Schema.optionalKey<Schema.String>
526
+ spanId: Schema.optionalKey<Schema.String>
527
+ timestamp: Schema.String
528
+ }>
529
+ type TelemetryLog = typeof TelemetryLog.Type
530
+ ```
531
+
532
+ The durable wire shape of one forwarded log record. `traceId` and `spanId` are
533
+ present only when a span was active. `timestamp` is ISO-8601. Every persisted
534
+ `telemetry.log` payload decodes with this schema: a projection that would not
535
+ degrades to a total record with an empty cause rather than to a payload
536
+ consumers throw on.
537
+
538
+ ### JournalLogger.TelemetryCause
539
+
540
+ ```ts
541
+ const TelemetryCause: Schema.Struct<{
542
+ version: Schema.Literal<1>
543
+ reasons: Schema.Array<typeof TelemetryCauseReason>
544
+ }>
545
+ type TelemetryCause = typeof TelemetryCause.Type
546
+ ```
547
+
548
+ A versioned structural Effect cause. Effect stores composed failures as an
549
+ ordered reason list, and the projection preserves that order and each
550
+ discriminator.
551
+
552
+ ### JournalLogger.TelemetryCauseReason
553
+
554
+ ```ts
555
+ const TelemetryCauseReason: Schema.Union<[
556
+ typeof TelemetryFail,
557
+ typeof TelemetryDie,
558
+ typeof TelemetryInterrupt
559
+ ]>
560
+ type TelemetryCauseReason = typeof TelemetryCauseReason.Type
561
+ ```
562
+
563
+ One reason in a persisted cause. `TelemetryFail` carries `error`,
564
+ `TelemetryDie` carries `defect`, and `TelemetryInterrupt` carries a
565
+ non-negative `fiberId` or `null`. All three are exported individually.
566
+
567
+ ### JournalLogger.InvalidJournalLoggerOptions
568
+
569
+ ```ts
570
+ class InvalidJournalLoggerOptions {
571
+ readonly code: "invalid_journal_logger_options"
572
+ readonly path: string
573
+ readonly message: string
574
+ }
575
+ ```
576
+
577
+ The stable logger-configuration refusal, raised during layer acquisition.
578
+
579
+ ### JournalLogger constants
580
+
581
+ ```ts
582
+ const maximumCapacity: number // 65536
583
+ const maximumSnapshotBytes: number // 1048576
584
+ const maximumSnapshotMembers: number // 4096
585
+ const maximumSnapshotDepth: number // 64
586
+ const unrenderableMarker: string // "[Unrenderable]"
587
+ const truncatedMarker: string // "[Truncated]"
588
+ ```
589
+
590
+ A snapshot admits at most `maximumSnapshotBytes` of encoded data,
591
+ `maximumSnapshotMembers` container members, and `maximumSnapshotDepth`
592
+ container edges. Unreadable values become `unrenderableMarker`, values past a
593
+ ceiling become `truncatedMarker`, and deeper values become the journal's
594
+ `[Deep]` marker. Container-shaped fields keep their shape, so annotations that
595
+ spent the whole budget arrive as `{ "[Truncated]": "[Truncated]" }` rather than
596
+ as a scalar. Text is bounded in one pass that never cuts a surrogate pair, and
597
+ the journal's own redaction rules run before queue admission.
598
+
599
+ ## Metric
600
+
601
+ The runtime signals that cross package boundaries. Producers live in the
602
+ packages that know when to advance them; this module owns only the identifiers
603
+ and the handles.
604
+
605
+ ### Metric handles
606
+
607
+ ```ts
608
+ const runThroughput: Metric.Counter // "flows_run_throughput"
609
+ const activeSeats: Metric.Gauge // "flows_seat_active"
610
+ const quotaParks: Metric.Counter // "flows_quota_park"
611
+ const structuredOutputRejections: Metric.Counter // "flows_agent_structured_output_rejections"
612
+ const structuredOutputExhausted: Metric.Counter // "flows_agent_structured_output_exhausted"
613
+ const droppedLogRecords: Metric.Counter // "flows_observability_log_dropped"
614
+ ```
615
+
616
+ - `runThroughput` advances after a terminal run transition commits in
617
+ [`@smthrs/run-store`](/api/run-store).
618
+ - `activeSeats` is held for the lifetime of a production `Agent.run` stream in
619
+ [`@smthrs/agent`](/api/agent) and released on success, failure, or
620
+ interruption.
621
+ - `quotaParks` advances when a sealed quota decision is first executed, not
622
+ when it is replayed after a wake or a process restart.
623
+ - `structuredOutputRejections` advances once per agent answer its declared
624
+ output schema refuses, in the same session or a fresh one.
625
+ - `structuredOutputExhausted` advances once per agent step that fails after
626
+ spending every output correction and its repair.
627
+ - `droppedLogRecords` advances once per record lost by `JournalLogger`.
628
+
629
+ Step-cache lookup and write counters remain owned by
630
+ [`@smthrs/step-cache`](/api/step-cache); this package does not duplicate those
631
+ handles.
632
+
633
+ ### Metric.registry
634
+
635
+ ```ts
636
+ const registry: {
637
+ readonly runThroughput: typeof runThroughput
638
+ readonly activeSeats: typeof activeSeats
639
+ readonly quotaParks: typeof quotaParks
640
+ readonly structuredOutputRejections: typeof structuredOutputRejections
641
+ readonly structuredOutputExhausted: typeof structuredOutputExhausted
642
+ readonly droppedLogRecords: typeof droppedLogRecords
643
+ }
644
+ ```
645
+
646
+ All six handles as one object, for a host that enumerates them. The six
647
+ series names are the dashboard contract; treat them as public API.
648
+
649
+ ## Otel
650
+
651
+ Provider-neutral composition for OpenTelemetry providers the application
652
+ already built. This module allocates no exporter.
653
+
654
+ ### Otel.Options
655
+
656
+ ```ts
657
+ interface Options {
658
+ readonly resource: Resource.Configuration
659
+ readonly tracerProvider?:
660
+ | Api.TracerProvider
661
+ | ((resource: Resource) => Api.TracerProvider)
662
+ | undefined
663
+ readonly loggerProvider?:
664
+ | LoggerProvider
665
+ | ((resource: Resource) => LoggerProvider)
666
+ | undefined
667
+ readonly metricReader?: (() => MetricReader | ReadonlyArray<MetricReader>) | undefined
668
+ readonly loggerMergeWithExisting?: boolean | undefined
669
+ readonly metricTemporality?: OtelMetrics.TemporalityPreference | undefined
670
+ }
671
+ ```
672
+
673
+ `metricTemporality` is `"cumulative"` or `"delta"`.
674
+
675
+ Ownership differs by field. `tracerProvider` and `loggerProvider` are borrowed:
676
+ the layer bridges onto them and never flushes or shuts one down, including a
677
+ provider a factory returned. `metricReader` is owned: the factory runs once
678
+ during layer acquisition, after resource validation, and closing the layer's
679
+ scope shuts down every reader it returned. Build the readers inside the
680
+ factory. Returning a reader that a longer-lived composition still exports
681
+ through disables that reader when this scope closes.
682
+
683
+ ### Otel.layerOtel
684
+
685
+ ```ts
686
+ const layerOtel: (options: Options) => Layer.Layer<never, Resource.InvalidResourceConfiguration>
687
+ ```
688
+
689
+ Bridges Effect's tracer, logger, and metrics onto the supplied providers and
690
+ the readers the `metricReader` factory returns, over the validated resource.
691
+ Spans and log records carry the instrumentation scope `effect` with the Effect
692
+ version.
693
+ Each bridge is installed only when its provider or factory is supplied, and a
694
+ factory that returns an empty array registers no reader at all.
695
+
696
+ ### Otel.layerNoop
697
+
698
+ ```ts
699
+ const layerNoop: Layer.Layer<never>
700
+ ```
701
+
702
+ A no-op OTEL layer, for callers that want an explicit optional slot.
703
+
704
+ ## NodeOtel
705
+
706
+ Node-only OTLP/HTTP OpenTelemetry SDK setup. Import it from
707
+ `@smthrs/observability/NodeOtel`; it is not re-exported from the root, because
708
+ it resolves Node-only host modules and would break the root's browser bundle.
709
+
710
+ ### NodeOtel.Options
711
+
712
+ ```ts
713
+ interface Options {
714
+ readonly endpoint: string
715
+ readonly resource: Resource.Configuration
716
+ readonly shutdownTimeout?: Duration.Input | undefined
717
+ readonly exportIntervalMillis?: number | undefined
718
+ }
719
+ ```
720
+
721
+ `endpoint` is decoded exactly as `Otlp.Options.baseUrl` is, and a refusal names
722
+ the path `endpoint`.
723
+
724
+ ### NodeOtel.layerOtel
725
+
726
+ ```ts
727
+ const layerOtel: (options: Options) => Layer.Layer<
728
+ never,
729
+ Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint
730
+ >
731
+ ```
732
+
733
+ Builds a scoped Node OTLP/HTTP layer for all three signals: a
734
+ `BatchSpanProcessor`, a `BatchLogRecordProcessor`, and a
735
+ `PeriodicExportingMetricReader`, each behind its own OTLP exporter. Exporter
736
+ objects are created only when the layer is built. `OTEL_SERVICE_NAME` and
737
+ `OTEL_RESOURCE_ATTRIBUTES` cannot add resource metadata after validation,
738
+ whether supplied by the process environment or an Effect `ConfigProvider`.
739
+ The OpenTelemetry exporters still read the standard transport variables
740
+ (`OTEL_EXPORTER_OTLP_HEADERS`, `_TIMEOUT`, `_COMPRESSION`, `_CERTIFICATE`,
741
+ `_CLIENT_CERTIFICATE`, `_CLIENT_KEY`, and their per-signal forms) from the
742
+ process environment; the explicit `endpoint` always wins over
743
+ `OTEL_EXPORTER_OTLP_ENDPOINT`. Headers set there reach this `endpoint`, so do
744
+ not set them for a different collector. `Otlp.layer` reads none of these.
745
+ Closing the scope
746
+ force-flushes both batch processors and collects the metric reader once, so
747
+ release rather than the interval is the deterministic flush.
748
+
749
+ ## BrowserOtel
750
+
751
+ Browser OpenTelemetry SDK setup with explicitly injected processors. Import it
752
+ from `@smthrs/observability/BrowserOtel`.
753
+
754
+ ### BrowserOtel.Options
755
+
756
+ ```ts
757
+ interface Options {
758
+ readonly resource: Resource.Configuration
759
+ readonly spanProcessor?: (() => SpanProcessor | ReadonlyArray<SpanProcessor>) | undefined
760
+ readonly logRecordProcessor?: (() => LogRecordProcessor | ReadonlyArray<LogRecordProcessor>) | undefined
761
+ readonly metricReader?: (() => MetricReader | ReadonlyArray<MetricReader>) | undefined
762
+ readonly loggerMergeWithExisting?: boolean | undefined
763
+ }
764
+ ```
765
+
766
+ Processors and readers are created by the caller's factories, which keeps this
767
+ module free of Node imports and free of browser exporter policy. Every factory
768
+ is owned: it runs once during layer acquisition, after resource validation, and
769
+ the web SDK shuts down everything it returned when the scope closes. A factory
770
+ that returns an empty array installs nothing for that signal.
771
+
772
+ ### BrowserOtel.layerOtel
773
+
774
+ ```ts
775
+ const layerOtel: (options: Options) => Layer.Layer<never, Resource.InvalidResourceConfiguration>
776
+ ```
777
+
778
+ Builds a scoped browser OpenTelemetry layer over the validated resource. A
779
+ layer with no processor factories at all still builds; it provides the resource
780
+ and bridges nothing.