@dxos/observability 0.8.4-main.a4bbb77 → 0.8.4-main.abd8ff62ef

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 (324) hide show
  1. package/README.md +14 -11
  2. package/dist/lib/browser/chunk-3534PNWM.mjs +13 -0
  3. package/dist/lib/browser/chunk-3534PNWM.mjs.map +7 -0
  4. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  5. package/dist/lib/browser/index.mjs +940 -34
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/log-processor-HPHWNBOK.mjs +38 -0
  8. package/dist/lib/browser/log-processor-HPHWNBOK.mjs.map +7 -0
  9. package/dist/lib/browser/logs-A2VDAHHD.mjs +115 -0
  10. package/dist/lib/browser/logs-A2VDAHHD.mjs.map +7 -0
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/metrics-6OSN54ZV.mjs +115 -0
  13. package/dist/lib/browser/metrics-6OSN54ZV.mjs.map +7 -0
  14. package/dist/lib/browser/traces-browser-6MRGAKFC.mjs +151 -0
  15. package/dist/lib/browser/traces-browser-6MRGAKFC.mjs.map +7 -0
  16. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  17. package/dist/lib/node-esm/chunk-SYPJQI4L.mjs +15 -0
  18. package/dist/lib/node-esm/chunk-SYPJQI4L.mjs.map +7 -0
  19. package/dist/lib/node-esm/index.mjs +962 -34
  20. package/dist/lib/node-esm/index.mjs.map +4 -4
  21. package/dist/lib/node-esm/log-processor-ZODHERST.mjs +39 -0
  22. package/dist/lib/node-esm/log-processor-ZODHERST.mjs.map +7 -0
  23. package/dist/lib/node-esm/logs-TA32MBMW.mjs +116 -0
  24. package/dist/lib/node-esm/logs-TA32MBMW.mjs.map +7 -0
  25. package/dist/lib/node-esm/meta.json +1 -1
  26. package/dist/lib/node-esm/metrics-C5IKPAWD.mjs +116 -0
  27. package/dist/lib/node-esm/metrics-C5IKPAWD.mjs.map +7 -0
  28. package/dist/lib/node-esm/traces-5LKHMVVG.mjs +122 -0
  29. package/dist/lib/node-esm/traces-5LKHMVVG.mjs.map +7 -0
  30. package/dist/types/src/cli-observability-secrets.json +3 -4
  31. package/dist/types/src/extensions/index.d.ts +3 -0
  32. package/dist/types/src/extensions/index.d.ts.map +1 -0
  33. package/dist/types/src/extensions/index.js +6 -0
  34. package/dist/types/src/extensions/index.js.map +1 -0
  35. package/dist/types/src/extensions/otel/extension.d.ts +23 -0
  36. package/dist/types/src/extensions/otel/extension.d.ts.map +1 -0
  37. package/dist/types/src/extensions/otel/extension.js +201 -0
  38. package/dist/types/src/extensions/otel/extension.js.map +1 -0
  39. package/dist/types/src/extensions/otel/index.d.ts +2 -0
  40. package/dist/types/src/extensions/otel/index.d.ts.map +1 -0
  41. package/dist/types/src/extensions/otel/index.js +5 -0
  42. package/dist/types/src/extensions/otel/index.js.map +1 -0
  43. package/dist/types/src/{otel → extensions/otel}/logs.d.ts +4 -3
  44. package/dist/types/src/extensions/otel/logs.d.ts.map +1 -0
  45. package/dist/types/src/{otel → extensions/otel}/logs.js +52 -19
  46. package/dist/types/src/extensions/otel/logs.js.map +1 -0
  47. package/dist/types/src/extensions/otel/metrics.d.ts.map +1 -0
  48. package/dist/types/src/{otel → extensions/otel}/metrics.js +2 -10
  49. package/dist/types/src/extensions/otel/metrics.js.map +1 -0
  50. package/dist/types/src/{otel → extensions/otel}/otel.d.ts +3 -3
  51. package/dist/types/src/extensions/otel/otel.d.ts.map +1 -0
  52. package/dist/types/src/extensions/otel/otel.js.map +1 -0
  53. package/dist/types/src/extensions/otel/span-processors.d.ts +25 -0
  54. package/dist/types/src/extensions/otel/span-processors.d.ts.map +1 -0
  55. package/dist/types/src/extensions/otel/span-processors.js +41 -0
  56. package/dist/types/src/extensions/otel/span-processors.js.map +1 -0
  57. package/dist/types/src/extensions/otel/traces-browser.d.ts +25 -0
  58. package/dist/types/src/extensions/otel/traces-browser.d.ts.map +1 -0
  59. package/dist/types/src/extensions/otel/traces-browser.js +104 -0
  60. package/dist/types/src/extensions/otel/traces-browser.js.map +1 -0
  61. package/dist/types/src/extensions/otel/traces.d.ts +25 -0
  62. package/dist/types/src/extensions/otel/traces.d.ts.map +1 -0
  63. package/dist/types/src/extensions/otel/traces.js +87 -0
  64. package/dist/types/src/extensions/otel/traces.js.map +1 -0
  65. package/dist/types/src/extensions/posthog/extension.d.ts +22 -0
  66. package/dist/types/src/extensions/posthog/extension.d.ts.map +1 -0
  67. package/dist/types/src/extensions/posthog/extension.js +144 -0
  68. package/dist/types/src/extensions/posthog/extension.js.map +1 -0
  69. package/dist/types/src/extensions/posthog/index.d.ts +2 -0
  70. package/dist/types/src/extensions/posthog/index.d.ts.map +1 -0
  71. package/dist/types/src/extensions/posthog/index.js +5 -0
  72. package/dist/types/src/extensions/posthog/index.js.map +1 -0
  73. package/dist/types/src/extensions/posthog/log-processor.d.ts +3 -0
  74. package/dist/types/src/extensions/posthog/log-processor.d.ts.map +1 -0
  75. package/dist/types/src/extensions/posthog/log-processor.js +36 -0
  76. package/dist/types/src/extensions/posthog/log-processor.js.map +1 -0
  77. package/dist/types/src/extensions/posthog/log-processor.test.d.ts +2 -0
  78. package/dist/types/src/extensions/posthog/log-processor.test.d.ts.map +1 -0
  79. package/dist/types/src/extensions/posthog/log-processor.test.js +146 -0
  80. package/dist/types/src/extensions/posthog/log-processor.test.js.map +1 -0
  81. package/dist/types/src/extensions/stub.d.ts +3 -0
  82. package/dist/types/src/extensions/stub.d.ts.map +1 -0
  83. package/dist/types/src/extensions/stub.js +16 -0
  84. package/dist/types/src/extensions/stub.js.map +1 -0
  85. package/dist/types/src/index.d.ts +3 -2
  86. package/dist/types/src/index.d.ts.map +1 -1
  87. package/dist/types/src/index.js +4 -3
  88. package/dist/types/src/index.js.map +1 -1
  89. package/dist/types/src/observability-extension.d.ts +74 -0
  90. package/dist/types/src/observability-extension.d.ts.map +1 -0
  91. package/dist/types/src/observability-extension.js +5 -0
  92. package/dist/types/src/observability-extension.js.map +1 -0
  93. package/dist/types/src/observability.d.ts +32 -110
  94. package/dist/types/src/observability.d.ts.map +1 -1
  95. package/dist/types/src/observability.js +177 -465
  96. package/dist/types/src/observability.js.map +1 -1
  97. package/dist/types/src/observability.test.d.ts +2 -0
  98. package/dist/types/src/observability.test.d.ts.map +1 -0
  99. package/dist/types/src/observability.test.js +312 -0
  100. package/dist/types/src/observability.test.js.map +1 -0
  101. package/dist/types/src/providers/client-observability.d.ts +11 -0
  102. package/dist/types/src/providers/client-observability.d.ts.map +1 -0
  103. package/dist/types/src/providers/client-observability.js +202 -0
  104. package/dist/types/src/providers/client-observability.js.map +1 -0
  105. package/dist/types/src/providers/index.d.ts +4 -0
  106. package/dist/types/src/providers/index.d.ts.map +1 -0
  107. package/dist/types/src/providers/index.js +7 -0
  108. package/dist/types/src/providers/index.js.map +1 -0
  109. package/dist/types/src/providers/ip-data.d.ts +5 -0
  110. package/dist/types/src/providers/ip-data.d.ts.map +1 -0
  111. package/dist/types/src/providers/ip-data.js +57 -0
  112. package/dist/types/src/providers/ip-data.js.map +1 -0
  113. package/dist/types/src/providers/storage.d.ts +3 -0
  114. package/dist/types/src/providers/storage.d.ts.map +1 -0
  115. package/dist/types/src/providers/storage.js +19 -0
  116. package/dist/types/src/providers/storage.js.map +1 -0
  117. package/dist/types/src/storage/browser.d.ts +19 -0
  118. package/dist/types/src/storage/browser.d.ts.map +1 -0
  119. package/dist/types/src/storage/browser.js +69 -0
  120. package/dist/types/src/storage/browser.js.map +1 -0
  121. package/dist/types/src/storage/index.d.ts +2 -0
  122. package/dist/types/src/storage/index.d.ts.map +1 -0
  123. package/dist/types/src/storage/index.js.map +1 -0
  124. package/dist/types/src/storage/node.d.ts +26 -0
  125. package/dist/types/src/storage/node.d.ts.map +1 -0
  126. package/dist/types/src/{helpers/node-observability.js → storage/node.js} +38 -43
  127. package/dist/types/src/storage/node.js.map +1 -0
  128. package/dist/types/src/storage/node.test.d.ts +2 -0
  129. package/dist/types/src/storage/node.test.d.ts.map +1 -0
  130. package/dist/types/src/storage/node.test.js +103 -0
  131. package/dist/types/src/storage/node.test.js.map +1 -0
  132. package/dist/types/tsconfig.tsbuildinfo +1 -1
  133. package/package.json +34 -54
  134. package/src/cli-observability-secrets.json +3 -4
  135. package/src/extensions/index.ts +6 -0
  136. package/src/extensions/otel/extension.ts +258 -0
  137. package/src/extensions/otel/index.ts +5 -0
  138. package/src/extensions/otel/logs.ts +137 -0
  139. package/src/{otel → extensions/otel}/metrics.ts +2 -12
  140. package/src/{otel → extensions/otel}/otel.ts +3 -3
  141. package/src/extensions/otel/span-processors.ts +45 -0
  142. package/src/extensions/otel/traces-browser.ts +139 -0
  143. package/src/extensions/otel/traces.ts +113 -0
  144. package/src/extensions/posthog/extension.ts +181 -0
  145. package/src/extensions/posthog/index.ts +5 -0
  146. package/src/extensions/posthog/log-processor.test.ts +186 -0
  147. package/src/extensions/posthog/log-processor.ts +43 -0
  148. package/src/extensions/stub.ts +19 -0
  149. package/src/index.ts +4 -3
  150. package/src/observability-extension.ts +94 -0
  151. package/src/observability.test.ts +531 -0
  152. package/src/observability.ts +236 -577
  153. package/src/providers/client-observability.ts +255 -0
  154. package/src/providers/index.ts +7 -0
  155. package/src/providers/ip-data.ts +91 -0
  156. package/src/providers/storage.ts +23 -0
  157. package/src/storage/browser.ts +71 -0
  158. package/src/{segment → storage}/index.ts +0 -1
  159. package/src/storage/node.test.ts +129 -0
  160. package/src/{helpers/node-observability.ts → storage/node.ts} +41 -71
  161. package/src/vite-import-meta.d.ts +14 -0
  162. package/dist/lib/browser/chunk-5ICT2XF2.mjs +0 -1
  163. package/dist/lib/browser/chunk-ICKR6U3G.mjs +0 -161
  164. package/dist/lib/browser/chunk-ICKR6U3G.mjs.map +0 -7
  165. package/dist/lib/browser/chunk-LJO63BXO.mjs +0 -164
  166. package/dist/lib/browser/chunk-LJO63BXO.mjs.map +0 -7
  167. package/dist/lib/browser/chunk-YTRUOREY.mjs +0 -1025
  168. package/dist/lib/browser/chunk-YTRUOREY.mjs.map +0 -7
  169. package/dist/lib/browser/observability-CQGG3MID.mjs +0 -10
  170. package/dist/lib/browser/otel-6FVBNA5F.mjs +0 -327
  171. package/dist/lib/browser/otel-6FVBNA5F.mjs.map +0 -7
  172. package/dist/lib/browser/segment/index.mjs +0 -11
  173. package/dist/lib/browser/segment/index.mjs.map +0 -7
  174. package/dist/lib/browser/sentry/index.mjs +0 -24
  175. package/dist/lib/browser/sentry/index.mjs.map +0 -7
  176. package/dist/lib/browser/sentry-log-processor-RG4CFVGL.mjs +0 -162
  177. package/dist/lib/browser/sentry-log-processor-RG4CFVGL.mjs.map +0 -7
  178. package/dist/lib/node-esm/chunk-24NMRR4E.mjs +0 -229
  179. package/dist/lib/node-esm/chunk-24NMRR4E.mjs.map +0 -7
  180. package/dist/lib/node-esm/chunk-4EWQFQ2F.mjs +0 -1026
  181. package/dist/lib/node-esm/chunk-4EWQFQ2F.mjs.map +0 -7
  182. package/dist/lib/node-esm/chunk-QK5IUYVA.mjs +0 -135
  183. package/dist/lib/node-esm/chunk-QK5IUYVA.mjs.map +0 -7
  184. package/dist/lib/node-esm/chunk-QUZL7LKE.mjs +0 -2
  185. package/dist/lib/node-esm/chunk-QUZL7LKE.mjs.map +0 -7
  186. package/dist/lib/node-esm/observability-DHNVVRC7.mjs +0 -11
  187. package/dist/lib/node-esm/observability-DHNVVRC7.mjs.map +0 -7
  188. package/dist/lib/node-esm/otel-KHSGBROB.mjs +0 -310
  189. package/dist/lib/node-esm/otel-KHSGBROB.mjs.map +0 -7
  190. package/dist/lib/node-esm/segment/index.mjs +0 -12
  191. package/dist/lib/node-esm/segment/index.mjs.map +0 -7
  192. package/dist/lib/node-esm/sentry/index.mjs +0 -25
  193. package/dist/lib/node-esm/sentry/index.mjs.map +0 -7
  194. package/dist/lib/node-esm/sentry-log-processor-3BDS4BB4.mjs +0 -163
  195. package/dist/lib/node-esm/sentry-log-processor-3BDS4BB4.mjs.map +0 -7
  196. package/dist/types/src/helpers/browser-observability.d.ts +0 -17
  197. package/dist/types/src/helpers/browser-observability.d.ts.map +0 -1
  198. package/dist/types/src/helpers/browser-observability.js +0 -138
  199. package/dist/types/src/helpers/browser-observability.js.map +0 -1
  200. package/dist/types/src/helpers/common.d.ts +0 -12
  201. package/dist/types/src/helpers/common.d.ts.map +0 -1
  202. package/dist/types/src/helpers/common.js +0 -23
  203. package/dist/types/src/helpers/common.js.map +0 -1
  204. package/dist/types/src/helpers/index.d.ts +0 -6
  205. package/dist/types/src/helpers/index.d.ts.map +0 -1
  206. package/dist/types/src/helpers/index.js +0 -9
  207. package/dist/types/src/helpers/index.js.map +0 -1
  208. package/dist/types/src/helpers/map-spaces.d.ts +0 -18
  209. package/dist/types/src/helpers/map-spaces.d.ts.map +0 -1
  210. package/dist/types/src/helpers/map-spaces.js +0 -36
  211. package/dist/types/src/helpers/map-spaces.js.map +0 -1
  212. package/dist/types/src/helpers/node-observability.d.ts +0 -24
  213. package/dist/types/src/helpers/node-observability.d.ts.map +0 -1
  214. package/dist/types/src/helpers/node-observability.js.map +0 -1
  215. package/dist/types/src/helpers/setup-telemetry-listeners.d.ts +0 -4
  216. package/dist/types/src/helpers/setup-telemetry-listeners.d.ts.map +0 -1
  217. package/dist/types/src/helpers/setup-telemetry-listeners.js +0 -94
  218. package/dist/types/src/helpers/setup-telemetry-listeners.js.map +0 -1
  219. package/dist/types/src/otel/index.d.ts +0 -5
  220. package/dist/types/src/otel/index.d.ts.map +0 -1
  221. package/dist/types/src/otel/index.js +0 -8
  222. package/dist/types/src/otel/index.js.map +0 -1
  223. package/dist/types/src/otel/logs.d.ts.map +0 -1
  224. package/dist/types/src/otel/logs.js.map +0 -1
  225. package/dist/types/src/otel/metrics.d.ts.map +0 -1
  226. package/dist/types/src/otel/metrics.js.map +0 -1
  227. package/dist/types/src/otel/otel.d.ts.map +0 -1
  228. package/dist/types/src/otel/otel.js.map +0 -1
  229. package/dist/types/src/otel/traces-browser.d.ts +0 -8
  230. package/dist/types/src/otel/traces-browser.d.ts.map +0 -1
  231. package/dist/types/src/otel/traces-browser.js +0 -53
  232. package/dist/types/src/otel/traces-browser.js.map +0 -1
  233. package/dist/types/src/otel/traces.d.ts +0 -8
  234. package/dist/types/src/otel/traces.d.ts.map +0 -1
  235. package/dist/types/src/otel/traces.js +0 -46
  236. package/dist/types/src/otel/traces.js.map +0 -1
  237. package/dist/types/src/segment/base.d.ts +0 -15
  238. package/dist/types/src/segment/base.d.ts.map +0 -1
  239. package/dist/types/src/segment/base.js +0 -51
  240. package/dist/types/src/segment/base.js.map +0 -1
  241. package/dist/types/src/segment/browser.d.ts +0 -15
  242. package/dist/types/src/segment/browser.d.ts.map +0 -1
  243. package/dist/types/src/segment/browser.js +0 -63
  244. package/dist/types/src/segment/browser.js.map +0 -1
  245. package/dist/types/src/segment/index.d.ts +0 -3
  246. package/dist/types/src/segment/index.d.ts.map +0 -1
  247. package/dist/types/src/segment/index.js +0 -6
  248. package/dist/types/src/segment/index.js.map +0 -1
  249. package/dist/types/src/segment/node.d.ts +0 -16
  250. package/dist/types/src/segment/node.d.ts.map +0 -1
  251. package/dist/types/src/segment/node.js +0 -84
  252. package/dist/types/src/segment/node.js.map +0 -1
  253. package/dist/types/src/segment/types.d.ts +0 -52
  254. package/dist/types/src/segment/types.d.ts.map +0 -1
  255. package/dist/types/src/segment/types.js +0 -18
  256. package/dist/types/src/segment/types.js.map +0 -1
  257. package/dist/types/src/sentry/browser.d.ts +0 -32
  258. package/dist/types/src/sentry/browser.d.ts.map +0 -1
  259. package/dist/types/src/sentry/browser.js +0 -110
  260. package/dist/types/src/sentry/browser.js.map +0 -1
  261. package/dist/types/src/sentry/index.d.ts +0 -3
  262. package/dist/types/src/sentry/index.d.ts.map +0 -1
  263. package/dist/types/src/sentry/index.js.map +0 -1
  264. package/dist/types/src/sentry/node.d.ts +0 -32
  265. package/dist/types/src/sentry/node.d.ts.map +0 -1
  266. package/dist/types/src/sentry/node.js +0 -106
  267. package/dist/types/src/sentry/node.js.map +0 -1
  268. package/dist/types/src/sentry/node.node.test.d.ts +0 -2
  269. package/dist/types/src/sentry/node.node.test.d.ts.map +0 -1
  270. package/dist/types/src/sentry/node.node.test.js +0 -32
  271. package/dist/types/src/sentry/node.node.test.js.map +0 -1
  272. package/dist/types/src/sentry/sentry-log-processor.d.ts +0 -9
  273. package/dist/types/src/sentry/sentry-log-processor.d.ts.map +0 -1
  274. package/dist/types/src/sentry/sentry-log-processor.js +0 -144
  275. package/dist/types/src/sentry/sentry-log-processor.js.map +0 -1
  276. package/dist/types/src/sentry/sentry.node.test.d.ts +0 -2
  277. package/dist/types/src/sentry/sentry.node.test.d.ts.map +0 -1
  278. package/dist/types/src/sentry/sentry.node.test.js +0 -28
  279. package/dist/types/src/sentry/sentry.node.test.js.map +0 -1
  280. package/dist/types/src/sentry/types.d.ts +0 -18
  281. package/dist/types/src/sentry/types.d.ts.map +0 -1
  282. package/dist/types/src/sentry/types.js +0 -4
  283. package/dist/types/src/sentry/types.js.map +0 -1
  284. package/dist/types/src/testing/index.d.ts +0 -2
  285. package/dist/types/src/testing/index.d.ts.map +0 -1
  286. package/dist/types/src/testing/index.js +0 -5
  287. package/dist/types/src/testing/index.js.map +0 -1
  288. package/dist/types/src/testing/testkit/browser.d.ts +0 -2
  289. package/dist/types/src/testing/testkit/browser.d.ts.map +0 -1
  290. package/dist/types/src/testing/testkit/browser.js +0 -7
  291. package/dist/types/src/testing/testkit/browser.js.map +0 -1
  292. package/dist/types/src/testing/testkit/index.d.ts +0 -2
  293. package/dist/types/src/testing/testkit/index.d.ts.map +0 -1
  294. package/dist/types/src/testing/testkit/index.js +0 -6
  295. package/dist/types/src/testing/testkit/index.js.map +0 -1
  296. package/src/helpers/browser-observability.ts +0 -178
  297. package/src/helpers/common.ts +0 -38
  298. package/src/helpers/index.ts +0 -9
  299. package/src/helpers/map-spaces.ts +0 -48
  300. package/src/helpers/setup-telemetry-listeners.ts +0 -109
  301. package/src/otel/index.ts +0 -8
  302. package/src/otel/logs.ts +0 -102
  303. package/src/otel/traces-browser.ts +0 -62
  304. package/src/otel/traces.ts +0 -60
  305. package/src/segment/base.ts +0 -69
  306. package/src/segment/browser.ts +0 -69
  307. package/src/segment/node.ts +0 -95
  308. package/src/segment/types.ts +0 -57
  309. package/src/sentry/browser.ts +0 -133
  310. package/src/sentry/index.ts +0 -6
  311. package/src/sentry/node.node.test.ts +0 -40
  312. package/src/sentry/node.ts +0 -126
  313. package/src/sentry/sentry-log-processor.ts +0 -174
  314. package/src/sentry/sentry.node.test.ts +0 -35
  315. package/src/sentry/types.ts +0 -22
  316. package/src/testing/index.ts +0 -5
  317. package/src/testing/testkit/browser.ts +0 -8
  318. package/src/testing/testkit/index.ts +0 -7
  319. package/src/testing/testkit/shims.d.ts +0 -5
  320. /package/dist/lib/browser/{chunk-5ICT2XF2.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  321. /package/dist/lib/{browser/observability-CQGG3MID.mjs.map → node-esm/chunk-HSLMI22Q.mjs.map} +0 -0
  322. /package/dist/types/src/{otel → extensions/otel}/metrics.d.ts +0 -0
  323. /package/dist/types/src/{otel → extensions/otel}/otel.js +0 -0
  324. /package/dist/types/src/{sentry → storage}/index.js +0 -0
@@ -1,497 +1,209 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2025 DXOS.org
3
3
  //
4
- import { Event, scheduleTaskInterval } from '@dxos/async';
5
- import { PublicKey } from '@dxos/client';
6
- import { Context } from '@dxos/context';
4
+ import * as Array from 'effect/Array';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Function from 'effect/Function';
7
+ import { SubscriptionList } from '@dxos/async';
7
8
  import { invariant } from '@dxos/invariant';
8
- import { LogLevel, log } from '@dxos/log';
9
- import { ConnectionState } from '@dxos/network-manager';
10
- import { DeviceKind, Platform } from '@dxos/protocols/proto/dxos/client/services';
11
- import { isNode } from '@dxos/util';
12
- import buildSecrets from './cli-observability-secrets.json';
13
- import { getTelemetryIdentity, mapSpaces } from './helpers';
14
- import { TelemetryEvent } from './segment';
15
- const SPACE_METRICS_MIN_INTERVAL = 1000 * 60; // 1 minute
16
- const SPACE_TELEMETRY_MIN_INTERVAL = 1000 * 60 * 60; // 1 hour
17
- const NETWORK_METRICS_MIN_INTERVAL = 1000 * 60 * 5; // 5 minutes
18
- /*
19
- * Observability provides a common interface for error logging, metrics, and telemetry.
20
- * It currently provides these capabilities using Sentry, OpenTelemetry, and Segment.
21
- *
22
- * Segment:
23
- * https://app.segment.com/dxos/sources/composer-app/debugger
24
- * https://app.segment.com/dxos/sources/composer-app/settings/keys
25
- *
26
- * NOTE:
27
- * - Segment maintains a set of admin creates Source (e.g., "composer-app").
28
- * - Each source has at least one API_KEY, which is used by the client.
29
- *
30
- * Testing:
31
- * https://app.segment.com/dxos/sources/composer-app/settings/keys
32
- * - DX_TELEMETRY_API_KEY
33
- * - DX_SENTRY_DESTINATION
34
- *
35
- * Sentry:
36
- * https://sentry.io/organizations/dxos/issues
37
- *
38
- * OpenTelemetry:
39
- * https://dxosorg.grafana.net/explore
40
- */
41
- export class Observability {
42
- _mode;
43
- _namespace;
44
- _config;
45
- _group;
46
- _secrets;
47
- _tags = new Map();
48
- // TODO(wittjosiah): Generic metrics interface.
49
- _otelMetrics;
50
- _otelTraces;
51
- // TODO(wittjosiah): Generic telemetry interface.
52
- _telemetryBatchSize;
53
- _telemetry;
54
- // TODO(wittjosiah): Generic error logging interface.
55
- _sentryLogProcessor;
56
- _otelLogs;
57
- _errorReportingOptions;
58
- _captureException;
59
- _captureUserFeedback;
60
- _lastNetworkStatus;
61
- _ctx = new Context();
62
- // TODO(nf): make platform a required extension?
63
- constructor({ mode, namespace, environment, release, config, group, secrets, telemetry, errorLog, }) {
64
- this._mode = mode;
65
- this._namespace = namespace;
66
- this._config = config;
67
- this._group = group;
68
- this._secrets = this._loadSecrets(config, secrets);
69
- this._telemetryBatchSize = telemetry?.batchSize ?? 30;
70
- this._errorReportingOptions = errorLog?.sentryInitOptions;
71
- // Tags.
72
- this.setTag('mode', this._mode);
73
- this.setTag('namespace', this._namespace);
74
- this.setTag('environment', environment);
75
- this.setTag('release', release);
76
- this.setTag('session', PublicKey.random().toHex());
77
- this.setTag('group', this._group);
78
- }
79
- get mode() {
80
- return this._mode;
81
- }
82
- get group() {
83
- return this._group;
84
- }
85
- get enabled() {
86
- return this._mode !== 'disabled';
87
- }
88
- _loadSecrets(config, secrets) {
89
- if (isNode()) {
90
- const mergedSecrets = {
91
- ...buildSecrets,
92
- ...secrets,
93
- };
94
- process.env.DX_ENVIRONMENT && (mergedSecrets.DX_ENVIRONMENT = process.env.DX_ENVIRONMENT);
95
- process.env.DX_RELEASE && (mergedSecrets.DX_RELEASE = process.env.DX_RELEASE);
96
- process.env.SENTRY_DESTINATION && (mergedSecrets.SENTRY_DESTINATION = process.env.SENTRY_DESTINATION);
97
- process.env.TELEMETRY_API_KEY && (mergedSecrets.TELEMETRY_API_KEY = process.env.TELEMETRY_API_KEY);
98
- process.env.IPDATA_API_KEY && (mergedSecrets.IPDATA_API_KEY = process.env.IPDATA_API_KEY);
99
- process.env.DX_OTEL_ENDPOINT && (mergedSecrets.OTEL_ENDPOINT = process.env.DX_OTEL_ENDPOINT);
100
- process.env.DX_OTEL_AUTHORIZATION && (mergedSecrets.OTEL_AUTHORIZATION = process.env.DX_OTEL_AUTHORIZATION);
101
- return mergedSecrets;
102
- }
103
- else {
104
- log('config', { rtc: this._secrets, config });
105
- return {
106
- DX_ENVIRONMENT: config?.get('runtime.app.env.DX_ENVIRONMENT'),
107
- DX_RELEASE: config?.get('runtime.app.env.DX_RELEASE'),
108
- SENTRY_DESTINATION: config?.get('runtime.app.env.DX_SENTRY_DESTINATION'),
109
- TELEMETRY_API_KEY: config?.get('runtime.app.env.DX_TELEMETRY_API_KEY'),
110
- IPDATA_API_KEY: config?.get('runtime.app.env.DX_IPDATA_API_KEY'),
111
- OTEL_ENDPOINT: config?.get('runtime.app.env.DX_OTEL_ENDPOINT'),
112
- OTEL_AUTHORIZATION: config?.get('runtime.app.env.DX_OTEL_AUTHORIZATION'),
113
- ...secrets,
114
- };
115
- }
116
- }
117
- async initialize() {
118
- log('initializing...');
119
- await this._initLogs();
120
- await this._initMetrics();
121
- await this._initTelemetry();
122
- await this._initErrorLogs();
123
- await this._initTraces();
124
- }
125
- async close() {
126
- log('closing...');
127
- const closes = [];
128
- this._telemetry && closes.push(this._telemetry.close());
129
- this._otelMetrics && closes.push(this._otelMetrics.close());
130
- this._otelLogs && closes.push(this._otelLogs.close());
131
- await Promise.all(closes);
132
- await this._ctx.dispose();
133
- }
134
- setMode(mode) {
135
- this._mode = mode;
136
- }
137
- //
138
- // Tags
139
- //
140
- /** Callback (e.g., to share tags with Sentry.) */
141
- _setTag;
142
- /**
143
- * camelCase keys are converted to snake_case in Segment.
144
- */
145
- setTag(key, value, scope) {
146
- if (value === undefined) {
147
- return;
148
- }
149
- if (this.enabled && (scope === undefined || scope === 'all' || scope === 'errors')) {
150
- this._setTag?.(key, value);
151
- }
152
- if (!scope) {
153
- scope = 'all';
154
- }
155
- this._tags.set(key, { value, scope });
156
- }
157
- getTag(key) {
158
- return this._tags.get(key);
159
- }
160
- // TODO(wittjosiah): Improve privacy of telemetry identifiers. See `getTelemetryIdentifier`.
161
- async setIdentityTags(clientServices) {
162
- if (clientServices.IdentityService) {
163
- clientServices.IdentityService.queryIdentity().subscribe((idqr) => {
164
- if (!idqr?.identity?.did) {
165
- log('empty response from identity service', { idqr });
166
- return;
167
- }
168
- this.setTag('did', idqr.identity.did);
169
- this._telemetry?.identify({ userId: idqr.identity.did });
170
- });
171
- }
172
- if (clientServices.DevicesService) {
173
- clientServices.DevicesService.queryDevices().subscribe((dqr) => {
174
- if (!dqr || !dqr.devices || dqr.devices.length === 0) {
175
- log('empty response from device service', { device: dqr });
176
- return;
177
- }
178
- invariant(dqr, 'empty response from device service');
179
- const thisDevice = dqr.devices.find((device) => device.kind === DeviceKind.CURRENT);
180
- if (!thisDevice) {
181
- log('no current device', { device: dqr });
182
- return;
183
- }
184
- this.setTag('deviceKey', thisDevice.deviceKey.truncate());
185
- if (thisDevice.profile?.label) {
186
- this.setTag('deviceProfile', thisDevice.profile.label);
9
+ import { log } from '@dxos/log';
10
+ export * from './storage';
11
+ class ObservabilityImpl {
12
+ _initialized = false;
13
+ _extensions = [];
14
+ _dataProviders = [];
15
+ _subscriptions = new SubscriptionList();
16
+ initialize() {
17
+ if (this._initialized) {
18
+ return Effect.succeed(undefined);
19
+ }
20
+ const initializedExtensions = [];
21
+ return Effect.gen(this, function* () {
22
+ for (const extension of this._extensions) {
23
+ if (extension.initialize) {
24
+ yield* extension.initialize();
187
25
  }
188
- });
189
- }
190
- }
191
- setIPDataTelemetryTags = (ipData) => {
192
- this.setTag('city', ipData.city, 'telemetry');
193
- this.setTag('region', ipData.region, 'telemetry');
194
- this.setTag('country', ipData.country, 'telemetry');
195
- ipData.latitude && this.setTag('latitude', ipData.latitude.toString(), 'telemetry');
196
- ipData.longitude && this.setTag('longitude', ipData.longitude.toString(), 'telemetry');
197
- };
198
- //
199
- // Logs
200
- //
201
- async _initLogs() {
202
- if (this._secrets.OTEL_ENDPOINT && this._secrets.OTEL_AUTHORIZATION && this._mode !== 'disabled') {
203
- const { OtelLogs } = await import('./otel');
204
- this._otelLogs = new OtelLogs({
205
- endpoint: this._secrets.OTEL_ENDPOINT,
206
- authorizationHeader: this._secrets.OTEL_AUTHORIZATION,
207
- serviceName: this._namespace,
208
- serviceVersion: this.getTag('release')?.value ?? '0.0.0',
209
- getTags: () => Object.fromEntries(Array.from(this._tags)
210
- .filter(([key, value]) => {
211
- return value.scope === 'all' || value.scope === 'errors';
212
- })
213
- .map(([key, value]) => [key, value.value])),
214
- logLevel: LogLevel.VERBOSE,
215
- includeSharedWorkerLogs: false,
216
- });
217
- this._otelLogs && log.runtimeConfig.processors.push(this._otelLogs.logProcessor);
218
- log('otel logs enabled', { namespace: this._namespace });
219
- }
220
- else {
221
- log('otel logs disabled');
222
- }
223
- }
224
- //
225
- // Metrics
226
- //
227
- async _initMetrics() {
228
- if (this.enabled && this._secrets.OTEL_ENDPOINT && this._secrets.OTEL_AUTHORIZATION) {
229
- const { OtelMetrics } = await import('./otel');
230
- this._otelMetrics = new OtelMetrics({
231
- endpoint: this._secrets.OTEL_ENDPOINT,
232
- authorizationHeader: this._secrets.OTEL_AUTHORIZATION,
233
- serviceName: this._namespace,
234
- serviceVersion: this.getTag('release')?.value ?? '0.0.0',
235
- getTags: () => Object.fromEntries(Array.from(this._tags)
236
- .filter(([key, value]) => {
237
- return value.scope === 'all' || value.scope === 'metrics';
238
- })
239
- .map(([key, value]) => [key, value.value])),
240
- });
241
- log('otel metrics enabled');
242
- }
243
- else {
244
- log('otel metrics disabled');
245
- }
246
- }
247
- /**
248
- * Gauge metric.
249
- *
250
- * The default implementation uses OpenTelemetry
251
- */
252
- gauge(name, value, extraTags) {
253
- this._otelMetrics?.gauge(name, value, extraTags);
254
- }
255
- // TODO(nf): Refactor into ObservabilityExtensions.
256
- startNetworkMetrics(clientServices) {
257
- if (!clientServices.NetworkService) {
258
- return;
259
- }
260
- // TODO(nf): support type in debounce()
261
- const updateSignalMetrics = new Event().debounce(NETWORK_METRICS_MIN_INTERVAL);
262
- updateSignalMetrics.on(this._ctx, async () => {
263
- log('send signal metrics');
264
- this._lastNetworkStatus?.signaling?.forEach(({ server, state }) => {
265
- this.gauge('dxos.client.network.signal.connectionState', state, { server });
266
- });
267
- let swarmCount = 0;
268
- const connectionStates = new Map();
269
- for (const state in ConnectionState) {
270
- connectionStates.set(state, 0);
26
+ initializedExtensions.push(extension);
271
27
  }
272
- let totalReadBufferSize = 0;
273
- let totalWriteBufferSize = 0;
274
- let totalChannelBufferSize = 0;
275
- this._lastNetworkStatus?.connectionInfo?.forEach((connectionInfo) => {
276
- swarmCount++;
277
- for (const conn of connectionInfo.connections ?? []) {
278
- connectionStates.set(conn.state, (connectionStates.get(conn.state) ?? 0) + 1);
279
- totalReadBufferSize += conn.readBufferSize ?? 0;
280
- totalWriteBufferSize += conn.writeBufferSize ?? 0;
281
- for (const stream of conn.streams ?? []) {
282
- totalChannelBufferSize += stream.writeBufferSize ?? 0;
283
- }
28
+ const cleanups = yield* Effect.all(this._dataProviders.map((provider) => provider(this)));
29
+ this._subscriptions.add(...cleanups.filter((cleanup) => cleanup !== undefined));
30
+ this._initialized = true;
31
+ }).pipe(Effect.catchAll((error) => Effect.gen(this, function* () {
32
+ log.catch(error);
33
+ // Roll back already-initialized extensions.
34
+ for (const extension of initializedExtensions) {
35
+ if (extension.close) {
36
+ yield* extension.close().pipe(Effect.catchAll(() => Effect.succeed(undefined)));
284
37
  }
285
- this.gauge('dxos.client.network.swarm.count', swarmCount);
286
- for (const state in ConnectionState) {
287
- this.gauge('dxos.client.network.connection.count', connectionStates.get(state) ?? 0, { state });
38
+ }
39
+ this._subscriptions.clear();
40
+ })));
41
+ }
42
+ close() {
43
+ return Effect.gen(this, function* () {
44
+ this._subscriptions.clear();
45
+ this._dataProviders.length = 0;
46
+ for (const extension of this._extensions) {
47
+ if (extension.close) {
48
+ yield* extension.close();
288
49
  }
289
- this.gauge('dxos.client.network.totalReadBufferSize', totalReadBufferSize);
290
- this.gauge('dxos.client.network.totalWriteBufferSize', totalWriteBufferSize);
291
- this.gauge('dxos.client.network.totalChannelBufferSize', totalChannelBufferSize);
292
- });
293
- });
294
- clientServices.NetworkService.queryStatus().subscribe((networkStatus) => {
295
- this._lastNetworkStatus = networkStatus;
296
- updateSignalMetrics.emit();
50
+ }
51
+ this._initialized = false;
297
52
  });
298
- scheduleTaskInterval(this._ctx, async () => updateSignalMetrics.emit(), NETWORK_METRICS_MIN_INTERVAL);
299
53
  }
300
- startSpacesMetrics(client, namespace) {
301
- // TODO(nf): update subscription on new spaces
302
- const spaces = client.spaces.get();
303
- const subscriptions = new Map();
304
- this._ctx.onDispose(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));
305
- const updateSpaceMetrics = new Event().debounce(SPACE_METRICS_MIN_INTERVAL);
306
- updateSpaceMetrics.on(this._ctx, async () => {
307
- log('send space metrics');
308
- for (const data of mapSpaces(spaces, { truncateKeys: true })) {
309
- this.gauge('dxos.client.space.members', data.members, { key: data.key });
310
- this.gauge('dxos.client.space.objects', data.objects, { key: data.key });
311
- this.gauge('dxos.client.space.epoch', data.epoch, { key: data.key });
312
- this.gauge('dxos.client.space.currentDataMutations', data.currentDataMutations, { key: data.key });
54
+ enable() {
55
+ return Effect.gen(this, function* () {
56
+ for (const extension of this._extensions) {
57
+ if (extension.enable) {
58
+ yield* extension.enable();
59
+ }
313
60
  }
314
61
  });
315
- const updateSpaceTelemetry = new Event().debounce(SPACE_TELEMETRY_MIN_INTERVAL);
316
- updateSpaceTelemetry.on(this._ctx, async () => {
317
- log('send space telemetry');
318
- for (const data of mapSpaces(spaces, { truncateKeys: true })) {
319
- this.track({
320
- ...getTelemetryIdentity(client),
321
- event: TelemetryEvent.METRICS,
322
- action: 'space.update',
323
- properties: data,
324
- });
62
+ }
63
+ disable() {
64
+ return Effect.gen(this, function* () {
65
+ for (const extension of this._extensions) {
66
+ if (extension.disable) {
67
+ yield* extension.disable();
68
+ }
325
69
  }
326
70
  });
327
- const subscribeToSpaceUpdate = (space) => space.pipeline.subscribe({
328
- next: () => {
329
- updateSpaceMetrics.emit();
330
- updateSpaceTelemetry.emit();
331
- },
332
- });
333
- spaces.forEach((space) => {
334
- subscriptions.set(space.id, subscribeToSpaceUpdate(space));
335
- });
336
- client.spaces.subscribe({
337
- next: async (spaces) => {
338
- spaces
339
- .filter((space) => !subscriptions.has(space.id))
340
- .forEach((space) => {
341
- subscriptions.set(space.id, subscribeToSpaceUpdate(space));
342
- });
343
- },
344
- });
345
- scheduleTaskInterval(this._ctx, async () => updateSpaceMetrics.emit(), NETWORK_METRICS_MIN_INTERVAL);
346
71
  }
347
- async startRuntimeMetrics(client, frequency = NETWORK_METRICS_MIN_INTERVAL) {
348
- const platform = await client.services.services.SystemService?.getPlatform();
349
- invariant(platform, 'platform is required');
350
- this.setTag('platformType', Platform.PLATFORM_TYPE[platform.type].toLowerCase());
351
- if (this._mode === 'full') {
352
- if (platform.platform) {
353
- this.setTag('platform', platform.platform);
354
- }
355
- if (platform.arch) {
356
- this.setTag('arch', platform.arch);
357
- }
358
- if (platform.runtime) {
359
- this.setTag('runtime', platform.runtime);
360
- }
361
- }
362
- scheduleTaskInterval(this._ctx, async () => {
363
- if (client.services.constructor.name === 'WorkerClientServices') {
364
- const memory = window.performance.memory;
365
- if (memory) {
366
- this.gauge('dxos.client.runtime.heapTotal', memory.totalJSHeapSize);
367
- this.gauge('dxos.client.runtime.heapUsed', memory.usedJSHeapSize);
368
- this.gauge('dxos.client.runtime.heapSizeLimit', memory.jsHeapSizeLimit);
72
+ flush() {
73
+ return Effect.gen(this, function* () {
74
+ for (const extension of this._extensions) {
75
+ if (extension.flush) {
76
+ yield* extension.flush();
369
77
  }
370
78
  }
371
- client.services.services.SystemService?.getPlatform()
372
- .then((platform) => {
373
- if (platform.memory) {
374
- this.gauge('dxos.client.services.runtime.rss', platform.memory.rss);
375
- this.gauge('dxos.client.services.runtime.heapTotal', platform.memory.heapTotal);
376
- this.gauge('dxos.client.services.runtime.heapUsed', platform.memory.heapUsed);
377
- }
378
- })
379
- .catch((error) => log('platform error', { error }));
380
- }, frequency);
79
+ });
381
80
  }
382
- //
383
- // Telemetry
384
- //
385
- async _initTelemetry() {
386
- if (this._secrets.TELEMETRY_API_KEY && this._mode !== 'disabled' && typeof document !== 'undefined') {
387
- const { SegmentTelemetry } = await import('./segment');
388
- this._telemetry = new SegmentTelemetry({
389
- apiKey: this._secrets.TELEMETRY_API_KEY,
390
- batchSize: this._telemetryBatchSize,
391
- getTags: () => Object.fromEntries(Array.from(this._tags)
392
- .filter(([key, value]) => {
393
- return value.scope === 'all' || value.scope === 'telemetry';
394
- })
395
- .map(([key, value]) => [key, value.value])),
396
- });
397
- }
398
- else {
399
- log('segment disabled');
400
- }
81
+ _addExtension(extension) {
82
+ invariant(!this._initialized, 'Observability is already initialized');
83
+ this._extensions.push(extension);
401
84
  }
402
- /**
403
- * Submit telemetry page view.
404
- * The default implementation uses Segment.
405
- */
406
- page(options) {
407
- this._telemetry?.page(options);
85
+ _addDataProvider(dataProvider) {
86
+ invariant(!this._initialized, 'Observability is already initialized');
87
+ this._dataProviders.push(dataProvider);
408
88
  }
409
89
  /**
410
- * Submit telemetry user action.
411
- * The default implementation uses Segment.
90
+ * Adds a data provider and initializes it.
412
91
  */
413
- track(options) {
414
- this._telemetry?.track(options);
92
+ addDataProvider(dataProvider) {
93
+ return Effect.gen(this, function* () {
94
+ this._dataProviders.push(dataProvider);
95
+ const cleanup = yield* dataProvider(this);
96
+ if (cleanup) {
97
+ this._subscriptions.add(cleanup);
98
+ }
99
+ });
415
100
  }
416
- //
417
- // Error Logs
418
- //
419
- async _initErrorLogs() {
420
- if (this._secrets.SENTRY_DESTINATION && this._mode !== 'disabled') {
421
- const { captureException, captureUserFeedback, init, setTag } = await import('./sentry');
422
- const { SentryLogProcessor } = await import('./sentry/sentry-log-processor');
423
- this._captureException = captureException;
424
- this._captureUserFeedback = captureUserFeedback;
425
- this._setTag = setTag;
426
- // TODO(nf): Refactor package into this one?
427
- log.info('Initializing Sentry', {
428
- dest: this._secrets.SENTRY_DESTINATION,
429
- options: this._errorReportingOptions,
430
- });
431
- this._sentryLogProcessor = new SentryLogProcessor();
432
- init({
433
- ...this._errorReportingOptions,
434
- destination: this._secrets.SENTRY_DESTINATION,
435
- scrubFilenames: this._mode !== 'full',
436
- onError: (event) => this._sentryLogProcessor.addLogBreadcrumbsTo(event),
437
- });
438
- // TODO(nf): Set platform at instantiation? needed for node.
439
- // TODO(nf): Is this different than passing as properties in options?
440
- this._tags.forEach((v, k) => {
441
- if (v.scope === 'all' || v.scope === 'errors') {
442
- setTag(k, v.value);
443
- }
444
- });
101
+ identify(distinctId, attributes, setOnceAttributes) {
102
+ for (const extension of this._extensions) {
103
+ extension.identify?.(distinctId, attributes, setOnceAttributes);
445
104
  }
446
- else {
447
- log('sentry disabled');
105
+ }
106
+ alias(distinctId, previousId) {
107
+ for (const extension of this._extensions) {
108
+ extension.alias?.(distinctId, previousId);
448
109
  }
449
110
  }
450
- startErrorLogs() {
451
- this._sentryLogProcessor && log.runtimeConfig.processors.push(this._sentryLogProcessor.logProcessor);
111
+ setTags(tags, kind) {
112
+ for (const extension of this._extensions) {
113
+ if (kind && !extension.apis.some((api) => api.kind === kind)) {
114
+ continue;
115
+ }
116
+ const processedTags = Object.fromEntries(Object.entries(tags)
117
+ .filter((entry) => entry[1] !== undefined)
118
+ .map(([key, value]) => [key, value.toString()]));
119
+ extension.setTags?.(processedTags);
120
+ }
452
121
  }
453
- startTraces() {
454
- this._otelTraces && this._otelTraces.start();
122
+ get enabled() {
123
+ return this._extensions.every((extension) => extension.enabled);
455
124
  }
456
- // TODO(nf): Refactor init based on providers and their capabilities.
457
- async _initTraces() {
458
- if (this._secrets.OTEL_ENDPOINT && this._secrets.OTEL_AUTHORIZATION && this._mode !== 'disabled') {
459
- const { OtelTraces } = await import('./otel');
460
- this._otelTraces = new OtelTraces({
461
- endpoint: this._secrets.OTEL_ENDPOINT,
462
- authorizationHeader: this._secrets.OTEL_AUTHORIZATION,
463
- serviceName: this._namespace,
464
- serviceVersion: this.getTag('release')?.value ?? '0.0.0',
465
- getTags: () => Object.fromEntries(Array.from(this._tags)
466
- .filter(([key, value]) => {
467
- return value.scope === 'all' || value.scope === 'metrics';
468
- })
469
- .map(([key, value]) => [key, value.value])),
470
- });
471
- }
125
+ get errors() {
126
+ return {
127
+ captureException: (error, attributes) => {
128
+ for (const extension of this._getExtensions('errors')) {
129
+ extension.captureException(error, attributes);
130
+ }
131
+ },
132
+ };
472
133
  }
473
- /**
474
- * Manually capture an exception.
475
- * The default implementation uses Sentry.
476
- */
477
- captureException(err) {
478
- if (this.enabled) {
479
- this._captureException?.(err);
480
- }
134
+ get events() {
135
+ return {
136
+ captureEvent: (event, attributes) => {
137
+ for (const extension of this._getExtensions('events')) {
138
+ extension.captureEvent(event, attributes);
139
+ }
140
+ },
141
+ };
481
142
  }
482
- /**
483
- * Manually capture user feedback.
484
- * The default implementation uses Sentry.
485
- */
486
- captureUserFeedback(message) {
487
- if (!this._secrets.SENTRY_DESTINATION) {
488
- log.info('Feedback submitted without Sentry destination', { message });
489
- return;
490
- }
491
- // TODO(Zan): Should this respect telemetry mode? Sending feedback is explicitly user-initiated.
492
- // - Maybe if telemetry is disable we shouldn't enable replay.
493
- // - (Check the browser.ts implementation for reference).
494
- void this._captureUserFeedback?.(message);
143
+ get feedback() {
144
+ return {
145
+ captureUserFeedback: (form) => {
146
+ for (const extension of this._getExtensions('feedback')) {
147
+ extension.captureUserFeedback(form);
148
+ }
149
+ },
150
+ };
151
+ }
152
+ isAvailable(kind) {
153
+ const apis = this._getExtensions(kind);
154
+ if (apis.length === 0) {
155
+ return Effect.succeed(false);
156
+ }
157
+ return Effect.gen(this, function* () {
158
+ for (const api of apis) {
159
+ const available = yield* api.isAvailable();
160
+ if (available) {
161
+ return true;
162
+ }
163
+ }
164
+ return false;
165
+ });
166
+ }
167
+ get metrics() {
168
+ return {
169
+ gauge: (name, value, attributes) => {
170
+ for (const extension of this._getExtensions('metrics')) {
171
+ extension.gauge(name, value, attributes);
172
+ }
173
+ },
174
+ increment: (name, value, attributes) => {
175
+ for (const extension of this._getExtensions('metrics')) {
176
+ extension.increment(name, value, attributes);
177
+ }
178
+ },
179
+ distribution: (name, value, attributes) => {
180
+ for (const extension of this._getExtensions('metrics')) {
181
+ extension.distribution(name, value, attributes);
182
+ }
183
+ },
184
+ };
185
+ }
186
+ _getExtensions(kind) {
187
+ return Function.pipe(this._extensions, Array.flatMap((extension) => extension.apis), Array.filter((api) => api.kind === kind));
495
188
  }
496
189
  }
190
+ export const make = () => Effect.succeed(new ObservabilityImpl());
191
+ export const addExtension = (_extension) => Effect.fn(function* (_observability) {
192
+ const observability = yield* _observability;
193
+ const extension = yield* _extension;
194
+ invariant('_addExtension' in observability && typeof observability._addExtension === 'function');
195
+ observability._addExtension(extension);
196
+ return observability;
197
+ });
198
+ export const addDataProvider = (dataProvider) => Effect.fn(function* (_observability) {
199
+ const observability = yield* _observability;
200
+ invariant('_addDataProvider' in observability && typeof observability._addDataProvider === 'function');
201
+ observability._addDataProvider(dataProvider);
202
+ return observability;
203
+ });
204
+ export const initialize = Effect.fn(function* (_observability) {
205
+ const observability = yield* _observability;
206
+ yield* observability.initialize();
207
+ return observability;
208
+ });
497
209
  //# sourceMappingURL=observability.js.map