@dxos/observability 0.6.13 → 0.6.14-main.2b6a0f3

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 (57) hide show
  1. package/dist/lib/browser/{chunk-QUPP43SQ.mjs → chunk-4OXG76Y3.mjs} +58 -388
  2. package/dist/lib/browser/chunk-4OXG76Y3.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +323 -13
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/observability-WZNQCJ5C.mjs +7 -0
  7. package/dist/lib/node/{chunk-2ZVQBEPN.cjs → chunk-AMV7JU2O.cjs} +44 -379
  8. package/dist/lib/node/chunk-AMV7JU2O.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +340 -15
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.json +1 -1
  12. package/dist/lib/node/{observability-YPS7RMWB.cjs → observability-Y2NU446N.cjs} +6 -6
  13. package/dist/lib/node/{observability-YPS7RMWB.cjs.map → observability-Y2NU446N.cjs.map} +2 -2
  14. package/dist/lib/node-esm/chunk-CMDADTM3.mjs +133 -0
  15. package/dist/lib/node-esm/chunk-CMDADTM3.mjs.map +7 -0
  16. package/dist/lib/node-esm/chunk-D7JZEGRD.mjs +609 -0
  17. package/dist/lib/node-esm/chunk-D7JZEGRD.mjs.map +7 -0
  18. package/dist/lib/node-esm/chunk-YJ4KVBWC.mjs +2 -0
  19. package/dist/lib/node-esm/chunk-YJ4KVBWC.mjs.map +7 -0
  20. package/dist/lib/node-esm/index.mjs +344 -0
  21. package/dist/lib/node-esm/index.mjs.map +7 -0
  22. package/dist/lib/node-esm/meta.json +1 -0
  23. package/dist/lib/node-esm/observability-RAXT3Z2H.mjs +8 -0
  24. package/dist/lib/node-esm/observability-RAXT3Z2H.mjs.map +7 -0
  25. package/dist/lib/node-esm/otel-YI7HAFOG.mjs +258 -0
  26. package/dist/lib/node-esm/otel-YI7HAFOG.mjs.map +7 -0
  27. package/dist/lib/node-esm/segment/index.mjs +144 -0
  28. package/dist/lib/node-esm/segment/index.mjs.map +7 -0
  29. package/dist/lib/node-esm/sentry/index.mjs +25 -0
  30. package/dist/lib/node-esm/sentry/index.mjs.map +7 -0
  31. package/dist/lib/node-esm/sentry-log-processor-JYJH3AMG.mjs +133 -0
  32. package/dist/lib/node-esm/sentry-log-processor-JYJH3AMG.mjs.map +7 -0
  33. package/dist/types/src/observability.d.ts.map +1 -1
  34. package/dist/types/src/observability.js +2 -0
  35. package/dist/types/src/observability.js.map +1 -1
  36. package/dist/types/src/sentry/node.node.test.d.ts +2 -0
  37. package/dist/types/src/sentry/node.node.test.d.ts.map +1 -0
  38. package/dist/types/src/sentry/{node.test.js → node.node.test.js} +8 -15
  39. package/dist/types/src/sentry/node.node.test.js.map +1 -0
  40. package/dist/types/src/sentry/sentry.node.test.d.ts +2 -0
  41. package/dist/types/src/sentry/sentry.node.test.d.ts.map +1 -0
  42. package/dist/types/src/sentry/{sentry.test.js → sentry.node.test.js} +8 -15
  43. package/dist/types/src/sentry/sentry.node.test.js.map +1 -0
  44. package/package.json +22 -18
  45. package/src/observability.ts +2 -1
  46. package/src/sentry/{node.test.ts → node.node.test.ts} +2 -9
  47. package/src/sentry/{sentry.test.ts → sentry.node.test.ts} +2 -7
  48. package/dist/lib/browser/chunk-QUPP43SQ.mjs.map +0 -7
  49. package/dist/lib/browser/observability-EJU34BZA.mjs +0 -7
  50. package/dist/lib/node/chunk-2ZVQBEPN.cjs.map +0 -7
  51. package/dist/types/src/sentry/node.test.d.ts +0 -2
  52. package/dist/types/src/sentry/node.test.d.ts.map +0 -1
  53. package/dist/types/src/sentry/node.test.js.map +0 -1
  54. package/dist/types/src/sentry/sentry.test.d.ts +0 -2
  55. package/dist/types/src/sentry/sentry.test.d.ts.map +0 -1
  56. package/dist/types/src/sentry/sentry.test.js.map +0 -1
  57. /package/dist/lib/browser/{observability-EJU34BZA.mjs.map → observability-WZNQCJ5C.mjs.map} +0 -0
