@dxos/observability 0.3.11-main.0252f93

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 (138) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +26 -0
  3. package/dist/lib/browser/chunk-2J5YS65Q.mjs +81 -0
  4. package/dist/lib/browser/chunk-2J5YS65Q.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-6KUJPLEH.mjs +293 -0
  6. package/dist/lib/browser/chunk-6KUJPLEH.mjs.map +7 -0
  7. package/dist/lib/browser/datadog/index.mjs +9 -0
  8. package/dist/lib/browser/datadog/index.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +557 -0
  10. package/dist/lib/browser/index.mjs.map +7 -0
  11. package/dist/lib/browser/meta.json +1 -0
  12. package/dist/lib/browser/sentry/index.mjs +25 -0
  13. package/dist/lib/browser/sentry/index.mjs.map +7 -0
  14. package/dist/lib/node/chunk-FSAOBKO2.cjs +352 -0
  15. package/dist/lib/node/chunk-FSAOBKO2.cjs.map +7 -0
  16. package/dist/lib/node/chunk-VDBBIYH6.cjs +101 -0
  17. package/dist/lib/node/chunk-VDBBIYH6.cjs.map +7 -0
  18. package/dist/lib/node/datadog/index.cjs +31 -0
  19. package/dist/lib/node/datadog/index.cjs.map +7 -0
  20. package/dist/lib/node/index.cjs +630 -0
  21. package/dist/lib/node/index.cjs.map +7 -0
  22. package/dist/lib/node/meta.json +1 -0
  23. package/dist/lib/node/sentry/index.cjs +45 -0
  24. package/dist/lib/node/sentry/index.cjs.map +7 -0
  25. package/dist/types/src/cli-observability-secrets.json +7 -0
  26. package/dist/types/src/datadog/browser.d.ts +8 -0
  27. package/dist/types/src/datadog/browser.d.ts.map +1 -0
  28. package/dist/types/src/datadog/browser.js +22 -0
  29. package/dist/types/src/datadog/browser.js.map +1 -0
  30. package/dist/types/src/datadog/index.d.ts +3 -0
  31. package/dist/types/src/datadog/index.d.ts.map +1 -0
  32. package/dist/types/src/datadog/index.js +22 -0
  33. package/dist/types/src/datadog/index.js.map +1 -0
  34. package/dist/types/src/datadog/metrics.d.ts +16 -0
  35. package/dist/types/src/datadog/metrics.d.ts.map +1 -0
  36. package/dist/types/src/datadog/metrics.js +56 -0
  37. package/dist/types/src/datadog/metrics.js.map +1 -0
  38. package/dist/types/src/datadog/node.d.ts +7 -0
  39. package/dist/types/src/datadog/node.d.ts.map +1 -0
  40. package/dist/types/src/datadog/node.js +22 -0
  41. package/dist/types/src/datadog/node.js.map +1 -0
  42. package/dist/types/src/index.d.ts +2 -0
  43. package/dist/types/src/index.d.ts.map +1 -0
  44. package/dist/types/src/index.js +21 -0
  45. package/dist/types/src/index.js.map +1 -0
  46. package/dist/types/src/observability.d.ts +85 -0
  47. package/dist/types/src/observability.d.ts.map +1 -0
  48. package/dist/types/src/observability.js +352 -0
  49. package/dist/types/src/observability.js.map +1 -0
  50. package/dist/types/src/segment/browser.d.ts +9 -0
  51. package/dist/types/src/segment/browser.d.ts.map +1 -0
  52. package/dist/types/src/segment/browser.js +71 -0
  53. package/dist/types/src/segment/browser.js.map +1 -0
  54. package/dist/types/src/segment/index.d.ts +3 -0
  55. package/dist/types/src/segment/index.d.ts.map +1 -0
  56. package/dist/types/src/segment/index.js +22 -0
  57. package/dist/types/src/segment/index.js.map +1 -0
  58. package/dist/types/src/segment/node.d.ts +19 -0
  59. package/dist/types/src/segment/node.d.ts.map +1 -0
  60. package/dist/types/src/segment/node.js +88 -0
  61. package/dist/types/src/segment/node.js.map +1 -0
  62. package/dist/types/src/segment/types.d.ts +22 -0
  63. package/dist/types/src/segment/types.d.ts.map +1 -0
  64. package/dist/types/src/segment/types.js +6 -0
  65. package/dist/types/src/segment/types.js.map +1 -0
  66. package/dist/types/src/sentry/browser.d.ts +31 -0
  67. package/dist/types/src/sentry/browser.d.ts.map +1 -0
  68. package/dist/types/src/sentry/browser.js +112 -0
  69. package/dist/types/src/sentry/browser.js.map +1 -0
  70. package/dist/types/src/sentry/index.d.ts +4 -0
  71. package/dist/types/src/sentry/index.d.ts.map +1 -0
  72. package/dist/types/src/sentry/index.js +26 -0
  73. package/dist/types/src/sentry/index.js.map +1 -0
  74. package/dist/types/src/sentry/node.d.ts +32 -0
  75. package/dist/types/src/sentry/node.d.ts.map +1 -0
  76. package/dist/types/src/sentry/node.js +169 -0
  77. package/dist/types/src/sentry/node.js.map +1 -0
  78. package/dist/types/src/sentry/node.test.d.ts +2 -0
  79. package/dist/types/src/sentry/node.test.d.ts.map +1 -0
  80. package/dist/types/src/sentry/node.test.js +66 -0
  81. package/dist/types/src/sentry/node.test.js.map +1 -0
  82. package/dist/types/src/sentry/sentry.test.d.ts +2 -0
  83. package/dist/types/src/sentry/sentry.test.d.ts.map +1 -0
  84. package/dist/types/src/sentry/sentry.test.js +60 -0
  85. package/dist/types/src/sentry/sentry.test.js.map +1 -0
  86. package/dist/types/src/sentry/tracing.d.ts +5 -0
  87. package/dist/types/src/sentry/tracing.d.ts.map +1 -0
  88. package/dist/types/src/sentry/tracing.js +141 -0
  89. package/dist/types/src/sentry/tracing.js.map +1 -0
  90. package/dist/types/src/sentry/tracing.test.d.ts +2 -0
  91. package/dist/types/src/sentry/tracing.test.d.ts.map +1 -0
  92. package/dist/types/src/sentry/tracing.test.js +76 -0
  93. package/dist/types/src/sentry/tracing.test.js.map +1 -0
  94. package/dist/types/src/sentry/types.d.ts +18 -0
  95. package/dist/types/src/sentry/types.d.ts.map +1 -0
  96. package/dist/types/src/sentry/types.js +6 -0
  97. package/dist/types/src/sentry/types.js.map +1 -0
  98. package/dist/types/src/testing/index.d.ts +2 -0
  99. package/dist/types/src/testing/index.d.ts.map +1 -0
  100. package/dist/types/src/testing/index.js +21 -0
  101. package/dist/types/src/testing/index.js.map +1 -0
  102. package/dist/types/src/testing/testkit/browser.d.ts +2 -0
  103. package/dist/types/src/testing/testkit/browser.d.ts.map +1 -0
  104. package/dist/types/src/testing/testkit/browser.js +13 -0
  105. package/dist/types/src/testing/testkit/browser.js.map +1 -0
  106. package/dist/types/src/testing/testkit/index.d.ts +2 -0
  107. package/dist/types/src/testing/testkit/index.d.ts.map +1 -0
  108. package/dist/types/src/testing/testkit/index.js +12 -0
  109. package/dist/types/src/testing/testkit/index.js.map +1 -0
  110. package/dist/types/src/util.d.ts +19 -0
  111. package/dist/types/src/util.d.ts.map +1 -0
  112. package/dist/types/src/util.js +42 -0
  113. package/dist/types/src/util.js.map +1 -0
  114. package/package.json +94 -0
  115. package/src/cli-observability-secrets.json +7 -0
  116. package/src/datadog/browser.ts +21 -0
  117. package/src/datadog/index.ts +6 -0
  118. package/src/datadog/metrics.ts +49 -0
  119. package/src/datadog/node.ts +19 -0
  120. package/src/index.ts +5 -0
  121. package/src/observability.ts +442 -0
  122. package/src/segment/browser.ts +67 -0
  123. package/src/segment/index.ts +6 -0
  124. package/src/segment/node.ts +91 -0
  125. package/src/segment/types.ts +27 -0
  126. package/src/sentry/browser.ts +100 -0
  127. package/src/sentry/index.ts +9 -0
  128. package/src/sentry/node.test.ts +46 -0
  129. package/src/sentry/node.ts +153 -0
  130. package/src/sentry/sentry.test.ts +39 -0
  131. package/src/sentry/tracing.test.ts +62 -0
  132. package/src/sentry/tracing.ts +153 -0
  133. package/src/sentry/types.ts +22 -0
  134. package/src/testing/index.ts +5 -0
  135. package/src/testing/testkit/browser.ts +8 -0
  136. package/src/testing/testkit/index.ts +7 -0
  137. package/src/testing/testkit/shims.d.ts +5 -0
  138. package/src/util.ts +49 -0
