@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,325 @@
1
+ /**
2
+ * Explicit, validated OpenTelemetry resource metadata for Smithers.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+
7
+ import * as OtelResource from "@effect/opentelemetry/Resource"
8
+ import type { Attributes as OtelAttributes } from "@opentelemetry/api"
9
+ import * as Effect from "effect/Effect"
10
+ import * as Layer from "effect/Layer"
11
+ import * as OtlpResource from "effect/observability/OtlpResource"
12
+ import * as Schema from "effect/Schema"
13
+ import { schemaIssueMessage, schemaIssuePath } from "./internal/schemaIssuePath.ts"
14
+
15
+ /**
16
+ * Largest service-name or service-version field accepted by a resource.
17
+ *
18
+ * @category constants
19
+ * @since 1.0.0-rc.0
20
+ */
21
+ export const maximumIdentityLength = 1_024
22
+
23
+ /**
24
+ * Largest attribute key accepted by a resource.
25
+ *
26
+ * @category constants
27
+ * @since 1.0.0-rc.0
28
+ */
29
+ export const maximumAttributeKeyLength = 1_024
30
+
31
+ /**
32
+ * Largest string value accepted by one resource attribute.
33
+ *
34
+ * @category constants
35
+ * @since 1.0.0-rc.0
36
+ */
37
+ export const maximumAttributeStringLength = 65_536
38
+
39
+ /**
40
+ * Largest number of elements accepted in one array attribute value.
41
+ *
42
+ * @category constants
43
+ * @since 1.0.0-rc.0
44
+ */
45
+ export const maximumAttributeArrayLength = 256
46
+
47
+ /**
48
+ * Largest number of attributes accepted by one resource.
49
+ *
50
+ * @category constants
51
+ * @since 1.0.0-rc.0
52
+ */
53
+ export const maximumAttributes = 256
54
+
55
+ /**
56
+ * Largest OTLP/JSON encoding accepted for one whole resource, in UTF-8 bytes.
57
+ *
58
+ * The measure is the OTLP `Resource` message the exporters place in every
59
+ * request, `{"attributes":[{"key":…,"value":{…}}],"droppedAttributesCount":0}`
60
+ * with service identity and SDK-added `telemetry.sdk.name`,
61
+ * `telemetry.sdk.language` and `telemetry.sdk.version` included, after JSON
62
+ * escaping and UTF-8 encoding. The SDK's own values are reserved even for the
63
+ * default Effect exporter, whose values are shorter. A caller attribute that
64
+ * replaces an SDK field, or that service identity overwrites, is counted
65
+ * beside it. It is the bound the per-field limits cannot express: 256
66
+ * attributes at the string ceiling would encode to 16 MiB, and the resource
67
+ * rides in every export request, so the default transport, which discards a
68
+ * request over 1 MiB, would deliver nothing at all. 128 KiB admits one
69
+ * ASCII attribute at the string ceiling and leaves that transport 888 KiB of every
70
+ * request for the signal batch; see `Otlp.reservedBatchBytes`.
71
+ *
72
+ * @category constants
73
+ * @since 1.0.0-rc.0
74
+ */
75
+ export const maximumResourceBytes = 131_072
76
+
77
+ const loneSurrogate = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/
78
+ const embeddedNul = new RegExp(String.fromCharCode(0))
79
+
80
+ const isWellFormed = (value: string): boolean => !loneSurrogate.test(value) && !embeddedNul.test(value)
81
+
82
+ const identity = Schema.NonEmptyString.check(
83
+ Schema.isMaxLength(maximumIdentityLength),
84
+ Schema.makeFilter((value: string) => isWellFormed(value), { title: "wellFormedResourceIdentity" })
85
+ )
86
+
87
+ const attributeString = Schema.String.check(
88
+ Schema.isMaxLength(maximumAttributeStringLength),
89
+ Schema.makeFilter((value: string) => isWellFormed(value), { title: "wellFormedAttributeString" })
90
+ )
91
+
92
+ const attributeNumber = Schema.Number.check(
93
+ Schema.makeFilter((value: number) => Number.isFinite(value), { title: "finiteAttributeNumber" })
94
+ )
95
+
96
+ /**
97
+ * Runtime schema for one OpenTelemetry resource attribute value.
98
+ *
99
+ * @category schemas
100
+ * @since 1.0.0-rc.0
101
+ */
102
+ export const AttributeValue = Schema.Union([
103
+ attributeString,
104
+ attributeNumber,
105
+ Schema.Boolean,
106
+ Schema.Array(attributeString),
107
+ Schema.Array(attributeNumber),
108
+ Schema.Array(Schema.Boolean)
109
+ ]).check(
110
+ Schema.makeFilter(
111
+ (value) =>
112
+ !Array.isArray(value) || value.length <= maximumAttributeArrayLength || {
113
+ path: [],
114
+ issue: `holds ${value.length} elements, over the ${maximumAttributeArrayLength} element limit`
115
+ },
116
+ { title: "boundedResourceAttributeArrays" }
117
+ )
118
+ )
119
+
120
+ /**
121
+ * Runtime schema for OpenTelemetry resource attributes.
122
+ *
123
+ * @category schemas
124
+ * @since 1.0.0-rc.0
125
+ */
126
+ export const Attributes = Schema.Record(Schema.String, AttributeValue).check(
127
+ Schema.makeFilter(
128
+ (attributes: Readonly<Record<string, unknown>>) => Object.keys(attributes).length <= maximumAttributes,
129
+ { title: "boundedResourceAttributes" }
130
+ ),
131
+ Schema.makeFilter(
132
+ (attributes: Readonly<Record<string, unknown>>) =>
133
+ Object.keys(attributes).every(
134
+ (key) => key.length > 0 && key.length <= maximumAttributeKeyLength && isWellFormed(key)
135
+ ),
136
+ { title: "wellFormedResourceAttributeKeys" }
137
+ )
138
+ )
139
+
140
+ const encoder = new TextEncoder()
141
+
142
+ /**
143
+ * Counts OTLP JSON fragments, including keys, wrappers, escaping and UTF-8.
144
+ * Stops at the first fragment over budget: the refusal reports a lower bound.
145
+ * A configuration may reuse one large string in thousands of array slots, so
146
+ * serializing the whole resource before checking could allocate gigabytes.
147
+ */
148
+ const encodedResourceBytes = (configuration: {
149
+ readonly serviceName: string
150
+ readonly serviceVersion?: string | undefined
151
+ readonly attributes?: Record<string, unknown> | undefined
152
+ }): number => {
153
+ const bytes = (value: unknown) => encoder.encode(JSON.stringify(value)).byteLength
154
+ const identityAttributes = OtelResource.configToAttributes({
155
+ serviceName: configuration.serviceName,
156
+ ...(configuration.serviceVersion === undefined ? {} : { serviceVersion: configuration.serviceVersion })
157
+ })
158
+ // Use the pinned SDK projection so its added metadata cannot escape the
159
+ // complete-resource ceiling. Both exporters use these OTLP AnyValue shapes.
160
+ let total = bytes({
161
+ attributes: OtlpResource.entriesToAttributes(Object.entries(identityAttributes)),
162
+ droppedAttributesCount: 0
163
+ })
164
+ for (const [key, value] of Object.entries(configuration.attributes ?? {})) {
165
+ // An identity attribute is always present, so every addition needs a comma.
166
+ total += 1 + bytes({ key, value: Array.isArray(value) ? { arrayValue: { values: [] } } : null })
167
+ if (Array.isArray(value)) {
168
+ for (const [index, element] of value.entries()) {
169
+ total += (index === 0 ? 0 : 1) + bytes(OtlpResource.unknownToAttributeValue(element))
170
+ if (total > maximumResourceBytes) return total
171
+ }
172
+ } else {
173
+ total += bytes(OtlpResource.unknownToAttributeValue(value)) - 4 // replace JSON null
174
+ }
175
+ if (total > maximumResourceBytes) return total
176
+ }
177
+ return total
178
+ }
179
+
180
+ /**
181
+ * Runtime schema for the service identity attached to exported telemetry.
182
+ *
183
+ * @category schemas
184
+ * @since 1.0.0-rc.0
185
+ */
186
+ export const Configuration = Schema.Struct({
187
+ serviceName: identity,
188
+ serviceVersion: Schema.optional(identity),
189
+ attributes: Schema.optional(Attributes)
190
+ }).check(
191
+ Schema.makeFilter(
192
+ (configuration: {
193
+ readonly serviceName: string
194
+ readonly serviceVersion?: string | undefined
195
+ readonly attributes?: Record<string, unknown> | undefined
196
+ }) => {
197
+ const bytes = encodedResourceBytes(configuration)
198
+ // Only attributes can carry a resource past the budget: the two identity
199
+ // fields encode to at most 6 KiB each, so the refusal points there.
200
+ return bytes <= maximumResourceBytes || {
201
+ path: ["attributes"],
202
+ issue: `bring the resource to at least ${bytes} bytes of OTLP JSON, over the ${maximumResourceBytes} byte limit`
203
+ }
204
+ },
205
+ { title: "boundedResourceBytes" }
206
+ )
207
+ )
208
+
209
+ /**
210
+ * Configuration used to identify the service emitting telemetry.
211
+ *
212
+ * @category models
213
+ * @since 1.0.0-rc.0
214
+ */
215
+ export type Configuration = typeof Configuration.Type
216
+
217
+ /**
218
+ * Stable resource-configuration refusal shared by every OTEL layer.
219
+ *
220
+ * @category errors
221
+ * @since 1.0.0-rc.0
222
+ */
223
+ export class InvalidResourceConfiguration extends Schema.TaggedError<InvalidResourceConfiguration>()(
224
+ "@smthrs/observability/InvalidResourceConfiguration",
225
+ {
226
+ code: Schema.Literal("invalid_resource_configuration"),
227
+ path: Schema.String,
228
+ message: Schema.String
229
+ }
230
+ ) {}
231
+
232
+ const invalid = (cause: unknown): InvalidResourceConfiguration => {
233
+ const path = schemaIssuePath(cause, "resource")
234
+ return new InvalidResourceConfiguration({
235
+ code: "invalid_resource_configuration",
236
+ path,
237
+ message: `OpenTelemetry resource ${path} ${schemaIssueMessage(cause) ?? "is invalid"}`
238
+ })
239
+ }
240
+
241
+ /**
242
+ * Decodes one resource configuration without retaining rejected values.
243
+ *
244
+ * @category decoding
245
+ * @since 1.0.0-rc.0
246
+ */
247
+ export const decode = (
248
+ configuration: unknown
249
+ ): Effect.Effect<Configuration, InvalidResourceConfiguration> =>
250
+ Schema.decodeUnknownEffect(Configuration)(configuration).pipe(Effect.mapError(invalid))
251
+
252
+ /**
253
+ * Decodes one resource configuration for the package's pure projection API.
254
+ *
255
+ * @category decoding
256
+ * @since 1.0.0-rc.0
257
+ */
258
+ export const decodeSync = (configuration: unknown): Configuration => {
259
+ try {
260
+ return Schema.decodeUnknownSync(Configuration)(configuration)
261
+ } catch (cause) {
262
+ throw invalid(cause)
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Projects a decoded resource into the exact optional-property shape expected
268
+ * by the OpenTelemetry SDK.
269
+ *
270
+ * @category conversions
271
+ * @since 1.0.0-rc.0
272
+ */
273
+ export const toOpenTelemetryConfiguration = (
274
+ configuration: Configuration
275
+ ): {
276
+ readonly serviceName: string
277
+ readonly serviceVersion?: string
278
+ readonly attributes?: OtelAttributes
279
+ } => ({
280
+ serviceName: configuration.serviceName,
281
+ ...(configuration.serviceVersion === undefined ? {} : { serviceVersion: configuration.serviceVersion }),
282
+ ...(configuration.attributes === undefined
283
+ ? {}
284
+ : {
285
+ attributes: Object.fromEntries(
286
+ Object.entries(configuration.attributes).map(([key, value]) => [
287
+ key,
288
+ Array.isArray(value) ? [...value] : value
289
+ ])
290
+ ) as OtelAttributes
291
+ })
292
+ })
293
+
294
+ /**
295
+ * Converts explicit service metadata into OpenTelemetry resource attributes.
296
+ *
297
+ * No environment variables are read. Invalid metadata throws the same typed
298
+ * {@link InvalidResourceConfiguration} every layer returns during acquisition.
299
+ *
300
+ * @category conversions
301
+ * @since 1.0.0-rc.0
302
+ */
303
+ export const configToAttributes = (configuration: Configuration): OtelAttributes =>
304
+ OtelResource.configToAttributes(toOpenTelemetryConfiguration(decodeSync(configuration)))
305
+
306
+ /**
307
+ * Provides an explicitly validated OpenTelemetry resource.
308
+ *
309
+ * @category layers
310
+ * @since 1.0.0-rc.0
311
+ */
312
+ export const layer = (
313
+ configuration: Configuration
314
+ ): Layer.Layer<OtelResource.Resource, InvalidResourceConfiguration> =>
315
+ Layer.unwrap(
316
+ Effect.map(decode(configuration), (decoded) => OtelResource.layer(toOpenTelemetryConfiguration(decoded)))
317
+ )
318
+
319
+ /**
320
+ * The OpenTelemetry resource service.
321
+ *
322
+ * @category services
323
+ * @since 1.0.0-rc.0
324
+ */
325
+ export const Resource = OtelResource.Resource
package/src/index.ts ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Observability for flows: the default OTLP export wiring plus the
3
+ * Effect-native logger, metric, and OpenTelemetry resource layers.
4
+ *
5
+ * The store packages define and update their own metric handles
6
+ * (`JournalMetrics`, `RunStoreMetrics`, `CacheStoreMetrics`,
7
+ * `ArtifactStoreMetrics`, `DatabaseMetrics`) and open spans through Effect's
8
+ * tracer; this package is the exporter they deliberately leave out. `Otlp`
9
+ * only composes what `effect` already ships, so it is browser-bundleable. The
10
+ * remaining modules are the fuller stack folded in from the agent workspace:
11
+ * a structured `Logger`, a `JournalLogger` that mirrors log events into the
12
+ * run journal, `Metric` helpers, the `Resource` descriptor, and the `Otel`
13
+ * layer the OpenTelemetry SDK wiring installs behind.
14
+ *
15
+ * `NodeOtel` and `BrowserOtel` are deliberately NOT re-exported here. Each
16
+ * resolves a host-specific OpenTelemetry SDK. `NodeOtel` reaches Node-only
17
+ * host modules through `@effect/opentelemetry/NodeSdk` and
18
+ * `@opentelemetry/sdk-trace-node`, including the bare `async_hooks` specifier
19
+ * `@opentelemetry/context-async-hooks` imports, so re-exporting it would put a
20
+ * module a browser bundler cannot resolve in the root entry and break the
21
+ * browser bundle this package guarantees. Import them by subpath instead:
22
+ * `@smthrs/observability/NodeOtel`.
23
+ *
24
+ * @since 0.1.0
25
+ */
26
+
27
+ /**
28
+ * @category layers
29
+ * @since 0.1.0
30
+ */
31
+ export * as Otlp from "./Otlp.ts"
32
+
33
+ /**
34
+ * @category observability
35
+ * @since 1.0.0-rc.0
36
+ */
37
+ export * as Endpoint from "./Endpoint.ts"
38
+
39
+ /**
40
+ * @category observability
41
+ * @since 0.1.0
42
+ */
43
+ export * as JournalLogger from "./JournalLogger.ts"
44
+
45
+ /**
46
+ * @category observability
47
+ * @since 0.1.0
48
+ */
49
+ export * as Logger from "./Logger.ts"
50
+
51
+ /**
52
+ * @category observability
53
+ * @since 0.1.0
54
+ */
55
+ export * as Metric from "./Metric.ts"
56
+
57
+ /**
58
+ * @category observability
59
+ * @since 0.1.0
60
+ */
61
+ export * as Otel from "./Otel.ts"
62
+
63
+ /**
64
+ * @category observability
65
+ * @since 0.1.0
66
+ */
67
+ export * as Resource from "./Resource.ts"
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The decoder-issue walk shared by this package's refusals.
3
+ *
4
+ * `JournalLogger` and `Resource` both publish the path of the option a decode
5
+ * rejected, and `Resource` also publishes the measured size a budget filter
6
+ * attached to its refusal. Effect's issues nest the same way for both, so the
7
+ * traversal lives once and a decoder change is followed once.
8
+ *
9
+ * @private
10
+ * @since 1.0.0-rc.0
11
+ */
12
+
13
+ interface IssueLeaf {
14
+ readonly segments: ReadonlyArray<string>
15
+ readonly leaf: unknown
16
+ }
17
+
18
+ /**
19
+ * Walks a decode failure to its first offending leaf, collecting the path
20
+ * segments passed on the way. The walk is bounded so a self-referential issue
21
+ * tree cannot spin.
22
+ */
23
+ const walk = (error: unknown): IssueLeaf => {
24
+ let issue = (error as { readonly issue?: unknown } | null)?.issue
25
+ const segments: Array<string> = []
26
+ for (let depth = 0; depth < 64 && typeof issue === "object" && issue !== null; depth++) {
27
+ const node = issue as { readonly path?: unknown; readonly issue?: unknown; readonly issues?: unknown }
28
+ if (Array.isArray(node.path)) segments.push(...node.path.map(String))
29
+ if (node.issue !== undefined) {
30
+ issue = node.issue
31
+ continue
32
+ }
33
+ if (Array.isArray(node.issues) && node.issues[0] !== undefined) {
34
+ issue = node.issues[0]
35
+ continue
36
+ }
37
+ break
38
+ }
39
+ return { segments, leaf: issue }
40
+ }
41
+
42
+ /**
43
+ * Walks a decode failure to the dotted path of the value it refused.
44
+ *
45
+ * Returns the caller's domain name when the failure carries no path at all.
46
+ *
47
+ * @private
48
+ * @since 1.0.0-rc.0
49
+ */
50
+ export const schemaIssuePath = (error: unknown, fallback: string): string => walk(error).segments.join(".") || fallback
51
+
52
+ /**
53
+ * Reads the message a filter attached to the value a decode refused, when the
54
+ * filter attached one. None of the Effect checks this package composes attach
55
+ * one, so a refusal only ever carries text this package wrote, never the
56
+ * rejected value.
57
+ *
58
+ * @private
59
+ * @since 1.0.0-rc.0
60
+ */
61
+ export const schemaIssueMessage = (error: unknown): string | undefined => {
62
+ const leaf = walk(error).leaf as { readonly annotations?: { readonly message?: unknown } } | null | undefined
63
+ const message = leaf?.annotations?.message
64
+ return typeof message === "string" ? message : undefined
65
+ }
@@ -1,104 +0,0 @@
1
- version: "3.9"
2
-
3
- services:
4
- otel-collector:
5
- image: otel/opentelemetry-collector-contrib:0.148.0
6
- restart: unless-stopped
7
- command: ["--config", "/etc/otelcol/config.yml"]
8
- volumes:
9
- - ./otel-collector-config.yml:/etc/otelcol/config.yml:ro
10
- ports:
11
- - "4317:4317" # gRPC
12
- - "4318:4318" # HTTP (Smithers sends here)
13
- - "8889:8889" # Prometheus exporter scrape endpoint
14
- depends_on:
15
- tempo:
16
- condition: service_healthy
17
- loki:
18
- condition: service_healthy
19
- healthcheck:
20
- test: ["CMD", "/otelcol-contrib", "--version"]
21
- interval: 10s
22
- timeout: 5s
23
- retries: 12
24
- start_period: 10s
25
-
26
- loki:
27
- image: grafana/loki:3.3.2
28
- restart: unless-stopped
29
- command: ["-config.file=/etc/loki/local-config.yaml"]
30
- volumes:
31
- - ./loki/loki-config.yaml:/etc/loki/local-config.yaml:ro
32
- - ./data/loki:/loki
33
- ports:
34
- - "3100:3100"
35
- healthcheck:
36
- test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1:3100/ready"]
37
- interval: 10s
38
- timeout: 5s
39
- retries: 18
40
- start_period: 10s
41
-
42
- prometheus:
43
- image: prom/prometheus:v3.2.0
44
- restart: unless-stopped
45
- volumes:
46
- - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
47
- - ./data/prometheus:/prometheus
48
- ports:
49
- - "9090:9090"
50
- depends_on:
51
- otel-collector:
52
- condition: service_healthy
53
- healthcheck:
54
- test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1:9090/-/ready"]
55
- interval: 10s
56
- timeout: 5s
57
- retries: 18
58
- start_period: 10s
59
-
60
- tempo:
61
- image: grafana/tempo:2.7.0
62
- restart: unless-stopped
63
- command: ["-config.file=/etc/tempo/tempo.yml"]
64
- volumes:
65
- - ./tempo/tempo.yml:/etc/tempo/tempo.yml:ro
66
- - ./data/tempo:/tmp/tempo
67
- ports:
68
- - "3200:3200" # Tempo query API
69
- - "4317" # OTLP gRPC (internal)
70
- healthcheck:
71
- test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1:3200/api/search"]
72
- interval: 10s
73
- timeout: 5s
74
- retries: 24
75
- start_period: 20s
76
-
77
- grafana:
78
- image: grafana/grafana:11.5.0
79
- restart: unless-stopped
80
- environment:
81
- # Local dev default is "admin"; override via env for anything shared.
82
- - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:-admin}
83
- # Anonymous browsing stays on for frictionless local dev, but read-only.
84
- - GF_AUTH_ANONYMOUS_ENABLED=${GF_AUTH_ANONYMOUS_ENABLED:-true}
85
- - GF_AUTH_ANONYMOUS_ORG_ROLE=${GF_AUTH_ANONYMOUS_ORG_ROLE:-Viewer}
86
- volumes:
87
- - ./grafana/provisioning:/etc/grafana/provisioning:ro
88
- - ./grafana/dashboards:/var/lib/grafana/dashboards:ro
89
- - ./data/grafana:/var/lib/grafana
90
- ports:
91
- - "3001:3000"
92
- depends_on:
93
- prometheus:
94
- condition: service_healthy
95
- tempo:
96
- condition: service_healthy
97
- loki:
98
- condition: service_healthy
99
- healthcheck:
100
- test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1:3000/api/health"]
101
- interval: 10s
102
- timeout: 5s
103
- retries: 24
104
- start_period: 20s