@@ -0,0 +1,609 @@
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+
3
+ // packages/sdk/observability/src/observability.ts
4
+ import { Event, scheduleTaskInterval } from "@dxos/async";
5
+ import { PublicKey } from "@dxos/client";
6
+ import { Context } from "@dxos/context";
7
+ import { invariant } from "@dxos/invariant";
8
+ import { 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
+
13
+ // packages/sdk/observability/src/cli-observability-secrets.json
14
+ var cli_observability_secrets_default = {
15
+ SENTRY_DESTINATION: "https://2647916221e643869965e78469479aa4@o4504012000067584.ingest.sentry.io/4504012027265029",
16
+ TELEMETRY_API_KEY: "B00QG6PtJJrJ0VVFe0H5a6bcUUShKyZM",
17
+ IPDATA_API_KEY: "73dfdecdf979c18f07d50cf841bbdd9e589f237256326ac8cca23786",
18
+ OTEL_ENDPOINT: null,
19
+ OTEL_AUTHORIZATION: null
20
+ };
21
+
22
+ // packages/sdk/observability/src/helpers/common.ts
23
+ var getTelemetryIdentifier = (client) => {
24
+ if (!client?.initialized) {
25
+ return void 0;
26
+ }
27
+ const identity = client.halo.identity.get();
28
+ if (identity) {
29
+ return identity.identityKey.truncate();
30
+ }
31
+ return void 0;
32
+ };
33
+
34
+ // packages/sdk/observability/src/helpers/map-spaces.ts
35
+ var mapSpaces = (spaces, options = {
36
+ verbose: false,
37
+ truncateKeys: false
38
+ }) => {
39
+ return spaces.map((space) => {
40
+ const { open, ready } = space.internal.data.metrics ?? {};
41
+ const startup = open && ready && ready.getTime() - open.getTime();
42
+ const pipeline = space.internal.data.pipeline;
43
+ const startDataMutations = pipeline?.currentEpoch?.subject.assertion.timeframe.totalMessages() ?? 0;
44
+ const epoch = pipeline?.currentEpoch?.subject.assertion.number;
45
+ const currentDataMutations = pipeline?.currentDataTimeframe?.totalMessages() ?? 0;
46
+ const totalDataMutations = pipeline?.targetDataTimeframe?.totalMessages() ?? 0;
47
+ return {
48
+ // TODO(nf): truncate keys for DD?
49
+ key: space.key.truncate(),
50
+ open: space.isOpen,
51
+ members: space.members.get().length,
52
+ objects: space.db.coreDatabase.getAllObjectIds().length,
53
+ startup,
54
+ epoch,
55
+ // appliedEpoch,
56
+ startDataMutations,
57
+ currentDataMutations,
58
+ totalDataMutations,
59
+ // TODO(burdon): Negative?
60
+ progress: (Math.min(Math.abs((currentDataMutations - startDataMutations) / (totalDataMutations - startDataMutations)), 1) * 100).toFixed(0)
61
+ };
62
+ });
63
+ };
64
+
65
+ // packages/sdk/observability/src/observability.ts
66
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/observability/src/observability.ts";
67
+ var SPACE_METRICS_MIN_INTERVAL = 1e3 * 60;
68
+ var SPACE_TELEMETRY_MIN_INTERVAL = 1e3 * 60 * 60;
69
+ var NETWORK_METRICS_MIN_INTERVAL = 1e3 * 60 * 5;
70
+ var Observability = class {
71
+ // TODO(nf): make platform a required extension?
72
+ constructor({ namespace, environment, release, config, secrets, group, mode, telemetry, errorLog }) {
73
+ // TODO(nf): accept upstream context?
74
+ this._ctx = new Context(void 0, {
75
+ F: __dxlog_file,
76
+ L: 87
77
+ });
78
+ this._tags = /* @__PURE__ */ new Map();
79
+ this.addIPDataTelemetryTags = (ipData) => {
80
+ this.setTag("city", ipData.city, "telemetry");
81
+ this.setTag("region", ipData.region, "telemetry");
82
+ this.setTag("country", ipData.country, "telemetry");
83
+ ipData.latitude && this.setTag("latitude", ipData.latitude.toString(), "telemetry");
84
+ ipData.longitude && this.setTag("longitude", ipData.longitude.toString(), "telemetry");
85
+ };
86
+ this._namespace = namespace;
87
+ this._mode = mode;
88
+ this._config = config;
89
+ this._group = group;
90
+ this._secrets = this._loadSecrets(config, secrets);
91
+ this._telemetryBatchSize = telemetry?.batchSize ?? 30;
92
+ this._errorReportingOptions = errorLog?.sentryInitOptions;
93
+ if (this._group) {
94
+ this.setTag("group", this._group);
95
+ }
96
+ this.setTag("namespace", this._namespace);
97
+ environment && this.setTag("environment", environment);
98
+ release && this.setTag("release", release);
99
+ this.setTag("mode", this._mode);
100
+ this.setTag("session", PublicKey.random().toHex());
101
+ }
102
+ get mode() {
103
+ return this._mode;
104
+ }
105
+ get group() {
106
+ return this._group;
107
+ }
108
+ get enabled() {
109
+ return this._mode !== "disabled";
110
+ }
111
+ _loadSecrets(config, secrets) {
112
+ if (isNode()) {
113
+ const mergedSecrets = {
114
+ ...cli_observability_secrets_default,
115
+ ...secrets
116
+ };
117
+ process.env.DX_ENVIRONMENT && (mergedSecrets.DX_ENVIRONMENT = process.env.DX_ENVIRONMENT);
118
+ process.env.DX_RELEASE && (mergedSecrets.DX_RELEASE = process.env.DX_RELEASE);
119
+ process.env.SENTRY_DESTINATION && (mergedSecrets.SENTRY_DESTINATION = process.env.SENTRY_DESTINATION);
120
+ process.env.TELEMETRY_API_KEY && (mergedSecrets.TELEMETRY_API_KEY = process.env.TELEMETRY_API_KEY);
121
+ process.env.IPDATA_API_KEY && (mergedSecrets.IPDATA_API_KEY = process.env.IPDATA_API_KEY);
122
+ process.env.DX_OTEL_ENDPOINT && (mergedSecrets.OTEL_ENDPOINT = process.env.DX_OTEL_ENDPOINT);
123
+ process.env.DX_OTEL_AUTHORIZATION && (mergedSecrets.OTEL_AUTHORIZATION = process.env.DX_OTEL_AUTHORIZATION);
124
+ return mergedSecrets;
125
+ } else {
126
+ log("config", {
127
+ rtc: this._secrets,
128
+ config
129
+ }, {
130
+ F: __dxlog_file,
131
+ L: 151,
132
+ S: this,
133
+ C: (f, a) => f(...a)
134
+ });
135
+ return {
136
+ DX_ENVIRONMENT: config?.get("runtime.app.env.DX_ENVIRONMENT"),
137
+ DX_RELEASE: config?.get("runtime.app.env.DX_RELEASE"),
138
+ SENTRY_DESTINATION: config?.get("runtime.app.env.DX_SENTRY_DESTINATION"),
139
+ TELEMETRY_API_KEY: config?.get("runtime.app.env.DX_TELEMETRY_API_KEY"),
140
+ IPDATA_API_KEY: config?.get("runtime.app.env.DX_IPDATA_API_KEY"),
141
+ OTEL_ENDPOINT: config?.get("runtime.app.env.DX_OTEL_ENDPOINT"),
142
+ OTEL_AUTHORIZATION: config?.get("runtime.app.env.DX_OTEL_AUTHORIZATION"),
143
+ ...secrets
144
+ };
145
+ }
146
+ }
147
+ async initialize() {
148
+ await this._initMetrics();
149
+ await this._initTelemetry();
150
+ await this._initErrorLogs();
151
+ await this._initTraces();
152
+ }
153
+ async close() {
154
+ const closes = [];
155
+ this._telemetry && closes.push(this._telemetry.close());
156
+ this._otelMetrics && closes.push(this._otelMetrics.close());
157
+ this._otelLogs && closes.push(this._otelLogs.close());
158
+ await Promise.all(closes);
159
+ await this._ctx.dispose();
160
+ }
161
+ setMode(mode) {
162
+ this._mode = mode;
163
+ }
164
+ //
165
+ // Tags
166
+ //
167
+ setTag(key, value, scope) {
168
+ if (this.enabled && (scope === void 0 || scope === "all" || scope === "errors")) {
169
+ this._setTag?.(key, value);
170
+ }
171
+ if (!scope) {
172
+ scope = "all";
173
+ }
174
+ this._tags.set(key, {
175
+ value,
176
+ scope
177
+ });
178
+ }
179
+ getTag(key) {
180
+ return this._tags.get(key);
181
+ }
182
+ // TODO(wittjosiah): Improve privacy of telemetry identifiers. See `getTelemetryIdentifier`.
183
+ async setIdentityTags(clientServices) {
184
+ if (clientServices.IdentityService) {
185
+ clientServices.IdentityService.queryIdentity().subscribe((idqr) => {
186
+ if (!idqr?.identity?.identityKey) {
187
+ log("empty response from identity service", {
188
+ idqr
189
+ }, {
190
+ F: __dxlog_file,
191
+ L: 219,
192
+ S: this,
193
+ C: (f, a) => f(...a)
194
+ });
195
+ return;
196
+ }
197
+ this.setTag("identityKey", idqr.identity.identityKey.truncate());
198
+ });
199
+ }
200
+ if (clientServices.DevicesService) {
201
+ clientServices.DevicesService.queryDevices().subscribe((dqr) => {
202
+ if (!dqr || !dqr.devices || dqr.devices.length === 0) {
203
+ log("empty response from device service", {
204
+ device: dqr
205
+ }, {
206
+ F: __dxlog_file,
207
+ L: 229,
208
+ S: this,
209
+ C: (f, a) => f(...a)
210
+ });
211
+ return;
212
+ }
213
+ invariant(dqr, "empty response from device service", {
214
+ F: __dxlog_file,
215
+ L: 232,
216
+ S: this,
217
+ A: [
218
+ "dqr",
219
+ "'empty response from device service'"
220
+ ]
221
+ });
222
+ const thisDevice = dqr.devices.find((device) => device.kind === DeviceKind.CURRENT);
223
+ if (!thisDevice) {
224
+ log("no current device", {
225
+ device: dqr
226
+ }, {
227
+ F: __dxlog_file,
228
+ L: 236,
229
+ S: this,
230
+ C: (f, a) => f(...a)
231
+ });
232
+ return;
233
+ }
234
+ this.setTag("deviceKey", thisDevice.deviceKey.truncate());
235
+ if (thisDevice.profile?.label) {
236
+ this.setTag("deviceProfile", thisDevice.profile.label);
237
+ }
238
+ });
239
+ }
240
+ }
241
+ //
242
+ // Metrics
243
+ //
244
+ async _initMetrics() {
245
+ if (this.enabled && this._secrets.OTEL_ENDPOINT && this._secrets.OTEL_AUTHORIZATION) {
246
+ const { OtelMetrics } = await import("./otel-YI7HAFOG.mjs");
247
+ this._otelMetrics = new OtelMetrics({
248
+ endpoint: this._secrets.OTEL_ENDPOINT,
249
+ authorizationHeader: this._secrets.OTEL_AUTHORIZATION,
250
+ serviceName: this._namespace,
251
+ serviceVersion: this.getTag("release")?.value ?? "0.0.0",
252
+ getTags: () => Object.fromEntries(Array.from(this._tags).filter(([key, value]) => {
253
+ return value.scope === "all" || value.scope === "metrics";
254
+ }).map(([key, value]) => [
255
+ key,
256
+ value.value
257
+ ]))
258
+ });
259
+ log("otel metrics enabled", void 0, {
260
+ F: __dxlog_file,
261
+ L: 268,
262
+ S: this,
263
+ C: (f, a) => f(...a)
264
+ });
265
+ } else {
266
+ log("otel metrics disabled", void 0, {
267
+ F: __dxlog_file,
268
+ L: 270,
269
+ S: this,
270
+ C: (f, a) => f(...a)
271
+ });
272
+ }
273
+ }
274
+ /**
275
+ * Gauge metric.
276
+ *
277
+ * The default implementation uses OpenTelemetry
278
+ */
279
+ gauge(name, value, extraTags) {
280
+ this._otelMetrics?.gauge(name, value, extraTags);
281
+ }
282
+ // TODO(nf): Refactor into ObservabilityExtensions.
283
+ startNetworkMetrics(clientServices) {
284
+ if (!clientServices.NetworkService) {
285
+ return;
286
+ }
287
+ const updateSignalMetrics = new Event().debounce(NETWORK_METRICS_MIN_INTERVAL);
288
+ updateSignalMetrics.on(this._ctx, async () => {
289
+ log("send signal metrics", void 0, {
290
+ F: __dxlog_file,
291
+ L: 292,
292
+ S: this,
293
+ C: (f, a) => f(...a)
294
+ });
295
+ (this._lastNetworkStatus?.signaling).forEach(({ server, state }) => {
296
+ this.gauge("dxos.client.network.signal.connectionState", state, {
297
+ server
298
+ });
299
+ });
300
+ let swarmCount = 0;
301
+ const connectionStates = /* @__PURE__ */ new Map();
302
+ for (const state in ConnectionState) {
303
+ connectionStates.set(state, 0);
304
+ }
305
+ let totalReadBufferSize = 0;
306
+ let totalWriteBufferSize = 0;
307
+ let totalChannelBufferSize = 0;
308
+ this._lastNetworkStatus?.connectionInfo?.forEach((connectionInfo) => {
309
+ swarmCount++;
310
+ for (const conn of connectionInfo.connections ?? []) {
311
+ connectionStates.set(conn.state, (connectionStates.get(conn.state) ?? 0) + 1);
312
+ totalReadBufferSize += conn.readBufferSize ?? 0;
313
+ totalWriteBufferSize += conn.writeBufferSize ?? 0;
314
+ for (const stream of conn.streams ?? []) {
315
+ totalChannelBufferSize += stream.writeBufferSize ?? 0;
316
+ }
317
+ }
318
+ this.gauge("dxos.client.network.swarm.count", swarmCount);
319
+ for (const state in ConnectionState) {
320
+ this.gauge("dxos.client.network.connection.count", connectionStates.get(state) ?? 0, {
321
+ state
322
+ });
323
+ }
324
+ this.gauge("dxos.client.network.totalReadBufferSize", totalReadBufferSize);
325
+ this.gauge("dxos.client.network.totalWriteBufferSize", totalWriteBufferSize);
326
+ this.gauge("dxos.client.network.totalChannelBufferSize", totalChannelBufferSize);
327
+ });
328
+ });
329
+ clientServices.NetworkService.queryStatus().subscribe((networkStatus) => {
330
+ this._lastNetworkStatus = networkStatus;
331
+ updateSignalMetrics.emit();
332
+ });
333
+ scheduleTaskInterval(this._ctx, async () => updateSignalMetrics.emit(), NETWORK_METRICS_MIN_INTERVAL);
334
+ }
335
+ startSpacesMetrics(client, namespace) {
336
+ const spaces = client.spaces.get();
337
+ const subscriptions = /* @__PURE__ */ new Map();
338
+ this._ctx.onDispose(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));
339
+ const updateSpaceMetrics = new Event().debounce(SPACE_METRICS_MIN_INTERVAL);
340
+ updateSpaceMetrics.on(this._ctx, async () => {
341
+ log("send space metrics", void 0, {
342
+ F: __dxlog_file,
343
+ L: 346,
344
+ S: this,
345
+ C: (f, a) => f(...a)
346
+ });
347
+ for (const data of mapSpaces(spaces, {
348
+ truncateKeys: true
349
+ })) {
350
+ this.gauge("dxos.client.space.members", data.members, {
351
+ key: data.key
352
+ });
353
+ this.gauge("dxos.client.space.objects", data.objects, {
354
+ key: data.key
355
+ });
356
+ this.gauge("dxos.client.space.epoch", data.epoch, {
357
+ key: data.key
358
+ });
359
+ this.gauge("dxos.client.space.currentDataMutations", data.currentDataMutations, {
360
+ key: data.key
361
+ });
362
+ }
363
+ });
364
+ const updateSpaceTelemetry = new Event().debounce(SPACE_TELEMETRY_MIN_INTERVAL);
365
+ updateSpaceTelemetry.on(this._ctx, async () => {
366
+ log("send space telemetry", void 0, {
367
+ F: __dxlog_file,
368
+ L: 357,
369
+ S: this,
370
+ C: (f, a) => f(...a)
371
+ });
372
+ for (const data of mapSpaces(spaces, {
373
+ truncateKeys: true
374
+ })) {
375
+ this.event({
376
+ identityId: getTelemetryIdentifier(client),
377
+ name: `${namespace}.space.update`,
378
+ properties: data
379
+ });
380
+ }
381
+ });
382
+ const subscribeToSpaceUpdate = (space) => space.pipeline.subscribe({
383
+ next: () => {
384
+ updateSpaceMetrics.emit();
385
+ updateSpaceTelemetry.emit();
386
+ }
387
+ });
388
+ spaces.forEach((space) => {
389
+ subscriptions.set(space.key.toHex(), subscribeToSpaceUpdate(space));
390
+ });
391
+ client.spaces.subscribe({
392
+ next: async (spaces2) => {
393
+ spaces2.filter((space) => !subscriptions.has(space.key.toHex())).forEach((space) => {
394
+ subscriptions.set(space.key.toHex(), subscribeToSpaceUpdate(space));
395
+ });
396
+ }
397
+ });
398
+ scheduleTaskInterval(this._ctx, async () => updateSpaceMetrics.emit(), NETWORK_METRICS_MIN_INTERVAL);
399
+ }
400
+ async startRuntimeMetrics(client, frequency = NETWORK_METRICS_MIN_INTERVAL) {
401
+ const platform = await client.services.services.SystemService?.getPlatform();
402
+ invariant(platform, "platform is required", {
403
+ F: __dxlog_file,
404
+ L: 394,
405
+ S: this,
406
+ A: [
407
+ "platform",
408
+ "'platform is required'"
409
+ ]
410
+ });
411
+ this.setTag("platform_type", Platform.PLATFORM_TYPE[platform.type].toLowerCase());
412
+ if (this._mode === "full") {
413
+ if (platform.platform) {
414
+ this.setTag("platform", platform.platform);
415
+ }
416
+ if (platform.arch) {
417
+ this.setTag("arch", platform.arch);
418
+ }
419
+ if (platform.runtime) {
420
+ this.setTag("runtime", platform.runtime);
421
+ }
422
+ }
423
+ scheduleTaskInterval(this._ctx, async () => {
424
+ if (client.services.constructor.name === "WorkerClientServices") {
425
+ const memory = window.performance.memory;
426
+ if (memory) {
427
+ this.gauge("dxos.client.runtime.heapTotal", memory.totalJSHeapSize);
428
+ this.gauge("dxos.client.runtime.heapUsed", memory.usedJSHeapSize);
429
+ this.gauge("dxos.client.runtime.heapSizeLimit", memory.jsHeapSizeLimit);
430
+ }
431
+ }
432
+ client.services.services.SystemService?.getPlatform().then((platform2) => {
433
+ if (platform2.memory) {
434
+ this.gauge("dxos.client.services.runtime.rss", platform2.memory.rss);
435
+ this.gauge("dxos.client.services.runtime.heapTotal", platform2.memory.heapTotal);
436
+ this.gauge("dxos.client.services.runtime.heapUsed", platform2.memory.heapUsed);
437
+ }
438
+ }).catch((error) => log("platform error", {
439
+ error
440
+ }, {
441
+ F: __dxlog_file,
442
+ L: 429,
443
+ S: this,
444
+ C: (f, a) => f(...a)
445
+ }));
446
+ }, frequency);
447
+ }
448
+ //
449
+ // Telemetry
450
+ //
451
+ async _initTelemetry() {
452
+ if (this._secrets.TELEMETRY_API_KEY && this._mode !== "disabled") {
453
+ const { SegmentTelemetry } = await import("./segment/index.mjs");
454
+ this._telemetry = new SegmentTelemetry({
455
+ apiKey: this._secrets.TELEMETRY_API_KEY,
456
+ batchSize: this._telemetryBatchSize,
457
+ getTags: () => Object.fromEntries(Array.from(this._tags).filter(([key, value]) => {
458
+ return value.scope === "all" || value.scope === "telemetry";
459
+ }).map(([key, value]) => [
460
+ key,
461
+ value.value
462
+ ]))
463
+ });
464
+ } else {
465
+ log("segment disabled", void 0, {
466
+ F: __dxlog_file,
467
+ L: 455,
468
+ S: this,
469
+ C: (f, a) => f(...a)
470
+ });
471
+ }
472
+ }
473
+ /**
474
+ * A telemetry event.
475
+ *
476
+ * The default implementation uses Segment.
477
+ */
478
+ event(options) {
479
+ this._telemetry?.event(options);
480
+ }
481
+ /**
482
+ * A telemetry page view.
483
+ *
484
+ * The default implementation uses Segment.
485
+ */
486
+ page(options) {
487
+ this._telemetry?.page(options);
488
+ }
489
+ //
490
+ // Error Logs
491
+ //
492
+ async _initErrorLogs() {
493
+ if (this._secrets.SENTRY_DESTINATION && this._mode !== "disabled") {
494
+ const { captureException, captureUserFeedback, init, setTag } = await import("./sentry/index.mjs");
495
+ const { SentryLogProcessor } = await import("./sentry-log-processor-JYJH3AMG.mjs");
496
+ this._captureException = captureException;
497
+ this._captureUserFeedback = captureUserFeedback;
498
+ this._setTag = setTag;
499
+ log.info("Initializing Sentry", {
500
+ dest: this._secrets.SENTRY_DESTINATION,
501
+ options: this._errorReportingOptions
502
+ }, {
503
+ F: __dxlog_file,
504
+ L: 491,
505
+ S: this,
506
+ C: (f, a) => f(...a)
507
+ });
508
+ this._sentryLogProcessor = new SentryLogProcessor();
509
+ init({
510
+ ...this._errorReportingOptions,
511
+ destination: this._secrets.SENTRY_DESTINATION,
512
+ scrubFilenames: this._mode !== "full",
513
+ onError: (event) => this._sentryLogProcessor.addLogBreadcrumbsTo(event)
514
+ });
515
+ this._tags.forEach((v, k) => {
516
+ if (v.scope === "all" || v.scope === "errors") {
517
+ setTag(k, v.value);
518
+ }
519
+ });
520
+ } else {
521
+ log("sentry disabled", void 0, {
522
+ F: __dxlog_file,
523
+ L: 511,
524
+ S: this,
525
+ C: (f, a) => f(...a)
526
+ });
527
+ }
528
+ if (this._secrets.OTEL_ENDPOINT && this._secrets.OTEL_AUTHORIZATION && this._mode !== "disabled") {
529
+ const { OtelLogs } = await import("./otel-YI7HAFOG.mjs");
530
+ this._otelLogs = new OtelLogs({
531
+ endpoint: this._secrets.OTEL_ENDPOINT,
532
+ authorizationHeader: this._secrets.OTEL_AUTHORIZATION,
533
+ serviceName: this._namespace,
534
+ serviceVersion: this.getTag("release")?.value ?? "0.0.0",
535
+ getTags: () => Object.fromEntries(Array.from(this._tags).filter(([key, value]) => {
536
+ return value.scope === "all" || value.scope === "errors";
537
+ }).map(([key, value]) => [
538
+ key,
539
+ value.value
540
+ ]))
541
+ });
542
+ log("otel logs enabled", {
543
+ namespace: this._namespace
544
+ }, {
545
+ F: __dxlog_file,
546
+ L: 530,
547
+ S: this,
548
+ C: (f, a) => f(...a)
549
+ });
550
+ } else {
551
+ log("otel logs disabled", void 0, {
552
+ F: __dxlog_file,
553
+ L: 532,
554
+ S: this,
555
+ C: (f, a) => f(...a)
556
+ });
557
+ }
558
+ }
559
+ startErrorLogs() {
560
+ this._sentryLogProcessor && log.runtimeConfig.processors.push(this._sentryLogProcessor.logProcessor);
561
+ this._otelLogs && log.runtimeConfig.processors.push(this._otelLogs.logProcessor);
562
+ }
563
+ startTraces() {
564
+ this._otelTraces && this._otelTraces.start();
565
+ }
566
+ // TODO(nf): refactor init based on providers and their capabilities
567
+ async _initTraces() {
568
+ if (this._secrets.OTEL_ENDPOINT && this._secrets.OTEL_AUTHORIZATION && this._mode !== "disabled") {
569
+ const { OtelTraces } = await import("./otel-YI7HAFOG.mjs");
570
+ this._otelTraces = new OtelTraces({
571
+ endpoint: this._secrets.OTEL_ENDPOINT,
572
+ authorizationHeader: this._secrets.OTEL_AUTHORIZATION,
573
+ serviceName: this._namespace,
574
+ serviceVersion: this.getTag("release")?.value ?? "0.0.0",
575
+ getTags: () => Object.fromEntries(Array.from(this._tags).filter(([key, value]) => {
576
+ return value.scope === "all" || value.scope === "metrics";
577
+ }).map(([key, value]) => [
578
+ key,
579
+ value.value
580
+ ]))
581
+ });
582
+ }
583
+ }
584
+ /**
585
+ * Manually capture an exception.
586
+ *
587
+ * The default implementation uses Sentry.
588
+ */
589
+ captureException(err) {
590
+ if (this.enabled) {
591
+ this._captureException?.(err);
592
+ }
593
+ }
594
+ /**
595
+ * Manually capture user feedback.
596
+ *
597
+ * The default implementation uses Sentry.
598
+ */
599
+ captureUserFeedback(name, email, message) {
600
+ void this._captureUserFeedback?.(name, email, message);
601
+ }
602
+ };
603
+
604
+ export {
605
+ Observability,
606
+ getTelemetryIdentifier,
607
+ mapSpaces
608
+ };
609
+ //# sourceMappingURL=chunk-D7JZEGRD.mjs.map