@livestore/utils 0.0.0

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 (322) hide show
  1. package/dist/.tsbuildinfo.json +1 -0
  2. package/dist/Deferred.d.ts +10 -0
  3. package/dist/Deferred.d.ts.map +1 -0
  4. package/dist/Deferred.js +18 -0
  5. package/dist/Deferred.js.map +1 -0
  6. package/dist/NoopTracer.d.ts +9 -0
  7. package/dist/NoopTracer.d.ts.map +1 -0
  8. package/dist/NoopTracer.js +54 -0
  9. package/dist/NoopTracer.js.map +1 -0
  10. package/dist/base64.d.ts +12 -0
  11. package/dist/base64.d.ts.map +1 -0
  12. package/dist/base64.js +114 -0
  13. package/dist/base64.js.map +1 -0
  14. package/dist/binary.d.ts +4 -0
  15. package/dist/binary.d.ts.map +1 -0
  16. package/dist/binary.js +23 -0
  17. package/dist/binary.js.map +1 -0
  18. package/dist/browser.d.ts +3 -0
  19. package/dist/browser.d.ts.map +1 -0
  20. package/dist/browser.js +28 -0
  21. package/dist/browser.js.map +1 -0
  22. package/dist/effect/Debounce.d.ts +5 -0
  23. package/dist/effect/Debounce.d.ts.map +1 -0
  24. package/dist/effect/Debounce.js +33 -0
  25. package/dist/effect/Debounce.js.map +1 -0
  26. package/dist/effect/Effect.d.ts +7 -0
  27. package/dist/effect/Effect.d.ts.map +1 -0
  28. package/dist/effect/Effect.js +17 -0
  29. package/dist/effect/Effect.js.map +1 -0
  30. package/dist/effect/EndableQueue.d.ts +11 -0
  31. package/dist/effect/EndableQueue.d.ts.map +1 -0
  32. package/dist/effect/EndableQueue.js +22 -0
  33. package/dist/effect/EndableQueue.js.map +1 -0
  34. package/dist/effect/EnvVar.d.ts +16 -0
  35. package/dist/effect/EnvVar.d.ts.map +1 -0
  36. package/dist/effect/EnvVar.js +21 -0
  37. package/dist/effect/EnvVar.js.map +1 -0
  38. package/dist/effect/Error.d.ts +12 -0
  39. package/dist/effect/Error.d.ts.map +1 -0
  40. package/dist/effect/Error.js +13 -0
  41. package/dist/effect/Error.js.map +1 -0
  42. package/dist/effect/Gate.d.ts +14 -0
  43. package/dist/effect/Gate.d.ts.map +1 -0
  44. package/dist/effect/Gate.js +17 -0
  45. package/dist/effect/Gate.js.map +1 -0
  46. package/dist/effect/Layer.d.ts +6 -0
  47. package/dist/effect/Layer.d.ts.map +1 -0
  48. package/dist/effect/Layer.js +11 -0
  49. package/dist/effect/Layer.js.map +1 -0
  50. package/dist/effect/Otel/Dummy.d.ts +5 -0
  51. package/dist/effect/Otel/Dummy.d.ts.map +1 -0
  52. package/dist/effect/Otel/Dummy.js +22 -0
  53. package/dist/effect/Otel/Dummy.js.map +1 -0
  54. package/dist/effect/Otel/Meter.d.ts +20 -0
  55. package/dist/effect/Otel/Meter.d.ts.map +1 -0
  56. package/dist/effect/Otel/Meter.js +76 -0
  57. package/dist/effect/Otel/Meter.js.map +1 -0
  58. package/dist/effect/Otel/OtlpGrpc.d.ts +6 -0
  59. package/dist/effect/Otel/OtlpGrpc.d.ts.map +1 -0
  60. package/dist/effect/Otel/OtlpGrpc.js +42 -0
  61. package/dist/effect/Otel/OtlpGrpc.js.map +1 -0
  62. package/dist/effect/Otel/OtlpHttp.d.ts +6 -0
  63. package/dist/effect/Otel/OtlpHttp.d.ts.map +1 -0
  64. package/dist/effect/Otel/OtlpHttp.js +42 -0
  65. package/dist/effect/Otel/OtlpHttp.js.map +1 -0
  66. package/dist/effect/Otel/OtlpWebsocket.d.ts +6 -0
  67. package/dist/effect/Otel/OtlpWebsocket.d.ts.map +1 -0
  68. package/dist/effect/Otel/OtlpWebsocket.js +42 -0
  69. package/dist/effect/Otel/OtlpWebsocket.js.map +1 -0
  70. package/dist/effect/Otel/Span.d.ts +32 -0
  71. package/dist/effect/Otel/Span.d.ts.map +1 -0
  72. package/dist/effect/Otel/Span.js +97 -0
  73. package/dist/effect/Otel/Span.js.map +1 -0
  74. package/dist/effect/Otel/Tracer.d.ts +15 -0
  75. package/dist/effect/Otel/Tracer.d.ts.map +1 -0
  76. package/dist/effect/Otel/Tracer.js +17 -0
  77. package/dist/effect/Otel/Tracer.js.map +1 -0
  78. package/dist/effect/Otel/index.d.ts +8 -0
  79. package/dist/effect/Otel/index.d.ts.map +1 -0
  80. package/dist/effect/Otel/index.js +9 -0
  81. package/dist/effect/Otel/index.js.map +1 -0
  82. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpGrpc.d.ts +14 -0
  83. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpGrpc.d.ts.map +1 -0
  84. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpGrpc.js +15 -0
  85. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpGrpc.js.map +1 -0
  86. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpHttp.d.ts +14 -0
  87. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpHttp.d.ts.map +1 -0
  88. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpHttp.js +15 -0
  89. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpHttp.js.map +1 -0
  90. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpWebsocket.d.ts +19 -0
  91. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpWebsocket.d.ts.map +1 -0
  92. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpWebsocket.js +17 -0
  93. package/dist/effect/Otel/lib-metrics/ExporterMetricsOltpWebsocket.js.map +1 -0
  94. package/dist/effect/Otel/lib-metrics/MetricsProvider.d.ts +10 -0
  95. package/dist/effect/Otel/lib-metrics/MetricsProvider.d.ts.map +1 -0
  96. package/dist/effect/Otel/lib-metrics/MetricsProvider.js +4 -0
  97. package/dist/effect/Otel/lib-metrics/MetricsProvider.js.map +1 -0
  98. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderGrpc.d.ts +16 -0
  99. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderGrpc.d.ts.map +1 -0
  100. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderGrpc.js +39 -0
  101. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderGrpc.js.map +1 -0
  102. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderHttp.d.ts +16 -0
  103. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderHttp.d.ts.map +1 -0
  104. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderHttp.js +39 -0
  105. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderHttp.js.map +1 -0
  106. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderWebsocket.d.ts +16 -0
  107. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderWebsocket.d.ts.map +1 -0
  108. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderWebsocket.js +39 -0
  109. package/dist/effect/Otel/lib-metrics/OTLPMetricsProviderWebsocket.js.map +1 -0
  110. package/dist/effect/Otel/lib-metrics/PeriodicMetricsProvider.d.ts +17 -0
  111. package/dist/effect/Otel/lib-metrics/PeriodicMetricsProvider.d.ts.map +1 -0
  112. package/dist/effect/Otel/lib-metrics/PeriodicMetricsProvider.js +27 -0
  113. package/dist/effect/Otel/lib-metrics/PeriodicMetricsProvider.js.map +1 -0
  114. package/dist/effect/Otel/lib-tracer/BatchSpanProcessor.d.ts +18 -0
  115. package/dist/effect/Otel/lib-tracer/BatchSpanProcessor.d.ts.map +1 -0
  116. package/dist/effect/Otel/lib-tracer/BatchSpanProcessor.js +31 -0
  117. package/dist/effect/Otel/lib-tracer/BatchSpanProcessor.js.map +1 -0
  118. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpGrpc.d.ts +19 -0
  119. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpGrpc.d.ts.map +1 -0
  120. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpGrpc.js +36 -0
  121. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpGrpc.js.map +1 -0
  122. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpHttp.d.ts +19 -0
  123. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpHttp.d.ts.map +1 -0
  124. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpHttp.js +36 -0
  125. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpHttp.js.map +1 -0
  126. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpWebsocket.d.ts +9 -0
  127. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpWebsocket.d.ts.map +1 -0
  128. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpWebsocket.js +29 -0
  129. package/dist/effect/Otel/lib-tracer/ExporterTraceOtlpWebsocket.js.map +1 -0
  130. package/dist/effect/Otel/lib-tracer/SimpleProcessor.d.ts +19 -0
  131. package/dist/effect/Otel/lib-tracer/SimpleProcessor.d.ts.map +1 -0
  132. package/dist/effect/Otel/lib-tracer/SimpleProcessor.js +25 -0
  133. package/dist/effect/Otel/lib-tracer/SimpleProcessor.js.map +1 -0
  134. package/dist/effect/Otel/lib-tracer/TracerProvider.d.ts +10 -0
  135. package/dist/effect/Otel/lib-tracer/TracerProvider.d.ts.map +1 -0
  136. package/dist/effect/Otel/lib-tracer/TracerProvider.js +7 -0
  137. package/dist/effect/Otel/lib-tracer/TracerProvider.js.map +1 -0
  138. package/dist/effect/Otel/lib-tracer/WebProvider.d.ts +18 -0
  139. package/dist/effect/Otel/lib-tracer/WebProvider.d.ts.map +1 -0
  140. package/dist/effect/Otel/lib-tracer/WebProvider.js +25 -0
  141. package/dist/effect/Otel/lib-tracer/WebProvider.js.map +1 -0
  142. package/dist/effect/ReadonlyArray.d.ts +4 -0
  143. package/dist/effect/ReadonlyArray.d.ts.map +1 -0
  144. package/dist/effect/ReadonlyArray.js +11 -0
  145. package/dist/effect/ReadonlyArray.js.map +1 -0
  146. package/dist/effect/RequestResolver.d.ts +11 -0
  147. package/dist/effect/RequestResolver.d.ts.map +1 -0
  148. package/dist/effect/RequestResolver.js +18 -0
  149. package/dist/effect/RequestResolver.js.map +1 -0
  150. package/dist/effect/STM.d.ts +3 -0
  151. package/dist/effect/STM.d.ts.map +1 -0
  152. package/dist/effect/STM.js +3 -0
  153. package/dist/effect/STM.js.map +1 -0
  154. package/dist/effect/Schedule.d.ts +5 -0
  155. package/dist/effect/Schedule.d.ts.map +1 -0
  156. package/dist/effect/Schedule.js +7 -0
  157. package/dist/effect/Schedule.js.map +1 -0
  158. package/dist/effect/Scheduler.d.ts +49 -0
  159. package/dist/effect/Scheduler.d.ts.map +1 -0
  160. package/dist/effect/Scheduler.js +168 -0
  161. package/dist/effect/Scheduler.js.map +1 -0
  162. package/dist/effect/Schema/SchemaHash.d.ts +3 -0
  163. package/dist/effect/Schema/SchemaHash.d.ts.map +1 -0
  164. package/dist/effect/Schema/SchemaHash.js +15 -0
  165. package/dist/effect/Schema/SchemaHash.js.map +1 -0
  166. package/dist/effect/Schema/SchemaHash.test.d.ts +2 -0
  167. package/dist/effect/Schema/SchemaHash.test.d.ts.map +1 -0
  168. package/dist/effect/Schema/SchemaHash.test.js +13 -0
  169. package/dist/effect/Schema/SchemaHash.test.js.map +1 -0
  170. package/dist/effect/Schema/SchemaJsonWrapper.d.ts +11 -0
  171. package/dist/effect/Schema/SchemaJsonWrapper.d.ts.map +1 -0
  172. package/dist/effect/Schema/SchemaJsonWrapper.js +38 -0
  173. package/dist/effect/Schema/SchemaJsonWrapper.js.map +1 -0
  174. package/dist/effect/Schema/SchemaJsonWrapper.test.d.ts +2 -0
  175. package/dist/effect/Schema/SchemaJsonWrapper.test.d.ts.map +1 -0
  176. package/dist/effect/Schema/SchemaJsonWrapper.test.js +42 -0
  177. package/dist/effect/Schema/SchemaJsonWrapper.test.js.map +1 -0
  178. package/dist/effect/Schema/index.d.ts +15 -0
  179. package/dist/effect/Schema/index.d.ts.map +1 -0
  180. package/dist/effect/Schema/index.js +14 -0
  181. package/dist/effect/Schema/index.js.map +1 -0
  182. package/dist/effect/ServiceContext.d.ts +39 -0
  183. package/dist/effect/ServiceContext.d.ts.map +1 -0
  184. package/dist/effect/ServiceContext.js +61 -0
  185. package/dist/effect/ServiceContext.js.map +1 -0
  186. package/dist/effect/SmartQueue.d.ts +38 -0
  187. package/dist/effect/SmartQueue.d.ts.map +1 -0
  188. package/dist/effect/SmartQueue.js +123 -0
  189. package/dist/effect/SmartQueue.js.map +1 -0
  190. package/dist/effect/Stream/chainSwitch.d.ts +3 -0
  191. package/dist/effect/Stream/chainSwitch.d.ts.map +1 -0
  192. package/dist/effect/Stream/chainSwitch.js +48 -0
  193. package/dist/effect/Stream/chainSwitch.js.map +1 -0
  194. package/dist/effect/Stream/index.d.ts +37 -0
  195. package/dist/effect/Stream/index.d.ts.map +1 -0
  196. package/dist/effect/Stream/index.js +82 -0
  197. package/dist/effect/Stream/index.js.map +1 -0
  198. package/dist/effect/SubscriptionRef.d.ts +10 -0
  199. package/dist/effect/SubscriptionRef.d.ts.map +1 -0
  200. package/dist/effect/SubscriptionRef.js +8 -0
  201. package/dist/effect/SubscriptionRef.js.map +1 -0
  202. package/dist/effect/TimeoutGate.d.ts +13 -0
  203. package/dist/effect/TimeoutGate.d.ts.map +1 -0
  204. package/dist/effect/TimeoutGate.js +41 -0
  205. package/dist/effect/TimeoutGate.js.map +1 -0
  206. package/dist/effect/WebCrypto.d.ts +18 -0
  207. package/dist/effect/WebCrypto.d.ts.map +1 -0
  208. package/dist/effect/WebCrypto.js +56 -0
  209. package/dist/effect/WebCrypto.js.map +1 -0
  210. package/dist/effect/WebLock.d.ts +5 -0
  211. package/dist/effect/WebLock.d.ts.map +1 -0
  212. package/dist/effect/WebLock.js +20 -0
  213. package/dist/effect/WebLock.js.map +1 -0
  214. package/dist/effect/browser.d.ts +19 -0
  215. package/dist/effect/browser.d.ts.map +1 -0
  216. package/dist/effect/browser.js +82 -0
  217. package/dist/effect/browser.js.map +1 -0
  218. package/dist/effect/fetch.d.ts +89 -0
  219. package/dist/effect/fetch.d.ts.map +1 -0
  220. package/dist/effect/fetch.js +142 -0
  221. package/dist/effect/fetch.js.map +1 -0
  222. package/dist/effect/index.d.ts +50 -0
  223. package/dist/effect/index.d.ts.map +1 -0
  224. package/dist/effect/index.js +58 -0
  225. package/dist/effect/index.js.map +1 -0
  226. package/dist/global.d.ts +5 -0
  227. package/dist/global.d.ts.map +1 -0
  228. package/dist/global.js +2 -0
  229. package/dist/global.js.map +1 -0
  230. package/dist/guards.d.ts +6 -0
  231. package/dist/guards.d.ts.map +1 -0
  232. package/dist/guards.js +6 -0
  233. package/dist/guards.js.map +1 -0
  234. package/dist/index.d.ts +69 -0
  235. package/dist/index.d.ts.map +1 -0
  236. package/dist/index.js +162 -0
  237. package/dist/index.js.map +1 -0
  238. package/dist/object/index.d.ts +10 -0
  239. package/dist/object/index.d.ts.map +1 -0
  240. package/dist/object/index.js +10 -0
  241. package/dist/object/index.js.map +1 -0
  242. package/dist/object/omit.d.ts +3 -0
  243. package/dist/object/omit.d.ts.map +1 -0
  244. package/dist/object/omit.js +14 -0
  245. package/dist/object/omit.js.map +1 -0
  246. package/dist/object/pick.d.ts +14 -0
  247. package/dist/object/pick.d.ts.map +1 -0
  248. package/dist/object/pick.js +17 -0
  249. package/dist/object/pick.js.map +1 -0
  250. package/dist/promise.d.ts +6 -0
  251. package/dist/promise.d.ts.map +1 -0
  252. package/dist/promise.js +27 -0
  253. package/dist/promise.js.map +1 -0
  254. package/dist/set.d.ts +2 -0
  255. package/dist/set.d.ts.map +1 -0
  256. package/dist/set.js +10 -0
  257. package/dist/set.js.map +1 -0
  258. package/dist/single-item.d.ts +8 -0
  259. package/dist/single-item.d.ts.map +1 -0
  260. package/dist/single-item.js +9 -0
  261. package/dist/single-item.js.map +1 -0
  262. package/dist/string.d.ts +3 -0
  263. package/dist/string.d.ts.map +1 -0
  264. package/dist/string.js +3 -0
  265. package/dist/string.js.map +1 -0
  266. package/dist/time.d.ts +12 -0
  267. package/dist/time.d.ts.map +1 -0
  268. package/dist/time.js +22 -0
  269. package/dist/time.js.map +1 -0
  270. package/dist/types/index.d.ts +2 -0
  271. package/dist/types/index.d.ts.map +1 -0
  272. package/dist/types/index.js +2 -0
  273. package/dist/types/index.js.map +1 -0
  274. package/dist/types/json.d.ts +27 -0
  275. package/dist/types/json.d.ts.map +1 -0
  276. package/dist/types/json.js +2 -0
  277. package/dist/types/json.js.map +1 -0
  278. package/package.json +58 -0
  279. package/src/Deferred.ts +24 -0
  280. package/src/NoopTracer.ts +75 -0
  281. package/src/base64.ts +118 -0
  282. package/src/browser.ts +32 -0
  283. package/src/effect/Effect.ts +27 -0
  284. package/src/effect/Error.ts +12 -0
  285. package/src/effect/Otel/Dummy.ts +32 -0
  286. package/src/effect/Otel/Meter.ts +145 -0
  287. package/src/effect/Otel/OtlpGrpc.ts +75 -0
  288. package/src/effect/Otel/OtlpHttp.ts +75 -0
  289. package/src/effect/Otel/OtlpWebsocket.ts +75 -0
  290. package/src/effect/Otel/Span.ts +222 -0
  291. package/src/effect/Otel/Tracer.ts +30 -0
  292. package/src/effect/Otel/index.ts +8 -0
  293. package/src/effect/Otel/lib-metrics/ExporterMetricsOltpGrpc.ts +39 -0
  294. package/src/effect/Otel/lib-metrics/ExporterMetricsOltpHttp.ts +39 -0
  295. package/src/effect/Otel/lib-metrics/ExporterMetricsOltpWebsocket.ts +47 -0
  296. package/src/effect/Otel/lib-metrics/MetricsProvider.ts +12 -0
  297. package/src/effect/Otel/lib-metrics/OTLPMetricsProviderGrpc.ts +77 -0
  298. package/src/effect/Otel/lib-metrics/OTLPMetricsProviderHttp.ts +77 -0
  299. package/src/effect/Otel/lib-metrics/OTLPMetricsProviderWebsocket.ts +80 -0
  300. package/src/effect/Otel/lib-metrics/PeriodicMetricsProvider.ts +55 -0
  301. package/src/effect/Otel/lib-tracer/BatchSpanProcessor.ts +58 -0
  302. package/src/effect/Otel/lib-tracer/ExporterTraceOtlpGrpc.ts +64 -0
  303. package/src/effect/Otel/lib-tracer/ExporterTraceOtlpHttp.ts +64 -0
  304. package/src/effect/Otel/lib-tracer/ExporterTraceOtlpWebsocket.ts +38 -0
  305. package/src/effect/Otel/lib-tracer/README.md +1 -0
  306. package/src/effect/Otel/lib-tracer/SimpleProcessor.ts +46 -0
  307. package/src/effect/Otel/lib-tracer/TracerProvider.ts +16 -0
  308. package/src/effect/Otel/lib-tracer/WebProvider.ts +48 -0
  309. package/src/effect/Schedule.ts +12 -0
  310. package/src/effect/ServiceContext.ts +116 -0
  311. package/src/effect/index.ts +65 -0
  312. package/src/global.ts +5 -0
  313. package/src/guards.ts +8 -0
  314. package/src/index.ts +217 -0
  315. package/src/object/index.ts +24 -0
  316. package/src/object/omit.ts +17 -0
  317. package/src/object/pick.ts +27 -0
  318. package/src/promise.ts +43 -0
  319. package/src/set.ts +10 -0
  320. package/src/string.ts +2 -0
  321. package/src/time.ts +25 -0
  322. package/tsconfig.json +13 -0
