@dxos/observability 0.3.11-main.e19f39d → 0.3.11-main.e28df4f

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 (55) hide show
  1. package/dist/lib/browser/chunk-ROSK6U3K.mjs +83 -0
  2. package/dist/lib/browser/chunk-ROSK6U3K.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-STWCJK52.mjs +748 -0
  4. package/dist/lib/browser/chunk-STWCJK52.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +28 -553
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/observability-XIDFB6PJ.mjs +10 -0
  9. package/dist/lib/browser/observability-XIDFB6PJ.mjs.map +7 -0
  10. package/dist/lib/browser/segment/index.mjs +8 -0
  11. package/dist/lib/browser/segment/index.mjs.map +7 -0
  12. package/dist/lib/node/chunk-ARUBPK2W.cjs +170 -0
  13. package/dist/lib/node/chunk-ARUBPK2W.cjs.map +7 -0
  14. package/dist/lib/node/chunk-DE7OVD7T.cjs +769 -0
  15. package/dist/lib/node/chunk-DE7OVD7T.cjs.map +7 -0
  16. package/dist/lib/node/index.cjs +26 -602
  17. package/dist/lib/node/index.cjs.map +4 -4
  18. package/dist/lib/node/meta.json +1 -1
  19. package/dist/lib/node/observability-YMIQHLME.cjs +32 -0
  20. package/dist/lib/node/observability-YMIQHLME.cjs.map +7 -0
  21. package/dist/lib/node/segment/index.cjs +30 -0
  22. package/dist/lib/node/segment/index.cjs.map +7 -0
  23. package/dist/types/src/helpers/app-observability.d.ts +19 -0
  24. package/dist/types/src/helpers/app-observability.d.ts.map +1 -0
  25. package/dist/types/src/helpers/app-observability.js +195 -0
  26. package/dist/types/src/helpers/app-observability.js.map +1 -0
  27. package/dist/types/src/helpers/index.d.ts +4 -0
  28. package/dist/types/src/helpers/index.d.ts.map +1 -0
  29. package/dist/types/src/helpers/index.js +23 -0
  30. package/dist/types/src/helpers/index.js.map +1 -0
  31. package/dist/types/src/{util.d.ts → helpers/map-spaces.d.ts} +2 -3
  32. package/dist/types/src/helpers/map-spaces.d.ts.map +1 -0
  33. package/dist/types/src/{util.js → helpers/map-spaces.js} +1 -2
  34. package/dist/types/src/helpers/map-spaces.js.map +1 -0
  35. package/dist/types/src/helpers/setup-telemetry-listeners.d.ts +4 -0
  36. package/dist/types/src/helpers/setup-telemetry-listeners.d.ts.map +1 -0
  37. package/dist/types/src/helpers/setup-telemetry-listeners.js +96 -0
  38. package/dist/types/src/helpers/setup-telemetry-listeners.js.map +1 -0
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/index.js +1 -0
  42. package/dist/types/src/index.js.map +1 -1
  43. package/dist/types/src/observability.d.ts +3 -4
  44. package/dist/types/src/observability.d.ts.map +1 -1
  45. package/dist/types/src/observability.js +26 -25
  46. package/dist/types/src/observability.js.map +1 -1
  47. package/package.json +15 -14
  48. package/src/helpers/app-observability.ts +205 -0
  49. package/src/helpers/index.ts +7 -0
  50. package/src/{util.ts → helpers/map-spaces.ts} +1 -2
  51. package/src/helpers/setup-telemetry-listeners.ts +115 -0
  52. package/src/index.ts +1 -0
  53. package/src/observability.ts +26 -24
  54. package/dist/types/src/util.d.ts.map +0 -1
  55. package/dist/types/src/util.js.map +0 -1
