@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
@@ -0,0 +1,98 @@
1
+ ---
2
+ title: "Instrumentation and export"
3
+ description: "Why the Smithers packages instrument themselves but export nothing, what that split buys, and the three independent ways to read the same run."
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ Instrumentation and export are two different jobs, and Smithers puts them in
9
+ different packages on purpose.
10
+
11
+ ## Every other package is already instrumented
12
+
13
+ A flow execution opens spans without being asked. The flow lifecycle, the
14
+ engine dispatch, a run claim, a heartbeat, a journal write, down to individual
15
+ SQL statements: each is a span on Effect's own tracer. Alongside
16
+ them, each store package declares and updates its own metric handles on its hot
17
+ paths: `JournalMetrics` in [`@smthrs/journal`](/api/journal), `RunStoreMetrics`
18
+ in [`@smthrs/run-store`](/api/run-store), `CacheStoreMetrics` in
19
+ [`@smthrs/step-cache`](/api/step-cache), `ArtifactStoreMetrics` in
20
+ [`@smthrs/artifacts`](/api/artifacts), and `DatabaseMetrics` in
21
+ [`@smthrs/database`](/api/database).
22
+
23
+ None of those packages allocates an exporter. Effect's tracer and metric
24
+ registry are collection points; with no exporter installed they collect and
25
+ discard, at a cost close to zero.
26
+
27
+ ## Spans Effect names
28
+
29
+ A Smithers package names its own spans for the operation, such as
30
+ `RunStore.claim` or `Journal.emitDurable`. Effect names the spans of the SQL,
31
+ HTTP and RPC clients those packages use:
32
+
33
+ | Span | Name | Kind | What it carries |
34
+ | --------------- | -------------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
35
+ | SQL statement | The database system: `sqlite` or `postgresql` | `client` | `db.system.name`, `db.query.text` and `effect.sql.method` |
36
+ | SQL transaction | `sql.transaction` | `internal` | The events `effect.sql.transaction.commit`, `effect.sql.transaction.savepoint` and `effect.sql.transaction.rollback` |
37
+ | HTTP request | The request method, such as `POST` | `client` | `http.request.method`, `url.full`, `url.path`, `url.scheme`, `server.address`, `server.port` and `http.response.status_code` |
38
+ | RPC call | The procedure's tag, such as `Projection.Snapshot` | `client`, `server` | `rpc.system.name` (`effect_rpc`) and `rpc.method` |
39
+
40
+ On an HTTP request span, `server.address` is the host name without the scheme,
41
+ and `server.port` is always present, as the scheme's default when the URL names
42
+ none.
43
+
44
+ An HTTP request span records no request or response header. A host that wants
45
+ them provides `HttpClient.TracerHeaderFilter`. The model, artifact and
46
+ step-cache packages add their credential header names to
47
+ `Headers.CurrentRedactedNames`, so a recorded credential header of theirs reads
48
+ `<redacted>`. Every other recorded header keeps its value, apart from the names
49
+ Effect redacts itself, such as `authorization`, `cookie`, `set-cookie` and
50
+ `x-api-key`.
51
+
52
+ A `4xx` or `5xx` answer ends an HTTP request span as failed, with the status in
53
+ `error.type`. That holds even where the calling package treats the status as an
54
+ ordinary answer: a shared-cache miss is a failed `GET` span with `error.type`
55
+ `404` inside a lookup span that succeeded.
56
+
57
+ ## This package is the exporter
58
+
59
+ `Otlp.layerFetch` installs Effect's OTLP logger, metrics exporter, and tracer
60
+ against a collector endpoint, with a service identity filled in. That is the
61
+ whole wiring, and it is why telemetry is additive rather than invasive:
62
+ providing one layer turns on delivery for instrumentation that was already
63
+ there, and removing the line turns it off without touching a flow body.
64
+
65
+ The split also keeps the dependency in one place. Because `Otlp` composes only
66
+ what `effect` already ships, a package that wants a counter takes on no
67
+ OpenTelemetry dependency to get one, and the process pays for an SDK only if a
68
+ host chooses `NodeOtel` or `BrowserOtel`.
69
+
70
+ ## The producer owns the meaning, the exporter owns the delivery
71
+
72
+ A metric handle belongs to the package that knows when to advance it. This
73
+ package holds only the four cross-package runtime signals nobody else owns,
74
+ and it holds them so the producers can share one identifier:
75
+ `flows_run_throughput` is updated in [`@smthrs/run-store`](/api/run-store),
76
+ `flows_seat_active` and `flows_quota_park` in [`@smthrs/agent`](/api/agent),
77
+ and `flows_observability_log_dropped` here. Step-cache counters stay in
78
+ [`@smthrs/step-cache`](/api/step-cache); this package does not duplicate them.
79
+
80
+ The consequence for a reader: a metric's name tells you which package to open
81
+ to learn what advances it, and this package tells you only how it leaves the
82
+ process.
83
+
84
+ ## Three ways to read one run
85
+
86
+ Export is one read path, not the only one, and the other two need no collector:
87
+
88
+ 1. **The OTLP trace.** Every span and series posts to your collector. Filter on
89
+ the `service.name` you passed to the layer.
90
+ 2. **The durable journal.** `Journal.entries` reads a run's lifecycle events in
91
+ process, and `JournalLogger` puts the run's log records on that same
92
+ history. See [Forward logs to the run journal](../guides/forward-logs-to-the-journal.md).
93
+ 3. **The metric handles.** Effect's `Metric.value` reads a counter in process,
94
+ with no exporter installed at all. See
95
+ [Read the runtime metrics](../guides/read-runtime-metrics.md).
96
+
97
+ The three tell the same story about the same run, which is what makes a
98
+ disagreement between them worth investigating.
@@ -0,0 +1,73 @@
1
+ ---
2
+ title: "The layer map"
3
+ description: "The five telemetry layer builders this package ships, what each one allocates, and the rule that keeps the root entry point free of Node modules."
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ Five builders produce a telemetry layer, and they differ in one thing: how much
9
+ they allocate for you.
10
+
11
+ ## The five builders
12
+
13
+ | Builder | Allocates | Reach for it when |
14
+ | ----------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
15
+ | `Otlp.layerFetch` | Effect's three OTLP exporters, plus the host's global `fetch` | You have a collector and no other OpenTelemetry requirement. This is the default. |
16
+ | `Otlp.layer` | Effect's three OTLP exporters. You provide the `HttpClient` | You need a specific HTTP client, such as Undici on Node. |
17
+ | `NodeOtel.layerOtel` | The Node OpenTelemetry SDK: three OTLP/HTTP exporters and their processors | Node code that must run through the OpenTelemetry SDK. |
18
+ | `BrowserOtel.layerOtel` | The web OpenTelemetry SDK around processors and readers you construct | Browser code that must run through the OpenTelemetry SDK. |
19
+ | `Otel.layerOtel` | Effect bridges; optional caller factories build providers | The application controls SDK provider construction. |
20
+
21
+ Each has an explicit do-nothing counterpart: `Otlp.layerNoop` and
22
+ `Otel.layerNoop` both provide nothing and export nothing, so wiring code
23
+ switches layers instead of branching around a missing one.
24
+
25
+ ## Why `Otlp` is the default
26
+
27
+ `Otlp` composes only `effect/observability/Otlp`, so it adds no
28
+ OpenTelemetry SDK to the process, and it delivers over Effect's `HttpClient`
29
+ rather than a platform transport. That makes it the cheapest wiring and the
30
+ only one that runs unchanged in Node, in Bun, and in a browser.
31
+
32
+ Reach past it when something other than a collector endpoint is in play: an
33
+ existing OpenTelemetry instrumentation you must feed, a vendor exporter that is
34
+ not OTLP/HTTP JSON, or a provider a framework hands you.
35
+
36
+ ## Why the root entry point stops at `Otel`
37
+
38
+ The root entry point exports `Otlp`, `Endpoint`, `JournalLogger`, `Logger`,
39
+ `Metric`, `Otel`, and `Resource`. It stops there because those seven resolve
40
+ nothing host-specific.
41
+
42
+ `NodeOtel` does. It reaches `@effect/opentelemetry/NodeSdk` and
43
+ `@opentelemetry/sdk-trace-node`, and the latter pulls
44
+ `@opentelemetry/context-async-hooks`, which imports the bare specifier
45
+ `async_hooks`. A browser bundler cannot resolve that, so re-exporting `NodeOtel`
46
+ from the root would break the root's browser bundle for every consumer,
47
+ including those that never wanted an SDK. `BrowserOtel` is kept beside it for
48
+ symmetry: a module that binds one host belongs on a subpath.
49
+
50
+ Nothing the root entry point reaches resolves a `node:` built-in, as an ESM
51
+ import or as a `require("node:...")` call, so a browser bundle of the root
52
+ carries no host module.
53
+
54
+ ## `Resource` sits under all of them
55
+
56
+ Every builder decodes the same `Resource.Configuration`. `Otlp`, `NodeOtel`,
57
+ and `BrowserOtel` attach its attributes to all enabled signals. `Otel.layerOtel`
58
+ passes that validated resource to provider factories and the metric producer;
59
+ factories must use it when constructing tracer and logger providers.
60
+
61
+ Already-created providers retain their own resources. For those providers,
62
+ `Otel.layerOtel`'s resource option sets only the metric resource. Construct
63
+ them with the intended resource before injection to give all three signals the
64
+ same service identity. Spans and log records carry the instrumentation scope
65
+ `effect` with the Effect version, whatever the resource.
66
+
67
+ `Resource.layer` provides the resource on its own, for a composition that
68
+ assembles the rest itself.
69
+
70
+ `Otlp` is the one builder with defaults: `Otlp.defaultServiceName` is `flows`
71
+ and `Otlp.defaultServiceVersion` is this package's release version. Name your
72
+ own service in production, so a collector holding several Smithers processes
73
+ can tell them apart.
@@ -0,0 +1,106 @@
1
+ ---
2
+ title: "Validation at layer acquisition"
3
+ description: "Export failure is absorbed by design, so a misconfigured exporter looks exactly like a working one. Endpoints and resources are therefore decoded when the layer is built, and refused with typed errors."
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ An exporter that cannot deliver must not take the application down with it. A
9
+ collector outage is not an application outage, so Effect's exporter absorbs
10
+ export failure: it retries a transient failure three times, then temporarily
11
+ disables delivery, and the effect that produced the span never learns any of
12
+ it.
13
+
14
+ That is the right behavior, and it creates one hazard. A layer built against
15
+ `""`, `localhost:4318`, or an endpoint with a trailing newline behaves
16
+ identically to a working one: it builds, it runs, it fails nothing, and it
17
+ delivers nothing forever. Nobody notices until an operator goes looking for a
18
+ trace that was never sent.
19
+
20
+ ## Acquisition is the only place to report it
21
+
22
+ So both configuration inputs are decoded while the layer is being built, before
23
+ any exporter exists:
24
+
25
+ - The collector endpoint, by `Endpoint.decode`, failing with
26
+ `Endpoint.InvalidExporterEndpoint`.
27
+ - The service identity and resource attributes, by `Resource.decode`, failing
28
+ with `Resource.InvalidResourceConfiguration`.
29
+
30
+ Both are typed failures in the layer's error channel, which means a composition
31
+ sees them at startup, in the place where the value was written, rather than as
32
+ silence in a dashboard weeks later. `Otlp.layer`, `Otlp.layerFetch`, and
33
+ `NodeOtel.layerOtel` all decode their endpoint; every builder decodes its
34
+ resource.
35
+
36
+ ## What an endpoint must be
37
+
38
+ An absolute `http://` or `https://` URL, at most 2,048 characters, carrying no
39
+ username, password, query, fragment, backslashes, spaces, or control characters.
40
+ Base paths such as `https://collector.example/tenant/9` are supported.
41
+
42
+ Queries and fragments are refused because exporters append `/v1/<signal>` to
43
+ the base. Appending it after `?tenant=9` or `#notes` would leave the HTTP request
44
+ path unchanged, silently sending telemetry to the wrong route. Use exporter
45
+ headers for authentication, not credentials embedded in the URL.
46
+
47
+ The last clause is the one that surprises people, and it is the whole reason
48
+ `Endpoint` exists rather than a bare `new URL` check. The WHATWG URL parser is a
49
+ repairer, not a validator: it strips leading and trailing spaces and C0
50
+ controls, and removes tab, newline, and carriage return from anywhere in its
51
+ input. So `new URL("http://collector:4318\n")` succeeds, and reports a
52
+ well-formed URL, while the untrimmed original is what a builder would hand its
53
+ exporter. An endpoint read from a config file with a trailing newline, or
54
+ pasted with a leading space, is the most common shape of this mistake, and it
55
+ produces exactly the silent no-delivery the refusal exists to prevent. No legal
56
+ collector endpoint carries one of those characters, so refusing them costs
57
+ nothing.
58
+
59
+ Repeated trailing separators are normalized away instead of refused:
60
+ `http://host//` and `http://host` both post to `http://host/v1/traces`.
61
+
62
+ ## What a resource must be
63
+
64
+ `Resource.Configuration` bounds the identity so an accepted value cannot become
65
+ an unencodable payload later:
66
+
67
+ - `serviceName` and `serviceVersion` are non-empty, well formed, and at most
68
+ 1,024 UTF-16 code units.
69
+ - At most 256 attributes, with non-empty, well formed keys of at most 1,024
70
+ code units.
71
+ - Attribute values are finite numbers, booleans, strings of at most 65,536 code
72
+ units, or homogeneous arrays of one of those scalar types with at most 256
73
+ elements (`Resource.maximumAttributeArrayLength`).
74
+ - The complete OTLP JSON resource is at most 128 KiB
75
+ (`Resource.maximumResourceBytes`), including identity, SDK-added
76
+ `telemetry.sdk.name`, `telemetry.sdk.language` and `telemetry.sdk.version`,
77
+ keys, values, array wrappers, escaping and UTF-8. SDK fields are reserved even for the default Effect
78
+ exporter. Counting stops as soon as the budget is exceeded;
79
+ the value-free refusal names `attributes`, the measured lower bound and limit.
80
+ Per-field limits alone cannot guarantee this cumulative bound.
81
+ - Resource metadata is explicit. The default OTLP and Node SDK layers isolate
82
+ ambient resource configuration so it cannot enlarge metadata after admission.
83
+ - The 1 MiB transport reserves 8 KiB for the JSON envelope and escaped scope
84
+ name, which in a metrics request repeats the service name, leaving 888 KiB
85
+ (`Otlp.reservedBatchBytes`) for a signal batch. This is
86
+ about 909 bytes per record at the upstream 1,000-record log or span limit,
87
+ enough for ordinary batches; application records can still be too large.
88
+ - NUL and unpaired UTF-16 surrogates are refused anywhere. Valid astral Unicode
89
+ is preserved.
90
+
91
+ An empty `serviceName` is refused rather than defaulted, because anonymous
92
+ telemetry in a shared collector is worse than none.
93
+
94
+ ## Refusals never carry the rejected value
95
+
96
+ Both errors report a stable `code`, the `path` of the option the bad value
97
+ arrived on, and a message. Neither retains the value itself: `baseUrl` is the
98
+ field most likely to carry a token in a query string or a credential in its
99
+ userinfo, and an error message is the least controlled surface in a system. The
100
+ `path` is what you need to find the value, and you already have the value.
101
+
102
+ The `path` names the caller's own option, so a refusal from `Otlp` says
103
+ `baseUrl` and one from `NodeOtel` says `endpoint`.
104
+
105
+ For what to do when you see one, see
106
+ [Troubleshooting](../troubleshooting.md).
@@ -0,0 +1,190 @@
1
+ ---
2
+ title: "Export to an OTLP collector"
3
+ description: "Wire Otlp.layerFetch into a running program: the collector endpoint, the service identity, authentication headers, export cadence, the shutdown flush, and what happens when the collector is down."
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ `Otlp` posts logs, metrics, and traces to an OTLP/HTTP collector as JSON. This
9
+ guide covers the options you set once at startup and the behavior you should
10
+ expect from them afterwards.
11
+
12
+ ## Provide the layer
13
+
14
+ ```ts
15
+ import * as Otlp from "@smthrs/observability/Otlp"
16
+ import * as Effect from "effect/Effect"
17
+
18
+ const telemetry = Otlp.layerFetch({
19
+ baseUrl: "http://localhost:4318",
20
+ serviceName: "deploy-status"
21
+ })
22
+
23
+ // `program` is your application effect, unchanged from its non-telemetry form.
24
+ const outcome = program.pipe(Effect.provide(telemetry), Effect.scoped)
25
+ ```
26
+
27
+ The layer is scoped: give it a lifetime with `Effect.scoped`, or build it as
28
+ part of a runtime that owns a scope. Signals post below `baseUrl` at
29
+ `/v1/logs`, `/v1/metrics`, and `/v1/traces`, so a base URL with a path prefix
30
+ is honored: `http://collector:4318/tenant/9` posts to
31
+ `http://collector:4318/tenant/9/v1/traces`.
32
+
33
+ `Otlp.layer` is the same wiring without the `fetch` binding. Use it when the
34
+ host must supply its own HTTP client:
35
+
36
+ ```ts
37
+ import * as NodeHost from "@smthrs/platform-node/NodeHost"
38
+ import * as Layer from "effect/Layer"
39
+
40
+ const telemetry = Otlp.layer({ baseUrl: "http://localhost:4318" }).pipe(
41
+ Layer.provide(NodeHost.NodeHttpClient.layerUndici)
42
+ )
43
+ ```
44
+
45
+ ## Name the service
46
+
47
+ `serviceName` and `serviceVersion` become the `service.name` and
48
+ `service.version` resource attributes on every exported signal, and they are
49
+ how a collector holding several processes tells them apart. Omitted, they fall
50
+ back to `Otlp.defaultServiceName` (`flows`) and `Otlp.defaultServiceVersion`
51
+ (this package's release version), which is a reasonable default for a Smithers
52
+ CLI process and a poor one for your application.
53
+
54
+ Add deployment facts as `attributes`:
55
+
56
+ ```ts
57
+ const telemetry = Otlp.layerFetch({
58
+ baseUrl: "https://otlp.example.com",
59
+ serviceName: "deploy-status",
60
+ serviceVersion: "2.4.1",
61
+ attributes: {
62
+ "deployment.environment.name": "production",
63
+ "service.instance.id": process.env.HOSTNAME ?? "local"
64
+ }
65
+ })
66
+ ```
67
+
68
+ Attribute values are strings, finite numbers, booleans, or homogeneous arrays
69
+ of those. The full bounds are in
70
+ [Validation at layer acquisition](../concepts/validated-acquisition.md).
71
+
72
+ ## Authenticate
73
+
74
+ `headers` is sent with every export request, which is where a vendor token
75
+ goes:
76
+
77
+ ```ts
78
+ const telemetry = Otlp.layerFetch({
79
+ baseUrl: "https://otlp.example.com",
80
+ serviceName: "deploy-status",
81
+ headers: { authorization: "Bearer YOUR_TOKEN" }
82
+ })
83
+ ```
84
+
85
+ Read the token from the environment or your secret store. A credential in the
86
+ URL is refused: an endpoint carrying userinfo fails layer acquisition. A
87
+ credential header (`authorization`, `x-api-key`, `x-honeycomb-team`, and
88
+ similar names) over plaintext `http://` is refused too, unless the collector is
89
+ on `localhost`, `127.0.0.0/8`, or `[::1]`. Non-credential headers such as a
90
+ tenant id work on any endpoint. The check reads header names only, so use
91
+ `https://` for every remote collector.
92
+
93
+ Fetch redirects are refused, including same-origin redirects. Configure the
94
+ collector's final URL. Other HTTP transports must refuse redirects themselves.
95
+ For fetch options such as `credentials: "omit"`, provide
96
+ `FetchHttpClient.RequestInit` around the whole exporting effect:
97
+
98
+ ```ts
99
+ import * as FetchHttpClient from "effect/http/FetchHttpClient"
100
+
101
+ const outcome = program.pipe(
102
+ Effect.provide(telemetry),
103
+ Effect.provideService(FetchHttpClient.RequestInit, { credentials: "omit" }),
104
+ Effect.scoped
105
+ )
106
+ ```
107
+
108
+ Options supplied only to the inner HTTP-client layer are replaced by the
109
+ redirect policy. Ambient options are retained except `redirect`, which is
110
+ always `"manual"`. Redirect responses fail export through the existing failure
111
+ handling below; they never forward credentials or signal bodies.
112
+
113
+ ## Control the cadence and the flush
114
+
115
+ `exportInterval` sets how often all three signals batch and post. Omitted, each
116
+ signal keeps Effect's own default. `shutdownTimeout` bounds the final flush
117
+ when the layer's scope closes.
118
+
119
+ ```ts
120
+ const telemetry = Otlp.layerFetch({
121
+ baseUrl: "http://localhost:4318",
122
+ serviceName: "deploy-status",
123
+ exportInterval: "10 seconds",
124
+ shutdownTimeout: "5 seconds"
125
+ })
126
+ ```
127
+
128
+ Closing the scope is the deterministic flush. A short program may deliver
129
+ nothing on the interval and everything at shutdown, so read what a collector
130
+ received only after the scope has closed.
131
+
132
+ ## Turn export off explicitly
133
+
134
+ `Otlp.layerNoop` provides nothing and exports nothing. It exists so a host that
135
+ has no collector, or a browser build that has not opted in, switches layers
136
+ rather than branching around a missing provide:
137
+
138
+ ```ts
139
+ const telemetry = collectorUrl === undefined
140
+ ? Otlp.layerNoop
141
+ : Otlp.layerFetch({ baseUrl: collectorUrl, serviceName: "deploy-status" })
142
+ ```
143
+
144
+ ## What the collector receives
145
+
146
+ Every request is OTLP/HTTP JSON. Its `user-agent` is
147
+ `OTel-OTLP-Exporter-JavaScript-Effect-OtlpTracer/` and the Effect version, with
148
+ `OtlpLogger` or `OtlpMetrics` for the other two signals, after any `user-agent`
149
+ you set in `headers`.
150
+
151
+ | Part | What it carries |
152
+ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
153
+ | Resource | `telemetry.sdk.name` (`effect`), `telemetry.sdk.language` (`nodejs` or `webjs`) and `telemetry.sdk.version` (the Effect version), then your `attributes`, `service.name` and `service.version`. |
154
+ | Scope | Spans and log records name their scope `effect`, with the Effect version. Metrics name their scope for your service. |
155
+ | Spans | Status `1` on success. Status `2` on failure, with the first error's message and one `exception` event per error. Status `0` and the attribute `effect.fiber.interrupted` on interruption. Failure text and string attributes are redacted before they leave. |
156
+ | Log records | Your annotations as attributes, plus `effect.fiberId` and, for each log span, `effect.log_span.<label>` holding the elapsed milliseconds as a number. A record logged with a cause adds `exception.type`, `exception.message` and `exception.stacktrace`. |
157
+ | Metrics | Counters, gauges and histograms under the names the producing package declares. A timer's unit is `ms`. A histogram lists every boundary it declares in `explicitBounds` and counts values above the last one in a final bucket. |
158
+
159
+ The names of the spans themselves are in
160
+ [Instrumentation and export](../concepts/instrumentation-and-export.md#spans-effect-names).
161
+
162
+ ## What happens when the collector is down
163
+
164
+ Export failure never fails your program, and it never surfaces as a rejected
165
+ promise. Effect's exporter retries a transient failure three times, honoring a
166
+ `retry-after` response header on any retried status when one is present, then
167
+ disables that exporter for 60 seconds and logs a `Debug` record saying so.
168
+ Spans and records produced inside that window are dropped, and delivery resumes
169
+ afterwards.
170
+
171
+ The exporter reads a response's status and `retry-after` header and nothing
172
+ else. Each exchange ends when the status arrives, so a collector that accepts a
173
+ batch and never finishes its answer does not hold up the next one.
174
+
175
+ Two consequences worth planning for:
176
+
177
+ - A dead collector is invisible at `Info`. Run at `Debug` while you are
178
+ bringing an exporter up, or watch the collector side.
179
+ - A configuration mistake and a collector outage look the same after
180
+ acquisition. That is why the endpoint is decoded before any exporter exists;
181
+ see [Troubleshooting](../troubleshooting.md) when nothing arrives.
182
+
183
+ ## Next steps
184
+
185
+ - [Test telemetry without a collector](./testing.md): assert on what would have
186
+ been posted.
187
+ - [Wire an OpenTelemetry SDK](./wire-an-opentelemetry-sdk.md): when a collector
188
+ endpoint is not enough.
189
+ - [Read the runtime metrics](./read-runtime-metrics.md): what the exported
190
+ series mean.