@@ -0,0 +1,145 @@
1
+ import * as Context from '@effect/data/Context'
2
+ import { identity, pipe } from '@effect/data/Function'
3
+ import * as Effect from '@effect/io/Effect'
4
+ import * as Layer from '@effect/io/Layer'
5
+ import type * as OTMetrics from '@opentelemetry/api-metrics'
6
+
7
+ import { MetricsProvider } from './lib-metrics/MetricsProvider.js'
8
+
9
+ export const MeterSymbol = Symbol.for('effect-otel/Meter')
10
+ export type MeterSymbol = typeof MeterSymbol
11
+
12
+ export interface Meter {
13
+ readonly [MeterSymbol]: MeterSymbol
14
+ readonly meter: OTMetrics.Meter
15
+ }
16
+
17
+ export const Meter = Context.Tag<Meter>(MeterSymbol)
18
+
19
+ export const makeMeter = (name: string) =>
20
+ Effect.gen(function* ($) {
21
+ const { metricsProvider } = yield* $(MetricsProvider)
22
+
23
+ const meter = yield* $(Effect.sync(() => metricsProvider.getMeter(name)))
24
+
25
+ return identity<Meter>({
26
+ [MeterSymbol]: MeterSymbol,
27
+ meter,
28
+ })
29
+ })
30
+
31
+ export const LiveMeter = Layer.scoped(Meter, makeMeter('@effect/otel/Meter'))
32
+
33
+ type MetricCache = {
34
+ histograms: Map<string, OTMetrics.Histogram>
35
+ gauges: Map<string, { counter: OTMetrics.Counter; prevValue: number }>
36
+ // gauges: Map<string, { observable: OTMetrics.ObservableGauge; currentCallback: OTMetrics.ObservableCallback }>
37
+ upDownCounters: Map<string, OTMetrics.Counter>
38
+ }
39
+
40
+ const metricCache: MetricCache = {
41
+ histograms: new Map(),
42
+ gauges: new Map(),
43
+ upDownCounters: new Map(),
44
+ }
45
+
46
+ export const histogram =
47
+ (metricName: string, value: number, attributes?: OTMetrics.MetricAttributes) =>
48
+ <R, E, A>(effect: Effect.Effect<R, E, A>) =>
49
+ Effect.tap(effect, () =>
50
+ pipe(
51
+ Effect.map(Meter, ({ meter }) =>
52
+ getOrCreate(metricCache.histograms, metricName, () => meter.createHistogram(metricName)),
53
+ ),
54
+ Effect.tap((histogram) => Effect.sync(() => histogram.record(value, attributes))),
55
+ ),
56
+ )
57
+
58
+ export const histogramEff =
59
+ <R2>(metricName: string, valueEff: Effect.Effect<R2, never, number>) =>
60
+ <R, E, A>(effect: Effect.Effect<R, E, A>) =>
61
+ Effect.tap(effect, () =>
62
+ pipe(
63
+ Effect.map(Meter, ({ meter }) =>
64
+ getOrCreate(metricCache.histograms, metricName, () => meter.createHistogram(metricName)),
65
+ ),
66
+ Effect.tap((histogram) => Effect.map(valueEff, (value) => histogram.record(value))),
67
+ ),
68
+ )
69
+
70
+ export const upDownCounter =
71
+ (metricName: string, delta: number, attributes?: OTMetrics.MetricAttributes) =>
72
+ <R, E, A>(effect: Effect.Effect<R, E, A>) =>
73
+ Effect.tap(effect, () =>
74
+ pipe(
75
+ Effect.map(Meter, ({ meter }) =>
76
+ getOrCreate(metricCache.upDownCounters, metricName, () => meter.createUpDownCounter(metricName)),
77
+ ),
78
+ Effect.tap((counter) => Effect.sync(() => counter.add(delta, attributes))),
79
+ ),
80
+ )
81
+
82
+ /** NOTE we're using an up-down-counter here (which is push based) instead of an observable gauge (which is pull based) */
83
+ export const gauge =
84
+ (metricName: string, value: number, attributes?: OTMetrics.MetricAttributes) =>
85
+ <R, E, A>(effect: Effect.Effect<R, E, A>) => {
86
+ // NOTE this is currently used to keep separate gauges for each attribute value
87
+ const metricCacheName = metricName + '_' + JSON.stringify(attributes)
88
+ return Effect.tap(effect, () =>
89
+ pipe(
90
+ Effect.map(Meter, ({ meter }) =>
91
+ getOrCreate(metricCache.gauges, metricCacheName, () => ({
92
+ counter: meter.createUpDownCounter(metricName),
93
+ prevValue: 0,
94
+ })),
95
+ ),
96
+ Effect.tap(({ counter, prevValue }) =>
97
+ Effect.sync(() => {
98
+ const delta = value - prevValue
99
+ counter.add(delta, attributes)
100
+ metricCache.gauges.set(metricCacheName, { counter, prevValue: value })
101
+ }),
102
+ ),
103
+ ),
104
+ )
105
+ }
106
+
107
+ // export const gauge =
108
+ // (metricName: string, value: number, attributes?: OTMetrics.MetricAttributes) =>
109
+ // <R, E, A>(effect: Effect.Effect<R, E, A>) => {
110
+ // // NOTE this is currently used to keep separate gauges for each attribute value
111
+ // const metricCacheName = metricName + '_' + JSON.stringify(attributes)
112
+ // return pipe(
113
+ // effect,
114
+ // Effect.tap(() =>
115
+ // pipe(
116
+ // withMeter((meter) =>
117
+ // getOrCreate(metricCache.gauges, metricCacheName, () => ({
118
+ // observable: meter.createObservableGauge(metricName),
119
+ // currentCallback: () => {},
120
+ // })),
121
+ // ),
122
+ // Effect.tap(({ observable, currentCallback }) =>
123
+ // Effect.succeedWith(() => {
124
+ // observable.removeCallback(currentCallback)
125
+ // const newCallback: OTMetrics.ObservableCallback = (observableResult) => {
126
+ // observableResult.observe(value, attributes)
127
+ // }
128
+ // observable.addCallback(newCallback)
129
+ // metricCache.gauges.set(metricCacheName, { observable, currentCallback: newCallback })
130
+ // }),
131
+ // ),
132
+ // ),
133
+ // ),
134
+ // )
135
+ // }
136
+
137
+ const getOrCreate = <T>(map: Map<string, T>, name: string, create: () => T) => {
138
+ const cached = map.get(name)
139
+ if (cached) {
140
+ return cached
141
+ }
142
+ const created = create()
143
+ map.set(name, created)
144
+ return created
145
+ }
@@ -0,0 +1,75 @@
1
+ import * as Layer from '@effect/io/Layer'
2
+ import type { ResourceAttributes } from '@opentelemetry/resources'
3
+ import { Resource } from '@opentelemetry/resources'
4
+ import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
5
+
6
+ import * as Otel from './index.js'
7
+ import { makeOTLPMetricExporterConfigLayer } from './lib-metrics/ExporterMetricsOltpGrpc.js'
8
+ import { OTLPMetricsProvider } from './lib-metrics/OTLPMetricsProviderGrpc.js'
9
+ import { BatchProcessor } from './lib-tracer/BatchSpanProcessor.js'
10
+ import * as GrpcExporter from './lib-tracer/ExporterTraceOtlpGrpc.js'
11
+ import * as OTWeb from './lib-tracer/WebProvider.js'
12
+ import { LiveMeter } from './Meter.js'
13
+
14
+ //
15
+ // TRACING
16
+ //
17
+
18
+ const makeWebTracingProvider = (serviceName: string, resourceAttributes?: ResourceAttributes) =>
19
+ OTWeb.WebProvider({
20
+ resource: new Resource({
21
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
22
+ ...resourceAttributes,
23
+ }),
24
+ })
25
+
26
+ const TraceCollectorConfig = (exporterUrl?: string) =>
27
+ GrpcExporter.makeOTLPTraceExporterConfigLayer({
28
+ // empty headers makes sure to use XHR instead of `navigator.sendBeacon`
29
+ headers: {},
30
+ url: exporterUrl,
31
+ })
32
+
33
+ const LiveBatchGrpcProcessor = BatchProcessor(GrpcExporter.makeTracingSpanExporter)
34
+
35
+ export const makeWebTracingLayer = (
36
+ serviceName: string,
37
+ exporterUrl?: string,
38
+ resourceAttributes?: ResourceAttributes,
39
+ ): Layer.Layer<never, never, Otel.Tracer> =>
40
+ Layer.provideMerge(
41
+ TraceCollectorConfig(exporterUrl),
42
+ Layer.provide(
43
+ Layer.provideMerge(makeWebTracingProvider(serviceName, resourceAttributes), LiveBatchGrpcProcessor),
44
+ Otel.LiveTracer,
45
+ ),
46
+ )
47
+
48
+ //
49
+ // METRICS
50
+ //
51
+
52
+ const makeWebMetricProvider = (serviceName: string, resourceAttributes?: ResourceAttributes) =>
53
+ OTLPMetricsProvider({
54
+ resource: new Resource({
55
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
56
+ ...resourceAttributes,
57
+ }),
58
+ })
59
+
60
+ const MetricCollectorConfig = (exporterUrl?: string) =>
61
+ makeOTLPMetricExporterConfigLayer({
62
+ // empty headers makes sure to use XHR instead of `navigator.sendBeacon`
63
+ headers: {},
64
+ url: exporterUrl,
65
+ })
66
+
67
+ export const makeWebMetricLayer = (
68
+ serviceName: string,
69
+ exporterUrl?: string,
70
+ resourceAttributes?: ResourceAttributes,
71
+ ): Layer.Layer<never, never, Otel.Meter> =>
72
+ Layer.provide(
73
+ Layer.provideMerge(MetricCollectorConfig(exporterUrl), makeWebMetricProvider(serviceName, resourceAttributes)),
74
+ LiveMeter,
75
+ )
@@ -0,0 +1,75 @@
1
+ import * as Layer from '@effect/io/Layer'
2
+ import type { ResourceAttributes } from '@opentelemetry/resources'
3
+ import { Resource } from '@opentelemetry/resources'
4
+ import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
5
+
6
+ import * as Otel from './index.js'
7
+ import { makeOTLPMetricExporterConfigLayer } from './lib-metrics/ExporterMetricsOltpHttp.js'
8
+ import { OTLPMetricsProvider } from './lib-metrics/OTLPMetricsProviderHttp.js'
9
+ import { BatchProcessor } from './lib-tracer/BatchSpanProcessor.js'
10
+ import * as HttpExporter from './lib-tracer/ExporterTraceOtlpHttp.js'
11
+ import * as OTWeb from './lib-tracer/WebProvider.js'
12
+ import { LiveMeter } from './Meter.js'
13
+
14
+ //
15
+ // TRACING
16
+ //
17
+
18
+ const makeWebTracingProvider = (serviceName: string, resourceAttributes?: ResourceAttributes) =>
19
+ OTWeb.WebProvider({
20
+ resource: new Resource({
21
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
22
+ ...resourceAttributes,
23
+ }),
24
+ })
25
+
26
+ const TraceCollectorConfig = (exporterUrl?: string) =>
27
+ HttpExporter.makeOTLPTraceExporterConfigLayer({
28
+ // empty headers makes sure to use XHR instead of `navigator.sendBeacon`
29
+ headers: {},
30
+ url: exporterUrl,
31
+ })
32
+
33
+ const LiveBatchHttpProcessor = BatchProcessor(HttpExporter.makeTracingSpanExporter)
34
+
35
+ export const makeWebTracingLayer = (
36
+ serviceName: string,
37
+ exporterUrl?: string,
38
+ resourceAttributes?: ResourceAttributes,
39
+ ): Layer.Layer<never, never, Otel.Tracer> =>
40
+ Layer.provideMerge(
41
+ TraceCollectorConfig(exporterUrl),
42
+ Layer.provide(
43
+ Layer.provideMerge(makeWebTracingProvider(serviceName, resourceAttributes), LiveBatchHttpProcessor),
44
+ Otel.LiveTracer,
45
+ ),
46
+ )
47
+
48
+ //
49
+ // METRICS
50
+ //
51
+
52
+ const makeWebMetricProvider = (serviceName: string, resourceAttributes?: ResourceAttributes) =>
53
+ OTLPMetricsProvider({
54
+ resource: new Resource({
55
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
56
+ ...resourceAttributes,
57
+ }),
58
+ })
59
+
60
+ const MetricCollectorConfig = (exporterUrl?: string) =>
61
+ makeOTLPMetricExporterConfigLayer({
62
+ // empty headers makes sure to use XHR instead of `navigator.sendBeacon`
63
+ headers: {},
64
+ url: exporterUrl,
65
+ })
66
+
67
+ export const makeWebMetricLayer = (
68
+ serviceName: string,
69
+ exporterUrl?: string,
70
+ resourceAttributes?: ResourceAttributes,
71
+ ): Layer.Layer<never, never, Otel.Meter> =>
72
+ Layer.provide(
73
+ Layer.provideMerge(MetricCollectorConfig(exporterUrl), makeWebMetricProvider(serviceName, resourceAttributes)),
74
+ LiveMeter,
75
+ )
@@ -0,0 +1,75 @@
1
+ import * as Layer from '@effect/io/Layer'
2
+ import type { ResourceAttributes } from '@opentelemetry/resources'
3
+ import { Resource } from '@opentelemetry/resources'
4
+ import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
5
+
6
+ import * as Otel from './index.js'
7
+ import { makeOTLPMetricExporterConfigLayer } from './lib-metrics/ExporterMetricsOltpWebsocket.js'
8
+ import { OTLPMetricsProvider } from './lib-metrics/OTLPMetricsProviderWebsocket.js'
9
+ import { BatchProcessor } from './lib-tracer/BatchSpanProcessor.js'
10
+ import * as WebSocketExporter from './lib-tracer/ExporterTraceOtlpWebsocket.js'
11
+ import * as OTWeb from './lib-tracer/WebProvider.js'
12
+ import { LiveMeter } from './Meter.js'
13
+
14
+ //
15
+ // TRACING
16
+ //
17
+
18
+ const makeWebTracingProvider = (serviceName: string, resourceAttributes?: ResourceAttributes) =>
19
+ OTWeb.WebProvider({
20
+ resource: new Resource({
21
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
22
+ ...resourceAttributes,
23
+ }),
24
+ })
25
+
26
+ const TraceCollectorConfig = (exporterUrl?: string) =>
27
+ WebSocketExporter.makeOTLPTraceExporterConfigLayer({
28
+ // empty headers makes sure to use XHR instead of `navigator.sendBeacon`
29
+ headers: {},
30
+ url: exporterUrl,
31
+ })
32
+
33
+ const LiveBatchWebsocketProcessor = BatchProcessor(WebSocketExporter.makeTracingSpanExporter)
34
+
35
+ export const makeWebTracingLayer = (
36
+ serviceName: string,
37
+ exporterUrl?: string,
38
+ resourceAttributes?: ResourceAttributes,
39
+ ): Layer.Layer<never, never, Otel.Tracer> =>
40
+ Layer.provideMerge(
41
+ TraceCollectorConfig(exporterUrl),
42
+ Layer.provide(
43
+ Layer.provideMerge(makeWebTracingProvider(serviceName, resourceAttributes), LiveBatchWebsocketProcessor),
44
+ Otel.LiveTracer,
45
+ ),
46
+ )
47
+
48
+ //
49
+ // METRICS
50
+ //
51
+
52
+ const makeWebMetricProvider = (serviceName: string, resourceAttributes?: ResourceAttributes) =>
53
+ OTLPMetricsProvider({
54
+ resource: new Resource({
55
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
56
+ ...resourceAttributes,
57
+ }),
58
+ })
59
+
60
+ const MetricCollectorConfig = (exporterUrl?: string) =>
61
+ makeOTLPMetricExporterConfigLayer({
62
+ // empty headers makes sure to use XHR instead of `navigator.sendBeacon`
63
+ headers: {},
64
+ url: exporterUrl,
65
+ })
66
+
67
+ export const makeWebMetricLayer = (
68
+ serviceName: string,
69
+ exporterUrl?: string,
70
+ resourceAttributes?: ResourceAttributes,
71
+ ): Layer.Layer<never, never, Otel.Meter> =>
72
+ Layer.provide(
73
+ Layer.provideMerge(MetricCollectorConfig(exporterUrl), makeWebMetricProvider(serviceName, resourceAttributes)),
74
+ LiveMeter,
75
+ )
@@ -0,0 +1,222 @@
1
+ import * as Context from '@effect/data/Context'
2
+ import { pipe } from '@effect/data/Function'
3
+ import * as Option from '@effect/data/Option'
4
+ import * as Cause from '@effect/io/Cause'
5
+ import * as Effect from '@effect/io/Effect'
6
+ import * as Exit from '@effect/io/Exit'
7
+ import * as Layer from '@effect/io/Layer'
8
+ import * as Stream from '@effect/stream/Stream'
9
+ import * as otel from '@opentelemetry/api'
10
+
11
+ import { Tracer } from './Tracer.js'
12
+
13
+ export const SpanSymbol = Symbol.for('effect-otel/Span')
14
+ export type SpanSymbol = typeof SpanSymbol
15
+
16
+ // TODO refactor to use 2nd `Context.Tag` type generic instead of symbol
17
+ export interface Span {
18
+ readonly [SpanSymbol]: SpanSymbol
19
+ readonly span: otel.Span
20
+ }
21
+
22
+ export const Span = Context.Tag<Span>(SpanSymbol)
23
+
24
+ export const makeSpan = (span: otel.Span): Span => ({
25
+ [SpanSymbol]: SpanSymbol,
26
+ span,
27
+ })
28
+
29
+ export const requireParentSpan = <R, E, A>(effect: Effect.Effect<R, E, A>): Effect.Effect<R | Span, E, A> => effect
30
+
31
+ export const activeSpanContext: Effect.Effect<Span, never, otel.SpanContext> = Effect.map(Span, (_) =>
32
+ _.span.spanContext(),
33
+ )
34
+
35
+ export const activeContext: Effect.Effect<Span, never, otel.Context> = Effect.flatMap(Span, (_) =>
36
+ Effect.sync(() => otel.trace.setSpan(otel.context.active(), _.span)),
37
+ )
38
+
39
+ // TODO get rid of this
40
+ const inProgressSpans = new Set<otel.Span>()
41
+ // @ts-expect-error `inProgressSpans` is not a global variable
42
+ globalThis.inProgressSpans = inProgressSpans
43
+
44
+ // TODO get rid of this
45
+ export const endInProgressSpans = Effect.sync(() => {
46
+ inProgressSpans.forEach((span) => span.end())
47
+ inProgressSpans.clear()
48
+ })
49
+
50
+ const startSpan = (
51
+ tracer: otel.Tracer,
52
+ context: Context.Context<never>,
53
+ name: string,
54
+ options: otel.SpanOptions | undefined,
55
+ ctx: otel.Context | undefined,
56
+ ): otel.Span => {
57
+ let span: otel.Span
58
+ const maybeSpan = Context.getOption(context, Span)
59
+ if (ctx !== undefined) {
60
+ span = tracer.startSpan(name, options, ctx)
61
+ } else if (options?.root !== true && Option.isSome(maybeSpan)) {
62
+ const ctx = otel.trace.setSpan(otel.context.active(), maybeSpan.value.span)
63
+ span = tracer.startSpan(name, options, ctx)
64
+ } else {
65
+ span = tracer.startSpan(name, { ...options, root: true })
66
+ }
67
+ inProgressSpans.add(span)
68
+ return span
69
+ }
70
+
71
+ const handleExit = <E, A>(span: otel.Span, exit: Exit.Exit<E, A>) =>
72
+ Effect.sync(() => {
73
+ if (Exit.isFailure(exit)) {
74
+ if (Cause.isInterruptedOnly(exit.cause)) {
75
+ // TODO in the future set a special status code for interruption (once Otel supports it)
76
+ span.setStatus({ code: otel.SpanStatusCode.OK, message: Cause.pretty(exit.cause) })
77
+ // NOTE as a workaround we're using the `span.label` attribute which is visible in Grafana
78
+ // See https://github.com/grafana/grafana/pull/50931
79
+ span.setAttribute('span.label', '⚠️ Interrupted️')
80
+ } else {
81
+ span.setStatus({ code: otel.SpanStatusCode.ERROR, message: Cause.pretty(exit.cause) })
82
+ }
83
+ } else {
84
+ span.setStatus({ code: otel.SpanStatusCode.OK })
85
+ }
86
+ inProgressSpans.delete(span)
87
+ span.end()
88
+ })
89
+
90
+ export const withSpan =
91
+ (name: string, options?: otel.SpanOptions, ctx?: otel.Context) =>
92
+ <R, E, A>(effect: Effect.Effect<R, E, A>): Effect.Effect<Exclude<R, Span> | Tracer, E, A> =>
93
+ Effect.flatMap(Tracer, (tracer) =>
94
+ Effect.acquireUseRelease(
95
+ Effect.flatMap(Effect.context<never>(), (context) =>
96
+ Effect.sync(() => startSpan(tracer.tracer, context, name, options, ctx)),
97
+ ),
98
+ (span) => Effect.provideService(effect, Span, makeSpan(span)),
99
+ handleExit,
100
+ ),
101
+ )
102
+
103
+ export const withSpanScoped =
104
+ (name: string, options?: otel.SpanOptions, ctx?: otel.Context) =>
105
+ <R, E, A>(effect: Effect.Effect<R, E, A>) =>
106
+ Effect.flatMap(Tracer, (tracer) => {
107
+ const createSpan = Effect.acquireRelease(
108
+ Effect.flatMap(Effect.context<never>(), (context) =>
109
+ Effect.sync(() => startSpan(tracer.tracer, context, name, options, ctx)),
110
+ ),
111
+ handleExit,
112
+ )
113
+
114
+ return Effect.flatMap(createSpan, (span) => Effect.provideService(effect, Span, makeSpan(span)))
115
+ })
116
+
117
+ export const withSpanStream =
118
+ (name: string, options?: otel.SpanOptions, ctx?: otel.Context) =>
119
+ <R, E, A>(stream: Stream.Stream<R | Span, E, A>): Stream.Stream<Exclude<R, Span> | Tracer, E, A> =>
120
+ Stream.unwrapScoped(
121
+ Effect.flatMap(Tracer, (tracer) =>
122
+ pipe(
123
+ Effect.acquireRelease(
124
+ Effect.flatMap(Effect.context<never>(), (context) =>
125
+ Effect.sync(() => startSpan(tracer.tracer, context, name, options, ctx)),
126
+ ),
127
+ handleExit,
128
+ ),
129
+ Effect.map((span) => Stream.provideService(stream, Span, makeSpan(span))),
130
+ ),
131
+ ),
132
+ )
133
+
134
+ // TODO add optional arg for `Tag` of `Span`
135
+ export const spanLayer: {
136
+ (
137
+ name: string,
138
+ options?: otel.SpanOptions,
139
+ ctx?: otel.Context,
140
+ afterEnded?: (span: otel.Span) => Effect.Effect<never, never, void>,
141
+ ): Layer.Layer<Tracer, never, Span>
142
+ <TIdentifier>(
143
+ name: string,
144
+ options: otel.SpanOptions | undefined,
145
+ ctx: otel.Context | undefined,
146
+ afterEnded: ((span: otel.Span) => Effect.Effect<never, never, void>) | undefined,
147
+ tag: Context.Tag<TIdentifier, Span>,
148
+ ): Layer.Layer<Tracer, never, TIdentifier>
149
+ } = <TIdentifier>(
150
+ name: string,
151
+ options?: otel.SpanOptions,
152
+ ctx?: otel.Context,
153
+ afterEnded?: (span: otel.Span) => Effect.Effect<never, never, void>,
154
+ tag?: Context.Tag<TIdentifier, Span>,
155
+ ): Layer.Layer<Tracer, never, TIdentifier> =>
156
+ Layer.flatMap(Layer.context<Tracer>(), (context) =>
157
+ Layer.scoped(
158
+ tag ?? Span,
159
+ pipe(
160
+ Effect.sync(() => {
161
+ const tracer = Context.get(context, Tracer)
162
+ return startSpan(tracer.tracer, context, name, options, ctx)
163
+ }),
164
+ Effect.map(makeSpan),
165
+ Effect.acquireRelease(({ span }, exit) =>
166
+ pipe(
167
+ handleExit(span, exit),
168
+ Effect.tap(() => {
169
+ if (afterEnded !== undefined) {
170
+ return afterEnded(span)
171
+ }
172
+ return Effect.unit
173
+ }),
174
+ ),
175
+ ),
176
+ ),
177
+ ),
178
+ )
179
+
180
+ export const spanLayerFromContext = (parentSpanCtx: otel.Context) => {
181
+ // const _spanId = otel.trace.getSpan(parentSpanCtx)!.spanContext().spanId
182
+ return Layer.succeed(Span, makeSpan(otel.trace.getSpan(parentSpanCtx)!))
183
+ }
184
+
185
+ export const withSpanLayer =
186
+ (name: string, options?: otel.SpanOptions, ctx?: otel.Context) =>
187
+ <R, E, A>(layer: Layer.Layer<R | Span, E, A>): Layer.Layer<Tracer | Exclude<R, Span>, E, A> =>
188
+ Layer.provide(spanLayer(name, options, ctx), layer)
189
+
190
+ export const addAttribute = (name: string, value: otel.AttributeValue) =>
191
+ Effect.flatMap(Span, ({ span }) =>
192
+ Effect.sync(() => {
193
+ span.setAttribute(name, value)
194
+ }),
195
+ )
196
+
197
+ export const addAttributes = (attributes: otel.Attributes) =>
198
+ Effect.flatMap(Span, ({ span }) =>
199
+ Effect.sync(() => {
200
+ span.setAttributes(attributes)
201
+ }),
202
+ )
203
+
204
+ export const addAttributesEffect = <R, E>(attributes: Effect.Effect<R, E, otel.Attributes>) =>
205
+ Effect.flatMap(attributes, (attributes) =>
206
+ Effect.flatMap(Span, ({ span }) =>
207
+ Effect.sync(() => {
208
+ span.setAttributes(attributes)
209
+ }),
210
+ ),
211
+ )
212
+
213
+ export const addEvent = (
214
+ name: string,
215
+ attributesOrStartTime?: otel.SpanAttributes | otel.TimeInput,
216
+ startTime?: otel.TimeInput,
217
+ ) =>
218
+ Effect.flatMap(Span, ({ span }) =>
219
+ Effect.sync(() => {
220
+ span.addEvent(name, attributesOrStartTime, startTime)
221
+ }),
222
+ )
@@ -0,0 +1,30 @@
1
+ import * as Context from '@effect/data/Context'
2
+ import { identity } from '@effect/data/Function'
3
+ import * as Effect from '@effect/io/Effect'
4
+ import * as Layer from '@effect/io/Layer'
5
+ import type * as otel from '@opentelemetry/api'
6
+
7
+ import { TracerProvider } from './lib-tracer/TracerProvider.js'
8
+
9
+ export const TracerSymbol = Symbol.for('effect-otel/Tracer')
10
+ export type TracerSymbol = typeof TracerSymbol
11
+
12
+ export interface Tracer {
13
+ readonly [TracerSymbol]: TracerSymbol
14
+ readonly tracer: otel.Tracer
15
+ }
16
+
17
+ export const Tracer = Context.Tag<Tracer>(TracerSymbol)
18
+
19
+ export const makeTracer = (name: string) =>
20
+ Effect.gen(function* ($) {
21
+ const { tracerProvider } = yield* $(TracerProvider)
22
+ const tracer = yield* $(Effect.sync(() => tracerProvider.getTracer(name)))
23
+
24
+ return identity<Tracer>({
25
+ [TracerSymbol]: TracerSymbol,
26
+ tracer,
27
+ })
28
+ })
29
+
30
+ export const LiveTracer = Layer.scoped(Tracer, makeTracer('@effect/otel/Tracer'))
@@ -0,0 +1,8 @@
1
+ // otel
2
+ export * from './Meter.js'
3
+ export * from './Tracer.js'
4
+ export * from './Span.js'
5
+ export * from './Dummy.js'
6
+ export * from './lib-tracer/BatchSpanProcessor.js'
7
+ export * from './lib-metrics/MetricsProvider.js'
8
+ export * as OTWeb from './lib-tracer/WebProvider.js'
@@ -0,0 +1,39 @@
1
+ import * as Context from '@effect/data/Context'
2
+ import { pipe } from '@effect/data/Function'
3
+ import * as Effect from '@effect/io/Effect'
4
+ import * as Layer from '@effect/io/Layer'
5
+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc'
6
+ import type { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'
7
+
8
+ import { PeriodicMetricsProvider } from './PeriodicMetricsProvider.js'
9
+
10
+ export interface OTLPMetricExporterConfig {
11
+ readonly _: unique symbol
12
+ }
13
+
14
+ export const OTLPMetricExporterConfig = Context.Tag<OTLPMetricExporterConfig, OTLPExporterNodeConfigBase>(
15
+ 'otel-metric-exporter-config',
16
+ )
17
+
18
+ export const makeOTLPMetricExporterConfigLayer = (config: OTLPExporterNodeConfigBase) =>
19
+ Layer.succeed(OTLPMetricExporterConfig, config)
20
+
21
+ export const makeMetricExporter = Effect.gen(function* (_) {
22
+ const config = yield* _(OTLPMetricExporterConfig)
23
+
24
+ const metricExporter = yield* _(
25
+ pipe(
26
+ Effect.sync(() => new OTLPMetricExporter(config)),
27
+ Effect.acquireRelease((p) =>
28
+ pipe(
29
+ Effect.tryPromise(() => p.shutdown()),
30
+ Effect.orDie,
31
+ ),
32
+ ),
33
+ ),
34
+ )
35
+
36
+ return metricExporter
37
+ })
38
+
39
+ export const LivePeriodicMetricsProvider = PeriodicMetricsProvider(makeMetricExporter)