@dxos/observability 0.8.4-main.84f28bd → 0.8.4-main.8baae0fced

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 (330) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +14 -11
  3. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  4. package/dist/lib/browser/chunk-PSFTIG54.mjs +20 -0
  5. package/dist/lib/browser/chunk-PSFTIG54.mjs.map +7 -0
  6. package/dist/lib/browser/index.mjs +964 -34
  7. package/dist/lib/browser/index.mjs.map +4 -4
  8. package/dist/lib/browser/log-processor-HPHWNBOK.mjs +38 -0
  9. package/dist/lib/browser/log-processor-HPHWNBOK.mjs.map +7 -0
  10. package/dist/lib/browser/logs-UTNIFYHF.mjs +116 -0
  11. package/dist/lib/browser/logs-UTNIFYHF.mjs.map +7 -0
  12. package/dist/lib/browser/meta.json +1 -1
  13. package/dist/lib/browser/metrics-PRGSYAZJ.mjs +116 -0
  14. package/dist/lib/browser/metrics-PRGSYAZJ.mjs.map +7 -0
  15. package/dist/lib/browser/traces-browser-XRINKQUA.mjs +154 -0
  16. package/dist/lib/browser/traces-browser-XRINKQUA.mjs.map +7 -0
  17. package/dist/lib/node-esm/chunk-EDDZWPYV.mjs +22 -0
  18. package/dist/lib/node-esm/chunk-EDDZWPYV.mjs.map +7 -0
  19. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  20. package/dist/lib/node-esm/index.mjs +986 -34
  21. package/dist/lib/node-esm/index.mjs.map +4 -4
  22. package/dist/lib/node-esm/log-processor-ZODHERST.mjs +39 -0
  23. package/dist/lib/node-esm/log-processor-ZODHERST.mjs.map +7 -0
  24. package/dist/lib/node-esm/logs-ARJUVN3T.mjs +117 -0
  25. package/dist/lib/node-esm/logs-ARJUVN3T.mjs.map +7 -0
  26. package/dist/lib/node-esm/meta.json +1 -1
  27. package/dist/lib/node-esm/metrics-DREJOOAC.mjs +117 -0
  28. package/dist/lib/node-esm/metrics-DREJOOAC.mjs.map +7 -0
  29. package/dist/lib/node-esm/traces-74F7JUKF.mjs +125 -0
  30. package/dist/lib/node-esm/traces-74F7JUKF.mjs.map +7 -0
  31. package/dist/types/src/cli-observability-secrets.json +3 -4
  32. package/dist/types/src/extensions/index.d.ts +3 -0
  33. package/dist/types/src/extensions/index.d.ts.map +1 -0
  34. package/dist/types/src/extensions/index.js +6 -0
  35. package/dist/types/src/extensions/index.js.map +1 -0
  36. package/dist/types/src/extensions/otel/extension.d.ts +23 -0
  37. package/dist/types/src/extensions/otel/extension.d.ts.map +1 -0
  38. package/dist/types/src/extensions/otel/extension.js +220 -0
  39. package/dist/types/src/extensions/otel/extension.js.map +1 -0
  40. package/dist/types/src/extensions/otel/index.d.ts +2 -0
  41. package/dist/types/src/extensions/otel/index.d.ts.map +1 -0
  42. package/dist/types/src/extensions/otel/index.js +5 -0
  43. package/dist/types/src/extensions/otel/index.js.map +1 -0
  44. package/dist/types/src/{otel → extensions/otel}/logs.d.ts +4 -3
  45. package/dist/types/src/extensions/otel/logs.d.ts.map +1 -0
  46. package/dist/types/src/extensions/otel/logs.js +107 -0
  47. package/dist/types/src/extensions/otel/logs.js.map +1 -0
  48. package/dist/types/src/{otel → extensions/otel}/metrics.d.ts +0 -1
  49. package/dist/types/src/extensions/otel/metrics.d.ts.map +1 -0
  50. package/dist/types/src/{otel → extensions/otel}/metrics.js +8 -14
  51. package/dist/types/src/extensions/otel/metrics.js.map +1 -0
  52. package/dist/types/src/extensions/otel/otel.d.ts +19 -0
  53. package/dist/types/src/extensions/otel/otel.d.ts.map +1 -0
  54. package/dist/types/src/extensions/otel/otel.js +23 -0
  55. package/dist/types/src/extensions/otel/otel.js.map +1 -0
  56. package/dist/types/src/extensions/otel/span-processors.d.ts +25 -0
  57. package/dist/types/src/extensions/otel/span-processors.d.ts.map +1 -0
  58. package/dist/types/src/extensions/otel/span-processors.js +41 -0
  59. package/dist/types/src/extensions/otel/span-processors.js.map +1 -0
  60. package/dist/types/src/extensions/otel/traces-browser.d.ts +25 -0
  61. package/dist/types/src/extensions/otel/traces-browser.d.ts.map +1 -0
  62. package/dist/types/src/extensions/otel/traces-browser.js +105 -0
  63. package/dist/types/src/extensions/otel/traces-browser.js.map +1 -0
  64. package/dist/types/src/extensions/otel/traces.d.ts +25 -0
  65. package/dist/types/src/extensions/otel/traces.d.ts.map +1 -0
  66. package/dist/types/src/extensions/otel/traces.js +88 -0
  67. package/dist/types/src/extensions/otel/traces.js.map +1 -0
  68. package/dist/types/src/extensions/posthog/extension.d.ts +28 -0
  69. package/dist/types/src/extensions/posthog/extension.d.ts.map +1 -0
  70. package/dist/types/src/extensions/posthog/extension.js +156 -0
  71. package/dist/types/src/extensions/posthog/extension.js.map +1 -0
  72. package/dist/types/src/extensions/posthog/index.d.ts +2 -0
  73. package/dist/types/src/extensions/posthog/index.d.ts.map +1 -0
  74. package/dist/types/src/extensions/posthog/index.js +5 -0
  75. package/dist/types/src/extensions/posthog/index.js.map +1 -0
  76. package/dist/types/src/extensions/posthog/log-processor.d.ts +3 -0
  77. package/dist/types/src/extensions/posthog/log-processor.d.ts.map +1 -0
  78. package/dist/types/src/extensions/posthog/log-processor.js +36 -0
  79. package/dist/types/src/extensions/posthog/log-processor.js.map +1 -0
  80. package/dist/types/src/extensions/posthog/log-processor.test.d.ts +2 -0
  81. package/dist/types/src/extensions/posthog/log-processor.test.d.ts.map +1 -0
  82. package/dist/types/src/extensions/posthog/log-processor.test.js +146 -0
  83. package/dist/types/src/extensions/posthog/log-processor.test.js.map +1 -0
  84. package/dist/types/src/extensions/stub.d.ts +3 -0
  85. package/dist/types/src/extensions/stub.d.ts.map +1 -0
  86. package/dist/types/src/extensions/stub.js +16 -0
  87. package/dist/types/src/extensions/stub.js.map +1 -0
  88. package/dist/types/src/index.d.ts +3 -2
  89. package/dist/types/src/index.d.ts.map +1 -1
  90. package/dist/types/src/index.js +4 -3
  91. package/dist/types/src/index.js.map +1 -1
  92. package/dist/types/src/observability-extension.d.ts +74 -0
  93. package/dist/types/src/observability-extension.d.ts.map +1 -0
  94. package/dist/types/src/observability-extension.js +5 -0
  95. package/dist/types/src/observability-extension.js.map +1 -0
  96. package/dist/types/src/observability.d.ts +32 -110
  97. package/dist/types/src/observability.d.ts.map +1 -1
  98. package/dist/types/src/observability.js +178 -455
  99. package/dist/types/src/observability.js.map +1 -1
  100. package/dist/types/src/observability.test.d.ts +2 -0
  101. package/dist/types/src/observability.test.d.ts.map +1 -0
  102. package/dist/types/src/observability.test.js +312 -0
  103. package/dist/types/src/observability.test.js.map +1 -0
  104. package/dist/types/src/providers/client-observability.d.ts +11 -0
  105. package/dist/types/src/providers/client-observability.d.ts.map +1 -0
  106. package/dist/types/src/providers/client-observability.js +202 -0
  107. package/dist/types/src/providers/client-observability.js.map +1 -0
  108. package/dist/types/src/providers/index.d.ts +4 -0
  109. package/dist/types/src/providers/index.d.ts.map +1 -0
  110. package/dist/types/src/providers/index.js +7 -0
  111. package/dist/types/src/providers/index.js.map +1 -0
  112. package/dist/types/src/providers/ip-data.d.ts +5 -0
  113. package/dist/types/src/providers/ip-data.d.ts.map +1 -0
  114. package/dist/types/src/providers/ip-data.js +57 -0
  115. package/dist/types/src/providers/ip-data.js.map +1 -0
  116. package/dist/types/src/providers/storage.d.ts +3 -0
  117. package/dist/types/src/providers/storage.d.ts.map +1 -0
  118. package/dist/types/src/providers/storage.js +19 -0
  119. package/dist/types/src/providers/storage.js.map +1 -0
  120. package/dist/types/src/storage/browser.d.ts +19 -0
  121. package/dist/types/src/storage/browser.d.ts.map +1 -0
  122. package/dist/types/src/storage/browser.js +69 -0
  123. package/dist/types/src/storage/browser.js.map +1 -0
  124. package/dist/types/src/storage/index.d.ts +2 -0
  125. package/dist/types/src/storage/index.d.ts.map +1 -0
  126. package/{src/segment/index.ts → dist/types/src/storage/index.js} +1 -2
  127. package/dist/types/src/storage/index.js.map +1 -0
  128. package/dist/types/src/storage/node.d.ts +26 -0
  129. package/dist/types/src/storage/node.d.ts.map +1 -0
  130. package/dist/types/src/storage/node.js +92 -0
  131. package/dist/types/src/storage/node.js.map +1 -0
  132. package/dist/types/src/storage/node.test.d.ts +2 -0
  133. package/dist/types/src/storage/node.test.d.ts.map +1 -0
  134. package/dist/types/src/storage/node.test.js +103 -0
  135. package/dist/types/src/storage/node.test.js.map +1 -0
  136. package/dist/types/tsconfig.tsbuildinfo +1 -1
  137. package/package.json +48 -65
  138. package/src/cli-observability-secrets.json +3 -4
  139. package/src/extensions/index.ts +6 -0
  140. package/src/extensions/otel/extension.ts +279 -0
  141. package/src/extensions/otel/index.ts +5 -0
  142. package/src/extensions/otel/logs.ts +137 -0
  143. package/src/{otel → extensions/otel}/metrics.ts +6 -23
  144. package/src/extensions/otel/otel.ts +34 -0
  145. package/src/extensions/otel/span-processors.ts +45 -0
  146. package/src/extensions/otel/traces-browser.ts +139 -0
  147. package/src/extensions/otel/traces.ts +113 -0
  148. package/src/extensions/posthog/extension.ts +199 -0
  149. package/src/extensions/posthog/index.ts +5 -0
  150. package/src/extensions/posthog/log-processor.test.ts +186 -0
  151. package/src/extensions/posthog/log-processor.ts +43 -0
  152. package/src/extensions/stub.ts +19 -0
  153. package/src/index.ts +4 -3
  154. package/src/observability-extension.ts +94 -0
  155. package/src/observability.test.ts +531 -0
  156. package/src/observability.ts +238 -577
  157. package/src/providers/client-observability.ts +255 -0
  158. package/src/providers/index.ts +7 -0
  159. package/src/providers/ip-data.ts +91 -0
  160. package/src/providers/storage.ts +23 -0
  161. package/src/storage/browser.ts +71 -0
  162. package/src/{sentry → storage}/index.ts +0 -1
  163. package/src/storage/node.test.ts +129 -0
  164. package/src/{helpers/node-observability.ts → storage/node.ts} +41 -70
  165. package/src/vite-import-meta.d.ts +14 -0
  166. package/dist/lib/browser/chunk-33TCMAUB.mjs +0 -996
  167. package/dist/lib/browser/chunk-33TCMAUB.mjs.map +0 -7
  168. package/dist/lib/browser/chunk-5OQYI27L.mjs +0 -1
  169. package/dist/lib/browser/chunk-MWTIKIBZ.mjs +0 -147
  170. package/dist/lib/browser/chunk-MWTIKIBZ.mjs.map +0 -7
  171. package/dist/lib/browser/chunk-YEPQFAES.mjs +0 -164
  172. package/dist/lib/browser/chunk-YEPQFAES.mjs.map +0 -7
  173. package/dist/lib/browser/observability-EEM6BEY6.mjs +0 -10
  174. package/dist/lib/browser/otel-IRDZ7PES.mjs +0 -277
  175. package/dist/lib/browser/otel-IRDZ7PES.mjs.map +0 -7
  176. package/dist/lib/browser/segment/index.mjs +0 -11
  177. package/dist/lib/browser/segment/index.mjs.map +0 -7
  178. package/dist/lib/browser/sentry/index.mjs +0 -24
  179. package/dist/lib/browser/sentry/index.mjs.map +0 -7
  180. package/dist/lib/browser/sentry-log-processor-3F3SBJXM.mjs +0 -146
  181. package/dist/lib/browser/sentry-log-processor-3F3SBJXM.mjs.map +0 -7
  182. package/dist/lib/node-esm/chunk-552KLA6Z.mjs +0 -202
  183. package/dist/lib/node-esm/chunk-552KLA6Z.mjs.map +0 -7
  184. package/dist/lib/node-esm/chunk-EYW4X3O6.mjs +0 -997
  185. package/dist/lib/node-esm/chunk-EYW4X3O6.mjs.map +0 -7
  186. package/dist/lib/node-esm/chunk-MRAK2H7O.mjs +0 -2
  187. package/dist/lib/node-esm/chunk-MRAK2H7O.mjs.map +0 -7
  188. package/dist/lib/node-esm/chunk-TEH6VIKV.mjs +0 -135
  189. package/dist/lib/node-esm/chunk-TEH6VIKV.mjs.map +0 -7
  190. package/dist/lib/node-esm/observability-DAXZGOBS.mjs +0 -11
  191. package/dist/lib/node-esm/observability-DAXZGOBS.mjs.map +0 -7
  192. package/dist/lib/node-esm/otel-62HYJETM.mjs +0 -260
  193. package/dist/lib/node-esm/otel-62HYJETM.mjs.map +0 -7
  194. package/dist/lib/node-esm/segment/index.mjs +0 -12
  195. package/dist/lib/node-esm/segment/index.mjs.map +0 -7
  196. package/dist/lib/node-esm/sentry/index.mjs +0 -25
  197. package/dist/lib/node-esm/sentry/index.mjs.map +0 -7
  198. package/dist/lib/node-esm/sentry-log-processor-JAYRA23C.mjs +0 -147
  199. package/dist/lib/node-esm/sentry-log-processor-JAYRA23C.mjs.map +0 -7
  200. package/dist/types/src/helpers/browser-observability.d.ts +0 -17
  201. package/dist/types/src/helpers/browser-observability.d.ts.map +0 -1
  202. package/dist/types/src/helpers/browser-observability.js +0 -140
  203. package/dist/types/src/helpers/browser-observability.js.map +0 -1
  204. package/dist/types/src/helpers/common.d.ts +0 -12
  205. package/dist/types/src/helpers/common.d.ts.map +0 -1
  206. package/dist/types/src/helpers/common.js +0 -23
  207. package/dist/types/src/helpers/common.js.map +0 -1
  208. package/dist/types/src/helpers/index.d.ts +0 -6
  209. package/dist/types/src/helpers/index.d.ts.map +0 -1
  210. package/dist/types/src/helpers/index.js +0 -9
  211. package/dist/types/src/helpers/index.js.map +0 -1
  212. package/dist/types/src/helpers/map-spaces.d.ts +0 -18
  213. package/dist/types/src/helpers/map-spaces.d.ts.map +0 -1
  214. package/dist/types/src/helpers/map-spaces.js +0 -37
  215. package/dist/types/src/helpers/map-spaces.js.map +0 -1
  216. package/dist/types/src/helpers/node-observability.d.ts +0 -24
  217. package/dist/types/src/helpers/node-observability.d.ts.map +0 -1
  218. package/dist/types/src/helpers/node-observability.js +0 -101
  219. package/dist/types/src/helpers/node-observability.js.map +0 -1
  220. package/dist/types/src/helpers/setup-telemetry-listeners.d.ts +0 -4
  221. package/dist/types/src/helpers/setup-telemetry-listeners.d.ts.map +0 -1
  222. package/dist/types/src/helpers/setup-telemetry-listeners.js +0 -97
  223. package/dist/types/src/helpers/setup-telemetry-listeners.js.map +0 -1
  224. package/dist/types/src/otel/index.d.ts +0 -5
  225. package/dist/types/src/otel/index.d.ts.map +0 -1
  226. package/dist/types/src/otel/index.js +0 -8
  227. package/dist/types/src/otel/index.js.map +0 -1
  228. package/dist/types/src/otel/logs.d.ts.map +0 -1
  229. package/dist/types/src/otel/logs.js +0 -71
  230. package/dist/types/src/otel/logs.js.map +0 -1
  231. package/dist/types/src/otel/metrics.d.ts.map +0 -1
  232. package/dist/types/src/otel/metrics.js.map +0 -1
  233. package/dist/types/src/otel/otel.d.ts +0 -12
  234. package/dist/types/src/otel/otel.d.ts.map +0 -1
  235. package/dist/types/src/otel/otel.js +0 -11
  236. package/dist/types/src/otel/otel.js.map +0 -1
  237. package/dist/types/src/otel/traces-browser.d.ts +0 -8
  238. package/dist/types/src/otel/traces-browser.d.ts.map +0 -1
  239. package/dist/types/src/otel/traces-browser.js +0 -47
  240. package/dist/types/src/otel/traces-browser.js.map +0 -1
  241. package/dist/types/src/otel/traces.d.ts +0 -8
  242. package/dist/types/src/otel/traces.d.ts.map +0 -1
  243. package/dist/types/src/otel/traces.js +0 -40
  244. package/dist/types/src/otel/traces.js.map +0 -1
  245. package/dist/types/src/segment/base.d.ts +0 -15
  246. package/dist/types/src/segment/base.d.ts.map +0 -1
  247. package/dist/types/src/segment/base.js +0 -50
  248. package/dist/types/src/segment/base.js.map +0 -1
  249. package/dist/types/src/segment/browser.d.ts +0 -15
  250. package/dist/types/src/segment/browser.d.ts.map +0 -1
  251. package/dist/types/src/segment/browser.js +0 -67
  252. package/dist/types/src/segment/browser.js.map +0 -1
  253. package/dist/types/src/segment/index.d.ts +0 -3
  254. package/dist/types/src/segment/index.d.ts.map +0 -1
  255. package/dist/types/src/segment/index.js +0 -6
  256. package/dist/types/src/segment/index.js.map +0 -1
  257. package/dist/types/src/segment/node.d.ts +0 -16
  258. package/dist/types/src/segment/node.d.ts.map +0 -1
  259. package/dist/types/src/segment/node.js +0 -83
  260. package/dist/types/src/segment/node.js.map +0 -1
  261. package/dist/types/src/segment/types.d.ts +0 -52
  262. package/dist/types/src/segment/types.d.ts.map +0 -1
  263. package/dist/types/src/segment/types.js +0 -18
  264. package/dist/types/src/segment/types.js.map +0 -1
  265. package/dist/types/src/sentry/browser.d.ts +0 -32
  266. package/dist/types/src/sentry/browser.d.ts.map +0 -1
  267. package/dist/types/src/sentry/browser.js +0 -112
  268. package/dist/types/src/sentry/browser.js.map +0 -1
  269. package/dist/types/src/sentry/index.d.ts +0 -3
  270. package/dist/types/src/sentry/index.d.ts.map +0 -1
  271. package/dist/types/src/sentry/index.js +0 -6
  272. package/dist/types/src/sentry/index.js.map +0 -1
  273. package/dist/types/src/sentry/node.d.ts +0 -32
  274. package/dist/types/src/sentry/node.d.ts.map +0 -1
  275. package/dist/types/src/sentry/node.js +0 -111
  276. package/dist/types/src/sentry/node.js.map +0 -1
  277. package/dist/types/src/sentry/node.node.test.d.ts +0 -2
  278. package/dist/types/src/sentry/node.node.test.d.ts.map +0 -1
  279. package/dist/types/src/sentry/node.node.test.js +0 -34
  280. package/dist/types/src/sentry/node.node.test.js.map +0 -1
  281. package/dist/types/src/sentry/sentry-log-processor.d.ts +0 -9
  282. package/dist/types/src/sentry/sentry-log-processor.d.ts.map +0 -1
  283. package/dist/types/src/sentry/sentry-log-processor.js +0 -149
  284. package/dist/types/src/sentry/sentry-log-processor.js.map +0 -1
  285. package/dist/types/src/sentry/sentry.node.test.d.ts +0 -2
  286. package/dist/types/src/sentry/sentry.node.test.d.ts.map +0 -1
  287. package/dist/types/src/sentry/sentry.node.test.js +0 -28
  288. package/dist/types/src/sentry/sentry.node.test.js.map +0 -1
  289. package/dist/types/src/sentry/types.d.ts +0 -18
  290. package/dist/types/src/sentry/types.d.ts.map +0 -1
  291. package/dist/types/src/sentry/types.js +0 -4
  292. package/dist/types/src/sentry/types.js.map +0 -1
  293. package/dist/types/src/testing/index.d.ts +0 -2
  294. package/dist/types/src/testing/index.d.ts.map +0 -1
  295. package/dist/types/src/testing/index.js +0 -5
  296. package/dist/types/src/testing/index.js.map +0 -1
  297. package/dist/types/src/testing/testkit/browser.d.ts +0 -2
  298. package/dist/types/src/testing/testkit/browser.d.ts.map +0 -1
  299. package/dist/types/src/testing/testkit/browser.js +0 -7
  300. package/dist/types/src/testing/testkit/browser.js.map +0 -1
  301. package/dist/types/src/testing/testkit/index.d.ts +0 -2
  302. package/dist/types/src/testing/testkit/index.d.ts.map +0 -1
  303. package/dist/types/src/testing/testkit/index.js +0 -6
  304. package/dist/types/src/testing/testkit/index.js.map +0 -1
  305. package/src/helpers/browser-observability.ts +0 -177
  306. package/src/helpers/common.ts +0 -38
  307. package/src/helpers/index.ts +0 -9
  308. package/src/helpers/map-spaces.ts +0 -48
  309. package/src/helpers/setup-telemetry-listeners.ts +0 -108
  310. package/src/otel/index.ts +0 -8
  311. package/src/otel/logs.ts +0 -100
  312. package/src/otel/otel.ts +0 -21
  313. package/src/otel/traces-browser.ts +0 -59
  314. package/src/otel/traces.ts +0 -57
  315. package/src/segment/base.ts +0 -69
  316. package/src/segment/browser.ts +0 -68
  317. package/src/segment/node.ts +0 -94
  318. package/src/segment/types.ts +0 -57
  319. package/src/sentry/browser.ts +0 -133
  320. package/src/sentry/node.node.test.ts +0 -39
  321. package/src/sentry/node.ts +0 -126
  322. package/src/sentry/sentry-log-processor.ts +0 -166
  323. package/src/sentry/sentry.node.test.ts +0 -34
  324. package/src/sentry/types.ts +0 -22
  325. package/src/testing/index.ts +0 -5
  326. package/src/testing/testkit/browser.ts +0 -8
  327. package/src/testing/testkit/index.ts +0 -7
  328. package/src/testing/testkit/shims.d.ts +0 -5
  329. /package/dist/lib/browser/{chunk-5OQYI27L.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  330. /package/dist/lib/{browser/observability-EEM6BEY6.mjs.map → node-esm/chunk-HSLMI22Q.mjs.map} +0 -0
@@ -0,0 +1,34 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { DiagConsoleLogger, DiagLogLevel, diag } from '@opentelemetry/api';
6
+ import { type Resource } from '@opentelemetry/resources';
7
+
8
+ export type OtelOptions = {
9
+ endpoint: string;
10
+ headers: Record<string, string>;
11
+ resource: Resource;
12
+ getTags: () => { [key: string]: string };
13
+ consoleDiagLogLevel?: string;
14
+ };
15
+
16
+ export const setDiagLogger = (level?: string) => {
17
+ const logLevel = DiagLogLevel[level as keyof typeof DiagLogLevel];
18
+ if (logLevel) {
19
+ diag.setLogger(new DiagConsoleLogger(), logLevel);
20
+ }
21
+ };
22
+
23
+ /**
24
+ * Resolve a possibly-relative OTLP exporter URL to an absolute URL.
25
+ * The OpenTelemetry browser HTTP exporter validates user-provided URLs with `new URL(url)`,
26
+ * which throws on relative paths like `/api/otel/v1/logs`. In a browser context we resolve
27
+ * against `window.location.origin`; outside the browser we return the input unchanged.
28
+ */
29
+ export const resolveOtlpUrl = (url: string): string => {
30
+ if (typeof window !== 'undefined' && url.startsWith('/')) {
31
+ return new URL(url, window.location.origin).toString();
32
+ }
33
+ return url;
34
+ };
@@ -0,0 +1,45 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Context } from '@opentelemetry/api';
6
+ import { type ReadableSpan, type Span, type SpanProcessor } from '@opentelemetry/sdk-trace-base';
7
+
8
+ import { log } from '@dxos/log';
9
+
10
+ /**
11
+ * Injects dynamic tags as attributes on every span.
12
+ *
13
+ * This is an `onStart`-only processor; `onEnd`/`shutdown`/`forceFlush` are no-ops
14
+ * because this processor never holds pending work (delegates export to downstream
15
+ * processors like BatchSpanProcessor).
16
+ *
17
+ * Use for tags that are not known at provider construction (e.g. identity
18
+ * resolved asynchronously after login). For values known at startup, prefer
19
+ * putting them on the `Resource` — see `extension.ts`.
20
+ *
21
+ * Failures in the tag provider are swallowed so they can never break span
22
+ * recording (the processor is best-effort and runs on the startSpan hot path).
23
+ */
24
+ export class TagInjectorSpanProcessor implements SpanProcessor {
25
+ constructor(private readonly _getTags: () => Record<string, string>) {}
26
+
27
+ onStart(span: Span, _parentContext: Context): void {
28
+ let tags: Record<string, string>;
29
+ try {
30
+ tags = this._getTags();
31
+ } catch (err) {
32
+ log.catch(err);
33
+ return;
34
+ }
35
+ for (const [key, value] of Object.entries(tags)) {
36
+ span.setAttribute(key, value);
37
+ }
38
+ }
39
+
40
+ onEnd(_span: ReadableSpan): void {}
41
+
42
+ async shutdown(): Promise<void> {}
43
+
44
+ async forceFlush(): Promise<void> {}
45
+ }
@@ -0,0 +1,139 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import {
6
+ ROOT_CONTEXT,
7
+ SpanStatusCode,
8
+ type Tracer,
9
+ context as otelContext,
10
+ propagation,
11
+ trace,
12
+ } from '@opentelemetry/api';
13
+ import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web';
14
+ import { W3CTraceContextPropagator } from '@opentelemetry/core';
15
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
16
+ import { registerInstrumentations } from '@opentelemetry/instrumentation';
17
+ import {
18
+ AlwaysOnSampler,
19
+ BatchSpanProcessor,
20
+ ParentBasedSampler,
21
+ TraceIdRatioBasedSampler,
22
+ } from '@opentelemetry/sdk-trace-base';
23
+ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
24
+ import { ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
25
+
26
+ import { log } from '@dxos/log';
27
+ import { TRACE_ALL_KEY, type RemoteSpan, type StartSpanOptions, TRACE_PROCESSOR } from '@dxos/tracing';
28
+
29
+ import { type OtelOptions, resolveOtlpUrl } from './otel';
30
+ import { TagInjectorSpanProcessor } from './span-processors';
31
+
32
+ export class OtelTraces {
33
+ private _tracer: Tracer;
34
+ private readonly _tracerProvider: WebTracerProvider;
35
+
36
+ constructor(private readonly options: OtelOptions) {
37
+ propagation.setGlobalPropagator(new W3CTraceContextPropagator());
38
+
39
+ const forceTraceAll = typeof localStorage !== 'undefined' && localStorage.getItem(TRACE_ALL_KEY) === 'true';
40
+
41
+ this._tracerProvider = new WebTracerProvider({
42
+ resource: this.options.resource,
43
+ sampler: new ParentBasedSampler({
44
+ root: forceTraceAll ? new AlwaysOnSampler() : new TraceIdRatioBasedSampler(0.3),
45
+ }),
46
+ spanProcessors: [
47
+ new TagInjectorSpanProcessor(this.options.getTags),
48
+ new BatchSpanProcessor(
49
+ new OTLPTraceExporter({
50
+ url: resolveOtlpUrl(this.options.endpoint + '/v1/traces'),
51
+ headers: this.options.headers,
52
+ concurrencyLimit: 10,
53
+ }),
54
+ { scheduledDelayMillis: 5_000 },
55
+ ),
56
+ ],
57
+ });
58
+
59
+ trace.setGlobalTracerProvider(this._tracerProvider);
60
+
61
+ this._tracer = trace.getTracer(
62
+ 'dxos-observability',
63
+ this.options.resource.attributes[ATTR_SERVICE_VERSION]?.toString(),
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Forcibly flush the BatchSpanProcessor. Call before process exit / page unload
69
+ * to avoid losing queued spans (which manifests as "Missing Span" in SigNoz —
70
+ * their already-exported children reference a parent that never made it to OTLP).
71
+ */
72
+ public async flush(): Promise<void> {
73
+ await this._tracerProvider.forceFlush();
74
+ }
75
+
76
+ /**
77
+ * Flush + shut down the tracer provider via `WebTracerProvider.shutdown()`,
78
+ * which forces a final export then terminates all span processors.
79
+ *
80
+ * Terminal and effectively one-shot: safe to call after `flush()`, but
81
+ * `flush()` MUST NOT be called after `close()` — shutdown stops further
82
+ * exporting, so subsequent `close()`/`flush()` calls resolve without
83
+ * emitting new spans.
84
+ */
85
+ public async close(): Promise<void> {
86
+ await this._tracerProvider.shutdown();
87
+ }
88
+
89
+ public start(): void {
90
+ log('trace processor registered');
91
+
92
+ registerInstrumentations({
93
+ instrumentations: [
94
+ getWebAutoInstrumentations({
95
+ '@opentelemetry/instrumentation-fetch': { enabled: false, ignoreUrls: [/api\.ipdata\.co/] },
96
+ '@opentelemetry/instrumentation-document-load': { enabled: false },
97
+ '@opentelemetry/instrumentation-xml-http-request': { enabled: false },
98
+ '@opentelemetry/instrumentation-user-interaction': { enabled: false },
99
+ }),
100
+ ],
101
+ });
102
+
103
+ const tracer = this._tracer;
104
+
105
+ TRACE_PROCESSOR.tracingBackend = {
106
+ startSpan: (options: StartSpanOptions): RemoteSpan => {
107
+ log('begin otel trace', { options });
108
+ const parentCtx = options.parentContext
109
+ ? propagation.extract(ROOT_CONTEXT, {
110
+ traceparent: options.parentContext.traceparent,
111
+ tracestate: options.parentContext.tracestate ?? '',
112
+ })
113
+ : otelContext.active();
114
+
115
+ const span = tracer.startSpan(options.name, options, parentCtx);
116
+
117
+ const sc = span.spanContext();
118
+ const spanContext =
119
+ sc && sc.traceId && sc.spanId
120
+ ? {
121
+ traceparent: `00-${sc.traceId}-${sc.spanId}-${(sc.traceFlags ?? 0).toString(16).padStart(2, '0')}`,
122
+ tracestate: sc.traceState?.serialize(),
123
+ }
124
+ : undefined;
125
+
126
+ return {
127
+ end: (endTime?: number) => span.end(endTime),
128
+ setError: (err: unknown) => {
129
+ if (err instanceof Error) {
130
+ span.recordException(err);
131
+ }
132
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err instanceof Error ? err.message : String(err) });
133
+ },
134
+ spanContext,
135
+ };
136
+ },
137
+ };
138
+ }
139
+ }
@@ -0,0 +1,113 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import {
6
+ ROOT_CONTEXT,
7
+ SpanStatusCode,
8
+ type Tracer,
9
+ context as otelContext,
10
+ propagation,
11
+ trace,
12
+ } from '@opentelemetry/api';
13
+ import { W3CTraceContextPropagator } from '@opentelemetry/core';
14
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
15
+ import { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
16
+ import { ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
17
+
18
+ import { log } from '@dxos/log';
19
+ import { type RemoteSpan, type StartSpanOptions, TRACE_PROCESSOR } from '@dxos/tracing';
20
+
21
+ import { type OtelOptions, resolveOtlpUrl } from './otel';
22
+ import { TagInjectorSpanProcessor } from './span-processors';
23
+
24
+ export class OtelTraces {
25
+ private _tracer: Tracer;
26
+ private readonly _tracerProvider: BasicTracerProvider;
27
+
28
+ constructor(private readonly options: OtelOptions) {
29
+ propagation.setGlobalPropagator(new W3CTraceContextPropagator());
30
+
31
+ this._tracerProvider = new BasicTracerProvider({
32
+ resource: this.options.resource,
33
+ spanProcessors: [
34
+ new TagInjectorSpanProcessor(this.options.getTags),
35
+ new BatchSpanProcessor(
36
+ new OTLPTraceExporter({
37
+ url: resolveOtlpUrl(this.options.endpoint + '/v1/traces'),
38
+ headers: this.options.headers,
39
+ concurrencyLimit: 10,
40
+ }),
41
+ ),
42
+ ],
43
+ });
44
+
45
+ trace.setGlobalTracerProvider(this._tracerProvider);
46
+ this._tracer = trace.getTracer(
47
+ 'dxos-observability',
48
+ this.options.resource.attributes[ATTR_SERVICE_VERSION]?.toString(),
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Forcibly flush the BatchSpanProcessor. Call before process exit to avoid
54
+ * losing queued spans (which manifests as "Missing Span" in SigNoz — their
55
+ * already-exported children reference a parent that never made it to OTLP).
56
+ */
57
+ public async flush(): Promise<void> {
58
+ await this._tracerProvider.forceFlush();
59
+ }
60
+
61
+ /**
62
+ * Flush + shut down the tracer provider via `BasicTracerProvider.shutdown()`,
63
+ * which forces a final export then terminates all span processors.
64
+ *
65
+ * Terminal and effectively one-shot: safe to call after `flush()`, but
66
+ * `flush()` MUST NOT be called after `close()` — shutdown stops further
67
+ * exporting, so subsequent `close()`/`flush()` calls resolve without
68
+ * emitting new spans.
69
+ */
70
+ public async close(): Promise<void> {
71
+ await this._tracerProvider.shutdown();
72
+ }
73
+
74
+ public start(): void {
75
+ log('trace processor registered');
76
+
77
+ const tracer = this._tracer;
78
+
79
+ TRACE_PROCESSOR.tracingBackend = {
80
+ startSpan: (options: StartSpanOptions): RemoteSpan => {
81
+ log('begin otel trace', { options });
82
+ const parentCtx = options.parentContext
83
+ ? propagation.extract(ROOT_CONTEXT, {
84
+ traceparent: options.parentContext.traceparent,
85
+ tracestate: options.parentContext.tracestate ?? '',
86
+ })
87
+ : otelContext.active();
88
+
89
+ const span = tracer.startSpan(options.name, options, parentCtx);
90
+
91
+ const sc = span.spanContext();
92
+ const spanContext =
93
+ sc && sc.traceId && sc.spanId
94
+ ? {
95
+ traceparent: `00-${sc.traceId}-${sc.spanId}-${(sc.traceFlags ?? 0).toString(16).padStart(2, '0')}`,
96
+ tracestate: sc.traceState?.serialize(),
97
+ }
98
+ : undefined;
99
+
100
+ return {
101
+ end: (endTime?: number) => span.end(endTime),
102
+ setError: (err: unknown) => {
103
+ if (err instanceof Error) {
104
+ span.recordException(err);
105
+ }
106
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err instanceof Error ? err.message : String(err) });
107
+ },
108
+ spanContext,
109
+ };
110
+ },
111
+ };
112
+ }
113
+ }
@@ -0,0 +1,199 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import { type PostHogConfig } from 'posthog-js';
7
+
8
+ import { type Config } from '@dxos/config';
9
+ import { log } from '@dxos/log';
10
+ import { type IdbLogStore } from '@dxos/log-store-idb';
11
+
12
+ import { type Extension } from '../../observability-extension';
13
+ import { stubExtension } from '../stub';
14
+
15
+ export type ExtensionsOptions = {
16
+ config: Config;
17
+ /** Release identifier, e.g. `composer@0.8.3`. */
18
+ release?: string;
19
+ /** Deployment environment, e.g. `production` or `staging`. */
20
+ environment?: string;
21
+ posthog?: Partial<PostHogConfig>;
22
+ /**
23
+ * Shared persistent log store for debug log dumps.
24
+ * The owning app is expected to register `logStore.processor` with `log` itself —
25
+ * this extension only consumes the buffered logs (via `export()`).
26
+ */
27
+ logStore?: IdbLogStore;
28
+ /**
29
+ * Maximum byte size passed to `logStore.export()` when uploading feedback logs.
30
+ * Should match the upload limit enforced by the server receiving the logs.
31
+ * When omitted the full store is exported without trimming.
32
+ */
33
+ feedbackLogMaxSize?: number;
34
+ };
35
+
36
+ /** Upload serialized logs to the feedback-logs endpoint. Returns the R2 key on success. */
37
+ const uploadLogs = async (body: string): Promise<string | undefined> => {
38
+ try {
39
+ const response = await fetch('/api/feedback-logs', {
40
+ method: 'POST',
41
+ headers: { 'Content-Type': 'application/x-ndjson' },
42
+ body,
43
+ });
44
+ if (!response.ok) {
45
+ log.warn('feedback log upload failed', { status: response.status });
46
+ return undefined;
47
+ }
48
+ const { key } = await response.json();
49
+ return key;
50
+ } catch (err) {
51
+ log.warn('feedback log upload error', { error: err });
52
+ return undefined;
53
+ }
54
+ };
55
+
56
+ /** Create a PostHog-backed observability extension for events, errors, and feedback. */
57
+ export const extensions: (options: ExtensionsOptions) => Effect.Effect<Extension> = Effect.fn(function* ({
58
+ config,
59
+ release,
60
+ environment,
61
+ posthog: posthogConfig,
62
+ logStore,
63
+ feedbackLogMaxSize,
64
+ }) {
65
+ if (typeof window === 'undefined') {
66
+ log('PostHog is being stubbed because it is running in a worker.');
67
+ return stubExtension;
68
+ }
69
+
70
+ const feedbackSurveyId = config.get('runtime.app.env.DX_POSTHOG_FEEDBACK_SURVEY_ID');
71
+ const apiKey = config.get('runtime.app.env.DX_POSTHOG_API_KEY');
72
+ const api_host = config.get('runtime.app.env.DX_POSTHOG_API_HOST');
73
+ if (!apiKey || !api_host) {
74
+ log.info('Missing POSTHOG_API_KEY or POSTHOG_API_HOST');
75
+ return stubExtension;
76
+ }
77
+
78
+ const { default: posthog } = yield* Effect.promise(() => import('posthog-js'));
79
+ const { logProcessor } = yield* Effect.promise(() => import('./log-processor'));
80
+ let feedbackSurveyAvailable: boolean | null = null;
81
+ let unregisterPosthogProcessors: (() => void) | undefined;
82
+
83
+ const checkFeedbackSurveyAvailable = (): Effect.Effect<boolean> =>
84
+ feedbackSurveyId
85
+ ? Effect.promise(() => {
86
+ if (feedbackSurveyAvailable !== null) {
87
+ return Promise.resolve(feedbackSurveyAvailable);
88
+ }
89
+ return new Promise<boolean>((resolve) => {
90
+ posthog.getSurveys((surveys) => {
91
+ const found = surveys.some((s) => s.id === feedbackSurveyId);
92
+ feedbackSurveyAvailable = found;
93
+ resolve(found);
94
+ });
95
+ });
96
+ })
97
+ : Effect.succeed(false);
98
+
99
+ return {
100
+ initialize: () =>
101
+ Effect.sync(() => {
102
+ // https://posthog.com/docs/libraries/js/config
103
+ posthog.init(apiKey, {
104
+ api_host,
105
+ mask_all_text: true,
106
+ capture_exceptions: true,
107
+ ...posthogConfig,
108
+ });
109
+ if (release || environment) {
110
+ posthog.register({
111
+ ...(release ? { release } : {}),
112
+ ...(environment ? { environment } : {}),
113
+ });
114
+ }
115
+ unregisterPosthogProcessors?.();
116
+ const removePosthogLog = log.addProcessor(logProcessor);
117
+ unregisterPosthogProcessors = () => {
118
+ removePosthogLog();
119
+ };
120
+ }),
121
+ close: () =>
122
+ Effect.sync(() => {
123
+ unregisterPosthogProcessors?.();
124
+ unregisterPosthogProcessors = undefined;
125
+ }),
126
+ enable: () => Effect.sync(() => posthog.opt_in_capturing()),
127
+ disable: () => Effect.sync(() => posthog.opt_out_capturing()),
128
+ identify: (distinctId, attributes, setOnceAttributes) => {
129
+ posthog.identify(distinctId, attributes, setOnceAttributes);
130
+ },
131
+ alias: (distinctId, previousId) => {
132
+ posthog.alias(distinctId, previousId);
133
+ },
134
+ setTags: (tags) => {
135
+ posthog.register_for_session(tags);
136
+ },
137
+ get enabled(): boolean {
138
+ return posthog.is_capturing();
139
+ },
140
+ apis: [
141
+ {
142
+ kind: 'events',
143
+ isAvailable: () => Effect.succeed(true),
144
+ captureEvent: (event, attributes) => {
145
+ posthog.capture(event, attributes);
146
+ },
147
+ },
148
+ {
149
+ kind: 'errors',
150
+ isAvailable: () => Effect.succeed(true),
151
+ captureException: (error, attributes) => {
152
+ posthog.captureException(error, attributes);
153
+ },
154
+ },
155
+ {
156
+ kind: 'feedback',
157
+ // TODO(wittjosiah): Support custom surveys.
158
+ captureUserFeedback: (form) => {
159
+ return new Promise<string | undefined>((resolve, reject) => {
160
+ posthog.getSurveys((surveys) => {
161
+ void (async () => {
162
+ try {
163
+ const survey = surveys.find((survey) => survey.id === feedbackSurveyId);
164
+ if (!survey || survey.questions.length === 0) {
165
+ log.error('Missing feedback survey or survey has no questions', { feedbackSurveyId });
166
+ resolve(undefined);
167
+ return;
168
+ }
169
+
170
+ let debugLogDumpKey: string | null = null;
171
+ if (form.includeLogs !== false && logStore !== undefined) {
172
+ const ndjson = await logStore.export({ maxSize: feedbackLogMaxSize });
173
+ if (ndjson.length > 0) {
174
+ debugLogDumpKey = (await uploadLogs(ndjson)) ?? 'failed';
175
+ }
176
+ }
177
+
178
+ // https://posthog.com/docs/surveys/implementing-custom-surveys
179
+ const question = survey.questions[0];
180
+ const result = posthog.capture('survey sent', {
181
+ $survey_id: survey.id,
182
+ $survey_questions: [{ id: question.id, question: question.question }],
183
+ [`$survey_response_${question.id}`]: form.message,
184
+ debug_log_dump_key: debugLogDumpKey,
185
+ });
186
+ resolve(result?.uuid);
187
+ } catch (err) {
188
+ log.error('Failed to capture user feedback', { err });
189
+ reject(err);
190
+ }
191
+ })();
192
+ });
193
+ });
194
+ },
195
+ isAvailable: checkFeedbackSurveyAvailable,
196
+ },
197
+ ],
198
+ };
199
+ });
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './extension';