@@ -0,0 +1,630 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var node_exports = {};
30
+ __export(node_exports, {
31
+ Observability: () => Observability
32
+ });
33
+ module.exports = __toCommonJS(node_exports);
34
+ var import_chunk_VDBBIYH6 = require("./chunk-VDBBIYH6.cjs");
35
+ var import_chunk_FSAOBKO2 = require("./chunk-FSAOBKO2.cjs");
36
+ var import_async = require("@dxos/async");
37
+ var import_context = require("@dxos/context");
38
+ var import_invariant = require("@dxos/invariant");
39
+ var import_log = require("@dxos/log");
40
+ var import_network_manager = require("@dxos/network-manager");
41
+ var import_services = require("@dxos/protocols/proto/dxos/client/services");
42
+ var import_util = require("@dxos/util");
43
+ var import_analytics_node = __toESM(require("analytics-node"));
44
+ var import_invariant2 = require("@dxos/invariant");
45
+ var import_log2 = require("@dxos/log");
46
+ var cli_observability_secrets_default = {
47
+ SENTRY_DESTINATION: "https://2647916221e643869965e78469479aa4@o4504012000067584.ingest.sentry.io/4504012027265029",
48
+ TELEMETRY_API_KEY: "B00QG6PtJJrJ0VVFe0H5a6bcUUShKyZM",
49
+ IPDATA_API_KEY: "73dfdecdf979c18f07d50cf841bbdd9e589f237256326ac8cca23786",
50
+ DATADOG_API_KEY: null,
51
+ DATADOG_APP_KEY: null
52
+ };
53
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/observability/src/segment/node.ts";
54
+ var SegmentTelemetry = class {
55
+ constructor({ apiKey, batchSize, getTags }) {
56
+ this._getTags = getTags;
57
+ try {
58
+ (0, import_invariant2.invariant)(apiKey, "Key required to send telemetry", {
59
+ F: __dxlog_file,
60
+ L: 20,
61
+ S: this,
62
+ A: [
63
+ "apiKey",
64
+ "'Key required to send telemetry'"
65
+ ]
66
+ });
67
+ this._analytics = new import_analytics_node.default(apiKey, {
68
+ flushAt: batchSize,
69
+ enable: true
70
+ });
71
+ } catch (err) {
72
+ import_log2.log.catch("Failed to initialize telemetry", err, {
73
+ F: __dxlog_file,
74
+ L: 27,
75
+ S: this,
76
+ C: (f, a) => f(...a)
77
+ });
78
+ }
79
+ }
80
+ /**
81
+ * Track a page view.
82
+ */
83
+ page({ installationId: anonymousId, identityId: userId, ...options } = {}) {
84
+ if (!this._analytics) {
85
+ (0, import_log2.log)("Analytics not initialized", {
86
+ action: "page"
87
+ }, {
88
+ F: __dxlog_file,
89
+ L: 36,
90
+ S: this,
91
+ C: (f, a) => f(...a)
92
+ });
93
+ return;
94
+ }
95
+ try {
96
+ this._analytics.page({
97
+ ...options,
98
+ userId,
99
+ anonymousId
100
+ });
101
+ } catch (err) {
102
+ import_log2.log.catch("Failed to track page", err, {
103
+ F: __dxlog_file,
104
+ L: 47,
105
+ S: this,
106
+ C: (f, a) => f(...a)
107
+ });
108
+ }
109
+ }
110
+ /**
111
+ * Track an event.
112
+ */
113
+ event({ installationId: anonymousId, identityId: userId, name: event, ...options }) {
114
+ (0, import_log2.log)("sending event to telemetry", {
115
+ event,
116
+ options,
117
+ tags: Object.fromEntries(this._getTags().entries())
118
+ }, {
119
+ F: __dxlog_file,
120
+ L: 55,
121
+ S: this,
122
+ C: (f, a) => f(...a)
123
+ });
124
+ if (!this._analytics) {
125
+ (0, import_log2.log)("Analytics not initialized", {
126
+ action: "event"
127
+ }, {
128
+ F: __dxlog_file,
129
+ L: 57,
130
+ S: this,
131
+ C: (f, a) => f(...a)
132
+ });
133
+ return;
134
+ }
135
+ try {
136
+ this._analytics.track({
137
+ ...options,
138
+ context: Object.fromEntries(this._getTags().entries()),
139
+ userId,
140
+ anonymousId,
141
+ event
142
+ });
143
+ } catch (err) {
144
+ import_log2.log.catch("Failed to track event", err, {
145
+ F: __dxlog_file,
146
+ L: 70,
147
+ S: this,
148
+ C: (f, a) => f(...a)
149
+ });
150
+ }
151
+ }
152
+ /**
153
+ * Flush the event queue.
154
+ */
155
+ async flush() {
156
+ if (!this._analytics) {
157
+ (0, import_log2.log)("Analytics not initialized", {
158
+ action: "flush"
159
+ }, {
160
+ F: __dxlog_file,
161
+ L: 79,
162
+ S: this,
163
+ C: (f, a) => f(...a)
164
+ });
165
+ return;
166
+ }
167
+ try {
168
+ await this._analytics.flush((err) => {
169
+ (0, import_chunk_FSAOBKO2.captureException)(err);
170
+ });
171
+ } catch (err) {
172
+ import_log2.log.catch("Failed to flush", err, {
173
+ F: __dxlog_file,
174
+ L: 88,
175
+ S: this,
176
+ C: (f, a) => f(...a)
177
+ });
178
+ }
179
+ }
180
+ };
181
+ var mapSpaces = (spaces, options = {
182
+ verbose: false,
183
+ truncateKeys: false
184
+ }) => {
185
+ return spaces.map((space) => {
186
+ const { open, ready } = space.internal.data.metrics ?? {};
187
+ const startup = open && ready && ready.getTime() - open.getTime();
188
+ const pipeline = space.internal.data.pipeline;
189
+ const startDataMutations = pipeline?.currentEpoch?.subject.assertion.timeframe.totalMessages() ?? 0;
190
+ const epoch = pipeline?.currentEpoch?.subject.assertion.number;
191
+ const currentDataMutations = pipeline?.currentDataTimeframe?.totalMessages() ?? 0;
192
+ const totalDataMutations = pipeline?.targetDataTimeframe?.totalMessages() ?? 0;
193
+ return {
194
+ // TODO(nf): truncate keys for DD?
195
+ key: space.key.truncate(),
196
+ open: space.isOpen,
197
+ name: space.properties.name,
198
+ members: space.members.get().length,
199
+ objects: space.db.query().objects.length,
200
+ startup,
201
+ epoch,
202
+ // appliedEpoch,
203
+ startDataMutations,
204
+ currentDataMutations,
205
+ totalDataMutations,
206
+ // TODO(burdon): Negative?
207
+ progress: (Math.min(Math.abs((currentDataMutations - startDataMutations) / (totalDataMutations - startDataMutations)), 1) * 100).toFixed(0)
208
+ };
209
+ });
210
+ };
211
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/observability/src/observability.ts";
212
+ var SPACE_METRICS_MIN_INTERVAL = 1e3 * 60;
213
+ var DATADOG_IDLE_INTERVAL = 1e3 * 60 * 1;
214
+ var ERROR_TAGS = [
215
+ "identityKey",
216
+ "username",
217
+ "deviceKey",
218
+ "group"
219
+ ];
220
+ var Observability = class {
221
+ // TODO(nf): make platform a required extension?
222
+ constructor({ namespace, config, secrets, group, mode, telemetry, errorLog, logProcessor }) {
223
+ this._mode = "disabled";
224
+ this._ctx = new import_context.Context();
225
+ this._tags = /* @__PURE__ */ new Map();
226
+ this._namespace = namespace;
227
+ this._config = config;
228
+ this._mode = mode ?? "disabled";
229
+ this._group = group;
230
+ this._secrets = this._loadSecrets(config, secrets);
231
+ this._telemetryBatchSize = telemetry?.batchSize ?? 30;
232
+ this._errorReportingOptions = errorLog?.sentryInitOptions;
233
+ this._errorLogProcessor = logProcessor ?? false;
234
+ if (this._group) {
235
+ this.setTag("group", this._group);
236
+ }
237
+ this.setTag("namespace", this._namespace);
238
+ if (this._mode === "full") {
239
+ }
240
+ }
241
+ _loadSecrets(config, secrets) {
242
+ if ((0, import_util.isNode)()) {
243
+ return cli_observability_secrets_default;
244
+ } else {
245
+ (0, import_invariant.invariant)(config, "runtime config is required", {
246
+ F: __dxlog_file2,
247
+ L: 117,
248
+ S: this,
249
+ A: [
250
+ "config",
251
+ "'runtime config is required'"
252
+ ]
253
+ });
254
+ (0, import_log.log)("config", {
255
+ rtc: this._secrets,
256
+ config
257
+ }, {
258
+ F: __dxlog_file2,
259
+ L: 118,
260
+ S: this,
261
+ C: (f, a) => f(...a)
262
+ });
263
+ return {
264
+ DX_ENVIRONMENT: config.get("runtime.app.env.DX_ENVIRONMENT"),
265
+ DX_RELEASE: config.get("runtime.app.env.DX_RELEASE"),
266
+ SENTRY_DESTINATION: config.get("runtime.app.env.DX_SENTRY_DESTINATION"),
267
+ TELEMETRY_API_KEY: config.get("runtime.app.env.DX_TELEMETRY_API_KEY"),
268
+ IPDATA_API_KEY: config.get("runtime.app.env.DX_IPDATA_API_KEY"),
269
+ DATADOG_API_KEY: config.get("runtime.app.env.DX_DATADOG_API_KEY"),
270
+ DATADOG_APP_KEY: config.get("runtime.app.env.DX_DATADOG_APP_KEY"),
271
+ ...secrets
272
+ };
273
+ }
274
+ }
275
+ initialize() {
276
+ this._initMetrics();
277
+ this._initTelemetry();
278
+ this._initErrorLogs();
279
+ }
280
+ async close() {
281
+ await this._ctx.dispose();
282
+ }
283
+ setMode(mode) {
284
+ this._mode = mode;
285
+ }
286
+ get mode() {
287
+ return this._mode;
288
+ }
289
+ get enabled() {
290
+ return this._mode !== "disabled";
291
+ }
292
+ //
293
+ // Tags
294
+ //
295
+ /**
296
+ * Set a tag for all observability services.
297
+ */
298
+ setTag(key, value) {
299
+ if (this.enabled && ERROR_TAGS.includes(key)) {
300
+ (0, import_chunk_FSAOBKO2.setTag)(key, value);
301
+ }
302
+ this._tags.set(key, value);
303
+ }
304
+ // TODO(nf): Combine with setDeviceTags.
305
+ async setIdentityTags(client) {
306
+ client.services.services.IdentityService.queryIdentity().subscribe((idqr) => {
307
+ if (!idqr?.identity?.identityKey) {
308
+ (0, import_log.log)("empty response from identity service", {
309
+ idqr
310
+ }, {
311
+ F: __dxlog_file2,
312
+ L: 175,
313
+ S: this,
314
+ C: (f, a) => f(...a)
315
+ });
316
+ return;
317
+ }
318
+ this.setTag("identityKey", idqr?.identity?.identityKey.truncate());
319
+ if (idqr?.identity?.profile?.displayName) {
320
+ this.setTag("username", idqr?.identity?.profile?.displayName);
321
+ }
322
+ });
323
+ }
324
+ async setDeviceTags(client) {
325
+ client.services.services.DevicesService.queryDevices().subscribe((dqr) => {
326
+ if (!dqr || !dqr.devices || dqr.devices.length === 0) {
327
+ (0, import_log.log)("empty response from device service", {
328
+ device: dqr
329
+ }, {
330
+ F: __dxlog_file2,
331
+ L: 191,
332
+ S: this,
333
+ C: (f, a) => f(...a)
334
+ });
335
+ return;
336
+ }
337
+ (0, import_invariant.invariant)(dqr, "empty response from device service", {
338
+ F: __dxlog_file2,
339
+ L: 194,
340
+ S: this,
341
+ A: [
342
+ "dqr",
343
+ "'empty response from device service'"
344
+ ]
345
+ });
346
+ const thisDevice = dqr.devices.find((device) => device.kind === import_services.DeviceKind.CURRENT);
347
+ if (!thisDevice) {
348
+ (0, import_log.log)("no current device", {
349
+ device: dqr
350
+ }, {
351
+ F: __dxlog_file2,
352
+ L: 198,
353
+ S: this,
354
+ C: (f, a) => f(...a)
355
+ });
356
+ return;
357
+ }
358
+ this.setTag("deviceKey", thisDevice.deviceKey.truncate());
359
+ if (thisDevice.profile?.label) {
360
+ this.setTag("deviceProfile", thisDevice.profile.label);
361
+ }
362
+ });
363
+ }
364
+ //
365
+ // Metrics
366
+ //
367
+ _initMetrics() {
368
+ if (this.enabled && this._secrets.DATADOG_API_KEY) {
369
+ this._metrics = new import_chunk_VDBBIYH6.DatadogMetrics({
370
+ apiKey: this._secrets.DATADOG_API_KEY,
371
+ getTags: () => this._tags,
372
+ // TODO(nf): move/refactor from telementryContext, needed to read CORS proxy
373
+ config: this._config
374
+ });
375
+ } else {
376
+ (0, import_log.log)("datadog disabled", void 0, {
377
+ F: __dxlog_file2,
378
+ L: 221,
379
+ S: this,
380
+ C: (f, a) => f(...a)
381
+ });
382
+ }
383
+ }
384
+ /**
385
+ * Gauge metric.
386
+ *
387
+ * The default implementation uses Datadog.
388
+ */
389
+ gauge(name, value, extraTags) {
390
+ this._metrics?.gauge(name, value, extraTags);
391
+ }
392
+ // TODO(nf): Refactor into ObservabilityExtensions.
393
+ startNetworkMetrics(client) {
394
+ const updateSignalMetrics = new import_async.Event();
395
+ updateSignalMetrics.on(this._ctx, async (networkStatus) => {
396
+ (0, import_log.log)("send signal metrics", void 0, {
397
+ F: __dxlog_file2,
398
+ L: 241,
399
+ S: this,
400
+ C: (f, a) => f(...a)
401
+ });
402
+ networkStatus.signaling.forEach(({ server, state }) => {
403
+ this.gauge("dxos.client.network.signal.connectionState", state, {
404
+ server
405
+ });
406
+ });
407
+ let swarmCount = 0;
408
+ const connectionStates = /* @__PURE__ */ new Map();
409
+ for (const state in import_network_manager.ConnectionState) {
410
+ connectionStates.set(state, 0);
411
+ }
412
+ let totalReadBufferSize = 0;
413
+ let totalWriteBufferSize = 0;
414
+ let totalChannelBufferSize = 0;
415
+ networkStatus.connectionInfo?.forEach((connectionInfo) => {
416
+ swarmCount++;
417
+ for (const conn of connectionInfo.connections ?? []) {
418
+ connectionStates.set(conn.state, (connectionStates.get(conn.state) ?? 0) + 1);
419
+ totalReadBufferSize += conn.readBufferSize ?? 0;
420
+ totalWriteBufferSize += conn.writeBufferSize ?? 0;
421
+ for (const stream of conn.streams ?? []) {
422
+ totalChannelBufferSize += stream.writeBufferSize ?? 0;
423
+ }
424
+ }
425
+ this.gauge("dxos.client.network.swarm.count", swarmCount);
426
+ for (const state in import_network_manager.ConnectionState) {
427
+ this.gauge("dxos.client.network.connection.count", connectionStates.get(state) ?? 0, {
428
+ state
429
+ });
430
+ }
431
+ this.gauge("dxox.client.network.totalReadBufferSize", totalReadBufferSize);
432
+ this.gauge("dxos.client.network.totalWriteBufferSize", totalWriteBufferSize);
433
+ this.gauge("dxos.client.network.totalChannelBufferSize", totalChannelBufferSize);
434
+ });
435
+ });
436
+ client.services.services.NetworkService?.queryStatus().subscribe((networkStatus) => {
437
+ updateSignalMetrics.emit(networkStatus);
438
+ });
439
+ }
440
+ startSpacesMetrics(client) {
441
+ let spaces = client.spaces.get();
442
+ const subscriptions = /* @__PURE__ */ new Map();
443
+ this._ctx.onDispose(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));
444
+ const updateSpaceMetrics = new import_async.Event().debounce(SPACE_METRICS_MIN_INTERVAL);
445
+ updateSpaceMetrics.on(this._ctx, async (space) => {
446
+ (0, import_log.log)("send space update", void 0, {
447
+ F: __dxlog_file2,
448
+ L: 293,
449
+ S: this,
450
+ C: (f, a) => f(...a)
451
+ });
452
+ for (const sp of mapSpaces(spaces, {
453
+ truncateKeys: true
454
+ })) {
455
+ this.gauge("dxos.client.space.members", sp.members, {
456
+ key: sp.key
457
+ });
458
+ this.gauge("dxos.client.space.objects", sp.objects, {
459
+ key: sp.key
460
+ });
461
+ this.gauge("dxos.client.space.epoch", sp.epoch, {
462
+ key: sp.key
463
+ });
464
+ this.gauge("dxos.client.space.currentDataMutations", sp.currentDataMutations, {
465
+ key: sp.key
466
+ });
467
+ }
468
+ });
469
+ const subscribeToSpaceUpdate = (space) => space.pipeline.subscribe({
470
+ next: () => {
471
+ updateSpaceMetrics.emit();
472
+ }
473
+ });
474
+ spaces.forEach((space) => {
475
+ subscriptions.set(space.key.toHex(), subscribeToSpaceUpdate(space));
476
+ });
477
+ client.spaces.subscribe({
478
+ next: async () => {
479
+ spaces = client.spaces.get();
480
+ spaces.filter((space) => !subscriptions.has(space.key.toHex())).forEach((space) => {
481
+ subscriptions.set(space.key.toHex(), subscribeToSpaceUpdate(space));
482
+ });
483
+ }
484
+ });
485
+ (0, import_async.scheduleTaskInterval)(this._ctx, async () => updateSpaceMetrics.emit(), DATADOG_IDLE_INTERVAL);
486
+ }
487
+ async startRuntimeMetrics(client, frequency = DATADOG_IDLE_INTERVAL) {
488
+ const platform = await client.services.services.SystemService?.getPlatform();
489
+ (0, import_invariant.invariant)(platform, "platform is required", {
490
+ F: __dxlog_file2,
491
+ L: 330,
492
+ S: this,
493
+ A: [
494
+ "platform",
495
+ "'platform is required'"
496
+ ]
497
+ });
498
+ this.setTag("platform_type", import_services.Platform.PLATFORM_TYPE[platform.type].toLowerCase());
499
+ if (this._mode === "full") {
500
+ if (platform.platform) {
501
+ this.setTag("platform", platform.platform);
502
+ }
503
+ if (platform.arch) {
504
+ this.setTag("arch", platform.arch);
505
+ }
506
+ if (platform.runtime) {
507
+ this.setTag("runtime", platform.runtime);
508
+ }
509
+ }
510
+ (0, import_async.scheduleTaskInterval)(this._ctx, async () => {
511
+ (0, import_log.log)("platform", void 0, {
512
+ F: __dxlog_file2,
513
+ L: 348,
514
+ S: this,
515
+ C: (f, a) => f(...a)
516
+ });
517
+ client.services.services.SystemService?.getPlatform().then((platform2) => {
518
+ (0, import_log.log)("platform", {
519
+ platform: platform2
520
+ }, {
521
+ F: __dxlog_file2,
522
+ L: 351,
523
+ S: this,
524
+ C: (f, a) => f(...a)
525
+ });
526
+ if (platform2.memory) {
527
+ this.gauge("dxos.client.runtime.rss", platform2.memory.rss);
528
+ this.gauge("dxos.client.runtime.heapTotal", platform2.memory.heapTotal);
529
+ this.gauge("dxos.client.runtime.heapUsed", platform2.memory.heapUsed);
530
+ }
531
+ }).catch((error) => (0, import_log.log)("platform error", {
532
+ error
533
+ }, {
534
+ F: __dxlog_file2,
535
+ L: 358,
536
+ S: this,
537
+ C: (f, a) => f(...a)
538
+ }));
539
+ }, frequency);
540
+ }
541
+ //
542
+ // Telemetry
543
+ //
544
+ _initTelemetry() {
545
+ if (this._secrets.TELEMETRY_API_KEY && this._mode !== "disabled") {
546
+ this._telemetry = new SegmentTelemetry({
547
+ apiKey: this._secrets.TELEMETRY_API_KEY,
548
+ batchSize: this._telemetryBatchSize,
549
+ getTags: () => this._tags
550
+ });
551
+ } else {
552
+ (0, import_log.log)("segment disabled", void 0, {
553
+ F: __dxlog_file2,
554
+ L: 376,
555
+ S: this,
556
+ C: (f, a) => f(...a)
557
+ });
558
+ }
559
+ }
560
+ /**
561
+ * A telemetry event.
562
+ *
563
+ * The default implementation uses Segment.
564
+ */
565
+ event(options) {
566
+ this._telemetry?.event(options);
567
+ }
568
+ /**
569
+ * A telemetry page view.
570
+ *
571
+ * The default implementation uses Segment.
572
+ */
573
+ page(options) {
574
+ this._telemetry?.page(options);
575
+ }
576
+ //
577
+ // Error Logs
578
+ //
579
+ _initErrorLogs() {
580
+ if (this._secrets.SENTRY_DESTINATION && this._mode !== "disabled") {
581
+ import_log.log.info("Initializing Sentry", {
582
+ dest: this._secrets.SENTRY_DESTINATION,
583
+ options: this._errorReportingOptions
584
+ }, {
585
+ F: __dxlog_file2,
586
+ L: 405,
587
+ S: this,
588
+ C: (f, a) => f(...a)
589
+ });
590
+ (0, import_chunk_FSAOBKO2.init)({
591
+ ...this._errorReportingOptions,
592
+ destination: this._secrets.SENTRY_DESTINATION,
593
+ scrubFilenames: this._mode !== "full"
594
+ });
595
+ if (this._errorReportingOptions?.tracing) {
596
+ (0, import_chunk_FSAOBKO2.configureTracing)();
597
+ }
598
+ if (this._errorLogProcessor) {
599
+ (0, import_chunk_FSAOBKO2.enableSentryLogProcessor)();
600
+ }
601
+ this._tags.forEach((v, k) => {
602
+ if (ERROR_TAGS.includes(k)) {
603
+ (0, import_chunk_FSAOBKO2.setTag)(k, v);
604
+ }
605
+ });
606
+ } else {
607
+ (0, import_log.log)("sentry disabled", void 0, {
608
+ F: __dxlog_file2,
609
+ L: 428,
610
+ S: this,
611
+ C: (f, a) => f(...a)
612
+ });
613
+ }
614
+ }
615
+ /**
616
+ * Manually capture an exception.
617
+ *
618
+ * The default implementation uses Sentry.
619
+ */
620
+ captureException(err) {
621
+ if (this.enabled) {
622
+ (0, import_chunk_FSAOBKO2.captureException)(err);
623
+ }
624
+ }
625
+ };
626
+ // Annotate the CommonJS export names for ESM import in node:
627
+ 0 && (module.exports = {
628
+ Observability
629
+ });
630
+ //# sourceMappingURL=index.cjs.map