@@ -0,0 +1,115 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import type { Client } from '@dxos/client';
6
+
7
+ import { BASE_TELEMETRY_PROPERTIES, getTelemetryIdentifier } from './app-observability';
8
+ import type { Observability } from '../observability';
9
+
10
+ let lastFocusEvent = new Date();
11
+ let totalTime = 0;
12
+
13
+ export const setupTelemetryListeners = (namespace: string, client: Client, observability: Observability) => {
14
+ const clickCallback = (event: any) => {
15
+ if (BASE_TELEMETRY_PROPERTIES.group === 'dxos' && event.target && !event.target.id) {
16
+ // TODO(wittjosiah): Use @dxos/log so these can be filtered.
17
+ console.warn('Click event on element without id:', event.target);
18
+ }
19
+
20
+ setTimeout(() =>
21
+ observability.event({
22
+ identityId: getTelemetryIdentifier(client),
23
+ name: `${namespace}.window.click`,
24
+ properties: {
25
+ ...BASE_TELEMETRY_PROPERTIES,
26
+ href: window.location.href,
27
+ id: (event.target as HTMLElement)?.id,
28
+ path: (event.path as HTMLElement[])
29
+ ?.filter((el) => Boolean(el.tagName))
30
+ .map((el) => `${el.tagName.toLowerCase()}${el.id ? `#${el.id}` : ''}`)
31
+ .reverse()
32
+ .join('>'),
33
+ },
34
+ }),
35
+ );
36
+ };
37
+
38
+ const focusCallback = () => {
39
+ const now = new Date();
40
+ setTimeout(() =>
41
+ observability.event({
42
+ identityId: getTelemetryIdentifier(client),
43
+ name: `${namespace}.window.focus`,
44
+ properties: {
45
+ ...BASE_TELEMETRY_PROPERTIES,
46
+ href: window.location.href,
47
+ timeAway: now.getTime() - lastFocusEvent.getTime(),
48
+ },
49
+ }),
50
+ );
51
+ lastFocusEvent = now;
52
+ };
53
+
54
+ const blurCallback = () => {
55
+ const now = new Date();
56
+ const timeSpent = now.getTime() - lastFocusEvent.getTime();
57
+ setTimeout(() =>
58
+ observability.event({
59
+ identityId: getTelemetryIdentifier(client),
60
+ name: `${namespace}.window.blur`,
61
+ properties: {
62
+ ...BASE_TELEMETRY_PROPERTIES,
63
+ href: window.location.href,
64
+ timeSpent,
65
+ },
66
+ }),
67
+ );
68
+ lastFocusEvent = now;
69
+ totalTime = totalTime + timeSpent;
70
+ };
71
+
72
+ const unloadCallback = () => {
73
+ setTimeout(() =>
74
+ observability.event({
75
+ identityId: getTelemetryIdentifier(client),
76
+ name: `${namespace}.page.unload`,
77
+ properties: {
78
+ ...BASE_TELEMETRY_PROPERTIES,
79
+ href: window.location.href,
80
+ timeSpent: totalTime,
81
+ },
82
+ }),
83
+ );
84
+ };
85
+
86
+ const errorCallback = (event: ErrorEvent) => {
87
+ setTimeout(() =>
88
+ observability.event({
89
+ identityId: getTelemetryIdentifier(client),
90
+ name: `${namespace}.window.error`,
91
+ properties: {
92
+ ...BASE_TELEMETRY_PROPERTIES,
93
+ href: window.location.href,
94
+ message: event.message,
95
+ filename: event.filename,
96
+ stack: (event.error as Error).stack,
97
+ },
98
+ }),
99
+ );
100
+ };
101
+
102
+ window.addEventListener('click', clickCallback, true);
103
+ window.addEventListener('focus', focusCallback);
104
+ window.addEventListener('blur', blurCallback);
105
+ window.addEventListener('beforeunload', unloadCallback);
106
+ window.addEventListener('error', errorCallback);
107
+
108
+ return () => {
109
+ window.removeEventListener('click', clickCallback, true);
110
+ window.removeEventListener('focus', focusCallback);
111
+ window.removeEventListener('blur', blurCallback);
112
+ window.removeEventListener('beforeunload', unloadCallback);
113
+ window.removeEventListener('error', errorCallback);
114
+ };
115
+ };
package/src/index.ts CHANGED
@@ -2,4 +2,5 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ export * from './helpers';
5
6
  export * from './observability';
@@ -14,6 +14,7 @@ import { isNode } from '@dxos/util';
14
14
 
15
15
  import buildSecrets from './cli-observability-secrets.json';
16
16
  import { DatadogMetrics } from './datadog';
17
+ import { BASE_TELEMETRY_PROPERTIES, getTelemetryIdentifier, mapSpaces } from './helpers';
17
18
  import { SegmentTelemetry, type EventOptions, type PageOptions } from './segment';
18
19
  import {
19
20
  captureException as sentryCaptureException,
@@ -23,7 +24,6 @@ import {
23
24
  type InitOptions,
24
25
  setTag as sentrySetTag,
25
26
  } from './sentry';
26
- import { mapSpaces } from './util';
27
27
 
28
28
  const SPACE_METRICS_MIN_INTERVAL = 1000 * 60;
29
29
  // const DATADOG_IDLE_INTERVAL = 1000 * 60 * 5;
@@ -62,8 +62,8 @@ export type ObservabilityOptions = {
62
62
 
63
63
  errorLog?: {
64
64
  sentryInitOptions?: InitOptions;
65
+ logProcessor?: boolean;
65
66
  };
66
- logProcessor?: boolean;
67
67
  };
68
68
 
69
69
  /*
@@ -90,7 +90,7 @@ export class Observability {
90
90
  private _tags = new Map<string, string>();
91
91
 
92
92
  // TODO(nf): make platform a required extension?
93
- constructor({ namespace, config, secrets, group, mode, telemetry, errorLog, logProcessor }: ObservabilityOptions) {
93
+ constructor({ namespace, config, secrets, group, mode, telemetry, errorLog }: ObservabilityOptions) {
94
94
  this._namespace = namespace;
95
95
  this._config = config;
96
96
  this._mode = mode ?? 'disabled';
@@ -98,7 +98,7 @@ export class Observability {
98
98
  this._secrets = this._loadSecrets(config, secrets);
99
99
  this._telemetryBatchSize = telemetry?.batchSize ?? 30;
100
100
  this._errorReportingOptions = errorLog?.sentryInitOptions;
101
- this._errorLogProcessor = logProcessor ?? false;
101
+ this._errorLogProcessor = errorLog?.logProcessor ?? false;
102
102
 
103
103
  if (this._group) {
104
104
  this.setTag('group', this._group);
@@ -168,7 +168,7 @@ export class Observability {
168
168
  this._tags.set(key, value);
169
169
  }
170
170
 
171
- // TODO(nf): Combine with setDeviceTags.
171
+ // TODO(wittjosiah): Improve privacy of telemetry identifiers. See `getTelemetryIdentifier`.
172
172
  async setIdentityTags(client: Client) {
173
173
  client.services.services.IdentityService!.queryIdentity().subscribe((idqr) => {
174
174
  if (!idqr?.identity?.identityKey) {
@@ -176,16 +176,9 @@ export class Observability {
176
176
  return;
177
177
  }
178
178
 
179
- // TODO(nf): check mode
180
- // TODO(nf): cardinality
181
- this.setTag('identityKey', idqr?.identity?.identityKey.truncate());
182
- if (idqr?.identity?.profile?.displayName) {
183
- this.setTag('username', idqr?.identity?.profile?.displayName);
184
- }
179
+ this.setTag('identityKey', idqr.identity.identityKey.truncate());
185
180
  });
186
- }
187
181
 
188
- async setDeviceTags(client: Client) {
189
182
  client.services.services.DevicesService!.queryDevices().subscribe((dqr) => {
190
183
  if (!dqr || !dqr.devices || dqr.devices.length === 0) {
191
184
  log('empty response from device service', { device: dqr });
@@ -283,19 +276,30 @@ export class Observability {
283
276
  // scheduleTaskInterval(ctx, async () => updateSignalMetrics.emit(), DATADOG_IDLE_INTERVAL);
284
277
  }
285
278
 
286
- startSpacesMetrics(client: Client) {
287
- let spaces = client.spaces.get();
279
+ startSpacesMetrics(client: Client, namespace: string) {
280
+ const spaces = client.spaces.get();
288
281
  const subscriptions = new Map<string, { unsubscribe: () => void }>();
289
282
  this._ctx.onDispose(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));
290
283
 
291
284
  const updateSpaceMetrics = new Event<Space>().debounce(SPACE_METRICS_MIN_INTERVAL);
292
- updateSpaceMetrics.on(this._ctx, async (space) => {
285
+ updateSpaceMetrics.on(this._ctx, async () => {
293
286
  log('send space update');
294
- for (const sp of mapSpaces(spaces, { truncateKeys: true })) {
295
- this.gauge('dxos.client.space.members', sp.members, { key: sp.key });
296
- this.gauge('dxos.client.space.objects', sp.objects, { key: sp.key });
297
- this.gauge('dxos.client.space.epoch', sp.epoch, { key: sp.key });
298
- this.gauge('dxos.client.space.currentDataMutations', sp.currentDataMutations, { key: sp.key });
287
+ for (const data of mapSpaces(spaces, { truncateKeys: true })) {
288
+ // Metrics
289
+ this.gauge('dxos.client.space.members', data.members, { key: data.key });
290
+ this.gauge('dxos.client.space.objects', data.objects, { key: data.key });
291
+ this.gauge('dxos.client.space.epoch', data.epoch, { key: data.key });
292
+ this.gauge('dxos.client.space.currentDataMutations', data.currentDataMutations, { key: data.key });
293
+
294
+ // Telemetry
295
+ this.event({
296
+ identityId: getTelemetryIdentifier(client),
297
+ name: `${namespace}.space.update`,
298
+ properties: {
299
+ ...BASE_TELEMETRY_PROPERTIES,
300
+ ...data,
301
+ },
302
+ });
299
303
  }
300
304
  });
301
305
 
@@ -311,9 +315,7 @@ export class Observability {
311
315
  });
312
316
 
313
317
  client.spaces.subscribe({
314
- next: async () => {
315
- spaces = client.spaces.get();
316
- // spaces = await this.getSpaces(this._agent.client);
318
+ next: async (spaces) => {
317
319
  spaces
318
320
  .filter((space) => !subscriptions.has(space.key.toHex()))
319
321
  .forEach((space) => {
@@ -1 +0,0 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,SAAS,WAAY,KAAK,EAAE,YAAW,gBAAgB;;;;;;;;;;;;GAqCnE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,0BAA0B;AAC1B,EAAE;;;AASK,MAAM,SAAS,GAAG,CAAC,MAAe,EAAE,UAA4B,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;IAChH,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;;QAC1B,4BAA4B;QAC5B,oEAAoE;QACpE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,mCAAI,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAElE,kGAAkG;QAClG,uDAAuD;QACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC9C,MAAM,kBAAkB,GAAG,MAAA,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,YAAY,0CAAE,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,mCAAI,CAAC,CAAC;QACpG,MAAM,KAAK,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,YAAY,0CAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;QAC/D,yEAAyE;QACzE,MAAM,oBAAoB,GAAG,MAAA,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,oBAAoB,0CAAE,aAAa,EAAE,mCAAI,CAAC,CAAC;QAClF,MAAM,kBAAkB,GAAG,MAAA,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,mBAAmB,0CAAE,aAAa,EAAE,mCAAI,CAAC,CAAC;QAE/E,OAAO;YACL,kCAAkC;YAClC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE;YACzB,IAAI,EAAE,KAAK,CAAC,MAAM;YAClB,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC,IAAI;YAC3B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM;YACnC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,MAAM;YACxC,OAAO;YACP,KAAK;YACL,gBAAgB;YAChB,kBAAkB;YAClB,oBAAoB;YACpB,kBAAkB;YAElB,0BAA0B;YAC1B,QAAQ,EAAE,CACR,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,GAAG,kBAAkB,CAAC,GAAG,CAAC,kBAAkB,GAAG,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC9G,GAAG,CACJ,CAAC,OAAO,CAAC,CAAC,CAAC;SACb,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AArCW,QAAA,SAAS,aAqCpB"}