@dxos/observability 0.8.4-main.8342792842 → 0.8.4-main.8360d9e660

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 (39) hide show
  1. package/README.md +14 -11
  2. package/dist/lib/browser/index.mjs +17 -78
  3. package/dist/lib/browser/index.mjs.map +4 -4
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/{traces-browser-XYXBF5ZX.mjs → traces-browser-5DQUYGQ7.mjs} +9 -3
  6. package/dist/lib/browser/{traces-browser-XYXBF5ZX.mjs.map → traces-browser-5DQUYGQ7.mjs.map} +3 -3
  7. package/dist/lib/node-esm/index.mjs +16 -77
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/extensions/otel/traces-browser.d.ts.map +1 -1
  11. package/dist/types/src/extensions/otel/traces-browser.js +7 -1
  12. package/dist/types/src/extensions/otel/traces-browser.js.map +1 -1
  13. package/dist/types/src/extensions/posthog/extension.d.ts +3 -0
  14. package/dist/types/src/extensions/posthog/extension.d.ts.map +1 -1
  15. package/dist/types/src/extensions/posthog/extension.js +3 -4
  16. package/dist/types/src/extensions/posthog/extension.js.map +1 -1
  17. package/dist/types/src/index.d.ts +0 -1
  18. package/dist/types/src/index.d.ts.map +1 -1
  19. package/dist/types/src/index.js +0 -1
  20. package/dist/types/src/index.js.map +1 -1
  21. package/dist/types/src/providers/ip-data.d.ts.map +1 -1
  22. package/dist/types/src/providers/ip-data.js +4 -2
  23. package/dist/types/src/providers/ip-data.js.map +1 -1
  24. package/dist/types/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +16 -16
  26. package/src/extensions/otel/traces-browser.ts +7 -1
  27. package/src/extensions/posthog/extension.ts +5 -3
  28. package/src/index.ts +0 -1
  29. package/src/providers/ip-data.ts +5 -2
  30. package/dist/types/src/log-buffer.d.ts +0 -34
  31. package/dist/types/src/log-buffer.d.ts.map +0 -1
  32. package/dist/types/src/log-buffer.js +0 -70
  33. package/dist/types/src/log-buffer.js.map +0 -1
  34. package/dist/types/src/log-buffer.test.d.ts +0 -2
  35. package/dist/types/src/log-buffer.test.d.ts.map +0 -1
  36. package/dist/types/src/log-buffer.test.js +0 -107
  37. package/dist/types/src/log-buffer.test.js.map +0 -1
  38. package/src/log-buffer.test.ts +0 -134
  39. package/src/log-buffer.ts +0 -101
package/README.md CHANGED
@@ -2,22 +2,24 @@
2
2
 
3
3
  This package provides isomorphic observability capabilities for the DXOS platform.
4
4
 
5
- * Error log capture for monitoring and alerting.
6
- * Time-series data for monitoring, diagnostics, and alerting.
7
- * Telemetry logging for product usage statistics.
5
+ - Error log capture for monitoring and alerting.
6
+ - Time-series data for monitoring, diagnostics, and alerting.
7
+ - Telemetry logging for product usage statistics.
8
8
 
9
9
  The observability package provides the following facilities to support these capabilities:
10
- * Secrets loading for API keys for SaaS services
11
- * Common tag handling
12
- * Common group, opt-in handling
10
+
11
+ - Secrets loading for API keys for SaaS services
12
+ - Common tag handling
13
+ - Common group, opt-in handling
13
14
 
14
15
  This is currently implemented using the following providers:
15
16
 
16
- * Error log capture - Sentry and OpenTelemetry
17
- * Time-series data = OpenTelemetry
18
- * Telemetry logging - Segment
17
+ - Error log capture - Sentry and OpenTelemetry
18
+ - Time-series data = OpenTelemetry
19
+ - Telemetry logging - Segment
19
20
 
20
21
  # Usage and Configuration
22
+
21
23
  Entry points are provided in [helpers/](src/helpers/), which contain functionality to persist the configuration.
22
24
 
23
25
  `Mode` can be `disabled`, `basic`, and `full`. `basic` and `full` currently have the same behavior, but will control the exposure of public identity keys in the future. See https://github.com/orgs/dxos/discussions/5438
@@ -27,5 +29,6 @@ Entry points are provided in [helpers/](src/helpers/), which contain functionali
27
29
  `Namespace` is used by the provider backends to distinguish different applications and services.
28
30
 
29
31
  # TODO
30
- * Stabilize API and further decouple it from the underlying providers
31
- * Factor out metrics capabilities into ObservabilityExtension classes
32
+
33
+ - Stabilize API and further decouple it from the underlying providers
34
+ - Factor out metrics capabilities into ObservabilityExtension classes
@@ -2,69 +2,6 @@ import {
2
2
  __export
3
3
  } from "./chunk-J5LGTIGS.mjs";
4
4
 
5
- // src/log-buffer.ts
6
- import { LogLevel, shortLevelName } from "@dxos/log";
7
- import { CircularBuffer } from "@dxos/util";
8
- var DEFAULT_BUFFER_SIZE = 2e3;
9
- var MAX_CONTEXT_LENGTH = 500;
10
- var LogBuffer = class {
11
- _buffer;
12
- constructor(size = DEFAULT_BUFFER_SIZE) {
13
- this._buffer = new CircularBuffer(size);
14
- }
15
- /** Log processor that can be registered with `log.runtimeConfig.processors`. */
16
- logProcessor = (_config, entry) => {
17
- if (entry.level <= LogLevel.TRACE) {
18
- return;
19
- }
20
- const record = {
21
- t: (/* @__PURE__ */ new Date()).toISOString(),
22
- l: shortLevelName[entry.level] ?? "?",
23
- m: entry.message ?? ""
24
- };
25
- if (entry.meta) {
26
- record.f = getRelativeFilename(entry.meta.F);
27
- record.n = entry.meta.L;
28
- }
29
- if (entry.error) {
30
- record.e = entry.error.stack ?? entry.error.message;
31
- }
32
- if (entry.context != null) {
33
- try {
34
- const ctx = typeof entry.context === "function" ? entry.context() : entry.context;
35
- if (ctx != null && !(ctx instanceof Error)) {
36
- let json = JSON.stringify(ctx);
37
- if (json.length > MAX_CONTEXT_LENGTH) {
38
- json = json.slice(0, MAX_CONTEXT_LENGTH);
39
- }
40
- record.c = json;
41
- }
42
- } catch {
43
- }
44
- }
45
- this._buffer.push(record);
46
- };
47
- /** Number of entries currently in the buffer. */
48
- get size() {
49
- return this._buffer.elementCount;
50
- }
51
- /** Serialize buffer contents as NDJSON (newline-delimited JSON). */
52
- serialize() {
53
- const lines = [];
54
- for (const record of this._buffer) {
55
- lines.push(JSON.stringify(record));
56
- }
57
- return lines.join("\n");
58
- }
59
- };
60
- var getRelativeFilename = (filename) => {
61
- const match = filename.match(/.+\/(packages\/.+\/.+)/);
62
- if (match) {
63
- return match[1];
64
- }
65
- return filename;
66
- };
67
-
68
5
  // src/observability.ts
69
6
  var observability_exports = {};
70
7
  __export(observability_exports, {
@@ -407,7 +344,7 @@ import * as Effect3 from "effect/Effect";
407
344
  import * as Match from "effect/Match";
408
345
  import * as Option from "effect/Option";
409
346
  import * as Ref from "effect/Ref";
410
- import { LogLevel as LogLevel2, log as log3 } from "@dxos/log";
347
+ import { LogLevel, log as log3 } from "@dxos/log";
411
348
  import { isNode, isNonNullable } from "@dxos/util";
412
349
 
413
350
  // src/cli-observability-secrets.json
@@ -446,13 +383,13 @@ var extensions = Effect3.fn(function* ({
446
383
  // - logs should be cached locally in a circular buffer
447
384
  // - logs should be flushed to the server if user opts to include them in a bug report
448
385
  logs: logsEnabled = false,
449
- logLevel = LogLevel2.INFO,
386
+ logLevel = LogLevel.INFO,
450
387
  metrics: metricsEnabled = false,
451
388
  traces: tracesEnabled = false
452
389
  }) {
453
390
  const { OtelLogs } = yield* Effect3.promise(() => import("./logs-ATTRIUTL.mjs"));
454
391
  const { OtelMetrics } = yield* Effect3.promise(() => import("./metrics-PKTV6IGF.mjs"));
455
- const { OtelTraces } = yield* Effect3.promise(() => import("./traces-browser-XYXBF5ZX.mjs"));
392
+ const { OtelTraces } = yield* Effect3.promise(() => import("./traces-browser-5DQUYGQ7.mjs"));
456
393
  const cachedDisabled = yield* Effect3.promise(() => isObservabilityDisabled(serviceName));
457
394
  const enabledRef = yield* Ref.make(!cachedDisabled);
458
395
  const tags = /* @__PURE__ */ new Map();
@@ -561,7 +498,7 @@ __export(posthog_exports, {
561
498
 
562
499
  // src/extensions/posthog/extension.ts
563
500
  import * as Effect4 from "effect/Effect";
564
- import { log as log4 } from "@dxos/log";
501
+ import { LogBuffer, log as log4 } from "@dxos/log";
565
502
  var __dxlog_file4 = "/__w/dxos/dxos/packages/sdk/observability/src/extensions/posthog/extension.ts";
566
503
  var uploadLogs = async (body) => {
567
504
  try {
@@ -577,7 +514,7 @@ var uploadLogs = async (body) => {
577
514
  status: response.status
578
515
  }, {
579
516
  F: __dxlog_file4,
580
- L: 33,
517
+ L: 34,
581
518
  S: void 0,
582
519
  C: (f, a) => f(...a)
583
520
  });
@@ -590,18 +527,18 @@ var uploadLogs = async (body) => {
590
527
  error: err
591
528
  }, {
592
529
  F: __dxlog_file4,
593
- L: 39,
530
+ L: 40,
594
531
  S: void 0,
595
532
  C: (f, a) => f(...a)
596
533
  });
597
534
  return void 0;
598
535
  }
599
536
  };
600
- var extensions2 = Effect4.fn(function* ({ config, release, environment, posthog: posthogConfig }) {
537
+ var extensions2 = Effect4.fn(function* ({ config, release, environment, posthog: posthogConfig, logBuffer: externalLogBuffer }) {
601
538
  if (typeof window === "undefined") {
602
539
  log4("PostHog is being stubbed because it is running in a worker.", void 0, {
603
540
  F: __dxlog_file4,
604
- L: 52,
541
+ L: 54,
605
542
  S: this,
606
543
  C: (f, a) => f(...a)
607
544
  });
@@ -613,7 +550,7 @@ var extensions2 = Effect4.fn(function* ({ config, release, environment, posthog:
613
550
  if (!apiKey || !api_host) {
614
551
  log4.info("Missing POSTHOG_API_KEY or POSTHOG_API_HOST", void 0, {
615
552
  F: __dxlog_file4,
616
- L: 60,
553
+ L: 62,
617
554
  S: this,
618
555
  C: (f, a) => f(...a)
619
556
  });
@@ -621,7 +558,7 @@ var extensions2 = Effect4.fn(function* ({ config, release, environment, posthog:
621
558
  }
622
559
  const { default: posthog } = yield* Effect4.promise(() => import("posthog-js"));
623
560
  const { logProcessor } = yield* Effect4.promise(() => import("./log-processor-FDLTDQEM.mjs"));
624
- const logBuffer = new LogBuffer();
561
+ const logBuffer = externalLogBuffer ?? new LogBuffer();
625
562
  let feedbackSurveyAvailable = null;
626
563
  const checkFeedbackSurveyAvailable = () => feedbackSurveyId ? Effect4.promise(() => {
627
564
  if (feedbackSurveyAvailable !== null) {
@@ -707,7 +644,7 @@ var extensions2 = Effect4.fn(function* ({ config, release, environment, posthog:
707
644
  feedbackSurveyId
708
645
  }, {
709
646
  F: __dxlog_file4,
710
- L: 149,
647
+ L: 151,
711
648
  S: this,
712
649
  C: (f, a) => f(...a)
713
650
  });
@@ -1006,13 +943,14 @@ var IPData = Schema.Struct({
1006
943
  });
1007
944
  var getIPData = Effect6.fn(function* (config) {
1008
945
  const httpClient = yield* HttpClient.HttpClient;
946
+ const httpClientNoTrace = httpClient.pipe(HttpClient.withTracerDisabledWhen(() => true));
1009
947
  const cachedData = yield* Effect6.promise(() => localForage2.getItem("dxos:observability:ipdata"));
1010
948
  if (cachedData && cachedData.timestamp > Date.now() - IP_DATA_CACHE_TIMEOUT) {
1011
949
  return cachedData.data;
1012
950
  }
1013
951
  const IPDATA_API_KEY = config.get("runtime.app.env.DX_IPDATA_API_KEY");
1014
952
  if (IPDATA_API_KEY) {
1015
- const data = yield* HttpClientRequest.get(`https://api.ipdata.co?api-key=${IPDATA_API_KEY}`).pipe(httpClient.execute, Effect6.flatMap((res) => res.json), Effect6.flatMap(Schema.decodeUnknown(IPData)));
953
+ const data = yield* HttpClientRequest.get(`https://api.ipdata.co?api-key=${IPDATA_API_KEY}`).pipe(httpClientNoTrace.execute, Effect6.flatMap((res) => res.json), Effect6.flatMap(Schema.decodeUnknown(IPData)));
1016
954
  yield* Effect6.promise(() => localForage2.setItem("dxos:observability:ipdata", {
1017
955
  data,
1018
956
  timestamp: Date.now()
@@ -1033,9 +971,11 @@ var provider = (config) => (observability) => Effect6.gen(function* () {
1033
971
  longitude: ipData.longitude
1034
972
  });
1035
973
  }).pipe(Effect6.provide(FetchHttpClient.layer), Effect6.catchAll((err) => Effect6.sync(() => {
1036
- log6.catch(err, void 0, {
974
+ log6.verbose("ipdata fetch failed", {
975
+ err
976
+ }, {
1037
977
  F: __dxlog_file6,
1038
- L: 85,
978
+ L: 88,
1039
979
  S: void 0,
1040
980
  C: (f, a) => f(...a)
1041
981
  });
@@ -1062,7 +1002,6 @@ var provider2 = Effect7.fn(function* (observability) {
1062
1002
  }
1063
1003
  });
1064
1004
  export {
1065
- LogBuffer,
1066
1005
  observability_exports as Observability,
1067
1006
  observability_extension_exports as ObservabilityExtension,
1068
1007
  providers_exports as ObservabilityProvider
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/log-buffer.ts", "../../../src/observability.ts", "../../../src/storage/browser.ts", "../../../src/observability-extension.ts", "../../../src/extensions/otel/index.ts", "../../../src/extensions/otel/extension.ts", "../../../src/cli-observability-secrets.json", "../../../src/extensions/stub.ts", "../../../src/extensions/posthog/index.ts", "../../../src/extensions/posthog/extension.ts", "../../../src/providers/index.ts", "../../../src/providers/client-observability.ts", "../../../src/providers/ip-data.ts", "../../../src/providers/storage.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type LogConfig, type LogEntry, LogLevel, type LogProcessor, shortLevelName } from '@dxos/log';\nimport { CircularBuffer } from '@dxos/util';\n\nconst DEFAULT_BUFFER_SIZE = 2_000;\nconst MAX_CONTEXT_LENGTH = 500;\n\n/**\n * Compact log record with short property names for small serialized size.\n */\nexport type LogRecord = {\n /** ISO timestamp. */\n t: string;\n /** Level letter (D, V, I, W, E). */\n l: string;\n /** Message. */\n m: string;\n /** File path. */\n f?: string;\n /** Line number. */\n n?: number;\n /** Error stack. */\n e?: string;\n /** Context JSON. */\n c?: string;\n};\n\n/**\n * Captures recent log entries in a circular buffer for debug log dump on feedback submission.\n */\nexport class LogBuffer {\n private readonly _buffer: CircularBuffer<LogRecord>;\n\n constructor(size = DEFAULT_BUFFER_SIZE) {\n this._buffer = new CircularBuffer<LogRecord>(size);\n }\n\n /** Log processor that can be registered with `log.runtimeConfig.processors`. */\n readonly logProcessor: LogProcessor = (_config: LogConfig, entry: LogEntry) => {\n if (entry.level <= LogLevel.TRACE) {\n return;\n }\n\n const record: LogRecord = {\n t: new Date().toISOString(),\n l: shortLevelName[entry.level] ?? '?',\n m: entry.message ?? '',\n };\n\n if (entry.meta) {\n record.f = getRelativeFilename(entry.meta.F);\n record.n = entry.meta.L;\n }\n\n if (entry.error) {\n record.e = entry.error.stack ?? entry.error.message;\n }\n\n if (entry.context != null) {\n try {\n const ctx = typeof entry.context === 'function' ? entry.context() : entry.context;\n if (ctx != null && !(ctx instanceof Error)) {\n let json = JSON.stringify(ctx);\n if (json.length > MAX_CONTEXT_LENGTH) {\n json = json.slice(0, MAX_CONTEXT_LENGTH);\n }\n record.c = json;\n }\n } catch {\n // Skip context that throws or is non-serializable.\n }\n }\n\n this._buffer.push(record);\n };\n\n /** Number of entries currently in the buffer. */\n get size(): number {\n return this._buffer.elementCount;\n }\n\n /** Serialize buffer contents as NDJSON (newline-delimited JSON). */\n serialize(): string {\n const lines: string[] = [];\n for (const record of this._buffer) {\n lines.push(JSON.stringify(record));\n }\n return lines.join('\\n');\n }\n}\n\nconst getRelativeFilename = (filename: string): string => {\n const match = filename.match(/.+\\/(packages\\/.+\\/.+)/);\n if (match) {\n return match[1];\n }\n return filename;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Array from 'effect/Array';\nimport * as Effect from 'effect/Effect';\nimport * as Function from 'effect/Function';\n\nimport { type CleanupFn, SubscriptionList } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport {\n type Attributes,\n type Errors,\n type Events,\n type Extension,\n type ExtensionApi,\n type Feedback,\n type Kind,\n type Metrics,\n} from './observability-extension';\n\nexport * from './storage';\n\n// TODO(wittjosiah): Figure out how to handle when telemetry is disabled.\n// In theory the setting should be both persisted and synchronized.\n// Initialize probably should still run for the cases where data is emitted manually (e.g., feedback).\n\n/**\n * Provider of observability data.\n */\nexport type DataProvider = (observability: Observability) => Effect.Effect<CleanupFn | void, Error>;\n\n/**\n * Extensible observability provider.\n */\n// TODO(wittjosiah): Add pipe method.\nexport interface Observability {\n initialize(): Effect.Effect<void>;\n close(): Effect.Effect<void>;\n enable(): Effect.Effect<void>;\n disable(): Effect.Effect<void>;\n flush(): Effect.Effect<void>;\n addDataProvider(dataProvider: DataProvider): Effect.Effect<void, Error>;\n identify(distinctId: string, attributes?: Attributes, setOnceAttributes?: Attributes): void;\n alias(distinctId: string, previousId?: string): void;\n setTags(tags: Attributes, kind?: Kind): void;\n enabled: boolean;\n errors: Errors;\n events: Events;\n feedback: Feedback;\n /** True if at least one extension of the given kind reports as available. */\n isAvailable(kind: Kind): Effect.Effect<boolean>;\n metrics: Metrics;\n}\n\nclass ObservabilityImpl implements Observability {\n private _initialized = false;\n private readonly _extensions: Extension[] = [];\n private readonly _dataProviders: DataProvider[] = [];\n private readonly _subscriptions = new SubscriptionList();\n\n initialize(): Effect.Effect<void> {\n if (this._initialized) {\n return Effect.succeed(undefined);\n }\n\n const initializedExtensions: Extension[] = [];\n\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.initialize) {\n yield* extension.initialize();\n }\n initializedExtensions.push(extension);\n }\n\n const cleanups = yield* Effect.all(this._dataProviders.map((provider) => provider(this)));\n this._subscriptions.add(...cleanups.filter((cleanup) => cleanup !== undefined));\n this._initialized = true;\n }).pipe(\n Effect.catchAll((error) =>\n Effect.gen(this, function* () {\n log.catch(error);\n // Roll back already-initialized extensions.\n for (const extension of initializedExtensions) {\n if (extension.close) {\n yield* extension.close().pipe(Effect.catchAll(() => Effect.succeed(undefined)));\n }\n }\n this._subscriptions.clear();\n }),\n ),\n );\n }\n\n close(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n this._subscriptions.clear();\n this._dataProviders.length = 0;\n for (const extension of this._extensions) {\n if (extension.close) {\n yield* extension.close();\n }\n }\n this._initialized = false;\n });\n }\n\n enable(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.enable) {\n yield* extension.enable();\n }\n }\n });\n }\n\n disable(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.disable) {\n yield* extension.disable();\n }\n }\n });\n }\n\n flush(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.flush) {\n yield* extension.flush();\n }\n }\n });\n }\n\n _addExtension(extension: Extension): void {\n invariant(!this._initialized, 'Observability is already initialized');\n this._extensions.push(extension);\n }\n\n _addDataProvider(dataProvider: DataProvider): void {\n invariant(!this._initialized, 'Observability is already initialized');\n this._dataProviders.push(dataProvider);\n }\n\n /**\n * Adds a data provider and initializes it.\n */\n addDataProvider(dataProvider: DataProvider): Effect.Effect<void, Error> {\n return Effect.gen(this, function* () {\n this._dataProviders.push(dataProvider);\n const cleanup = yield* dataProvider(this);\n if (cleanup) {\n this._subscriptions.add(cleanup);\n }\n });\n }\n\n identify(distinctId: string, attributes?: Attributes, setOnceAttributes?: Attributes): void {\n for (const extension of this._extensions) {\n extension.identify?.(distinctId, attributes, setOnceAttributes);\n }\n }\n\n alias(distinctId: string, previousId?: string): void {\n for (const extension of this._extensions) {\n extension.alias?.(distinctId, previousId);\n }\n }\n\n setTags(tags: Attributes, kind?: Kind): void {\n for (const extension of this._extensions) {\n if (kind && !extension.apis.some((api) => api.kind === kind)) {\n continue;\n }\n\n const processedTags = Object.fromEntries(\n Object.entries(tags)\n .filter((entry): entry is [string, string | number | boolean] => entry[1] !== undefined)\n .map(([key, value]) => [key, value.toString()]),\n );\n extension.setTags?.(processedTags);\n }\n }\n\n get enabled(): boolean {\n return this._extensions.every((extension) => extension.enabled);\n }\n\n get errors(): Errors {\n return {\n captureException: (error, attributes) => {\n for (const extension of this._getExtensions('errors')) {\n extension.captureException(error, attributes);\n }\n },\n };\n }\n\n get events(): Events {\n return {\n captureEvent: (event, attributes) => {\n for (const extension of this._getExtensions('events')) {\n extension.captureEvent(event, attributes);\n }\n },\n };\n }\n\n get feedback(): Feedback {\n return {\n captureUserFeedback: (form) => {\n for (const extension of this._getExtensions('feedback')) {\n extension.captureUserFeedback(form);\n }\n },\n };\n }\n\n isAvailable(kind: Kind): Effect.Effect<boolean> {\n const apis = this._getExtensions(kind);\n if (apis.length === 0) {\n return Effect.succeed(false);\n }\n return Effect.gen(this, function* () {\n for (const api of apis) {\n const available = yield* api.isAvailable();\n if (available) {\n return true;\n }\n }\n return false;\n });\n }\n\n get metrics(): Metrics {\n return {\n gauge: (name, value, attributes) => {\n for (const extension of this._getExtensions('metrics')) {\n extension.gauge(name, value, attributes);\n }\n },\n increment: (name, value, attributes) => {\n for (const extension of this._getExtensions('metrics')) {\n extension.increment(name, value, attributes);\n }\n },\n distribution: (name, value, attributes) => {\n for (const extension of this._getExtensions('metrics')) {\n extension.distribution(name, value, attributes);\n }\n },\n };\n }\n\n private _getExtensions<T extends Kind>(kind: T): Extract<ExtensionApi, { kind: T }>[] {\n return Function.pipe(\n this._extensions,\n Array.flatMap((extension) => extension.apis),\n Array.filter((api): api is Extract<ExtensionApi, { kind: T }> => api.kind === kind),\n );\n }\n}\n\nexport const make = (): Effect.Effect<Observability> => Effect.succeed(new ObservabilityImpl());\n\nexport const addExtension = (_extension: Effect.Effect<Extension>) =>\n Effect.fn(function* (_observability: Effect.Effect<Observability>) {\n const observability = yield* _observability;\n const extension = yield* _extension;\n invariant('_addExtension' in observability && typeof observability._addExtension === 'function');\n observability._addExtension(extension);\n return observability;\n });\n\nexport const addDataProvider = (dataProvider: DataProvider) =>\n Effect.fn(function* (_observability: Effect.Effect<Observability>) {\n const observability = yield* _observability;\n invariant('_addDataProvider' in observability && typeof observability._addDataProvider === 'function');\n observability._addDataProvider(dataProvider);\n return observability;\n });\n\nexport const initialize = Effect.fn(function* (_observability: Effect.Effect<Observability>) {\n const observability = yield* _observability;\n yield* observability.initialize();\n return observability;\n});\n", "//\n// Copyright 2022 DXOS.org\n//\n\n// NOTE: localStorage is not available in web workers.\nimport * as localForage from 'localforage';\n\nimport { log } from '@dxos/log';\n\nconst OBSERVABILITY_DISABLED_KEY = 'observability-disabled';\nconst OBSERVABILITY_GROUP_KEY = 'observability-group';\n\n/** No-op in browser contexts. */\nexport const showObservabilityBanner = () => {\n log.warn('showObservabilityBanner is not supported in browser contexts.');\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const isObservabilityDisabled = async (namespace: string): Promise<boolean> => {\n try {\n return (await localForage.getItem(`${namespace}:${OBSERVABILITY_DISABLED_KEY}`)) === 'true';\n } catch (err) {\n log.catch('Failed to check if observability is disabled, assuming it is', err);\n return true;\n }\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const storeObservabilityDisabled = async (namespace: string, value: boolean) => {\n try {\n await localForage.setItem(`${namespace}:${OBSERVABILITY_DISABLED_KEY}`, String(value));\n } catch (err) {\n log.catch('Failed to store observability disabled', err);\n }\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const getObservabilityGroup = async (namespace: string): Promise<string | undefined> => {\n try {\n return (await localForage.getItem(`${namespace}:${OBSERVABILITY_GROUP_KEY}`)) ?? undefined;\n } catch (err) {\n log.catch('Failed to get observability group', err);\n }\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const storeObservabilityGroup = async (namespace: string, value: string) => {\n try {\n await localForage.setItem(`${namespace}:${OBSERVABILITY_GROUP_KEY}`, value);\n } catch (err) {\n log.catch('Failed to store observability group', err);\n }\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport type * as Effect from 'effect/Effect';\n\nexport * from './extensions';\n\n/**\n * Kind of observability extension.\n *\n * - errors: Error tracking (e.g., PostHog)\n * - events: Product usage event tracking (e.g., PostHog)\n * - feedback: User feedback submission (e.g., PostHog)\n * - logs: Structured logging (e.g., OTEL)\n * - metrics: Metric data (e.g., OTEL)\n * - traces: Distributed tracing (e.g., OTEL)\n */\nexport type Kind = 'errors' | 'events' | 'feedback' | 'logs' | 'metrics' | 'traces';\n\n/**\n * Base for every extension API variant. All kinds implement availability the same way.\n */\nexport type ExtensionApiBase<K extends Kind = Kind> = {\n kind: K;\n isAvailable(): Effect.Effect<boolean>;\n};\n\n/**\n * Metrics extension API (kind-specific methods only).\n */\nexport type Metrics = {\n gauge(name: string, value: number, tags?: Attributes): void;\n increment(name: string, value?: number, tags?: Attributes): void;\n distribution(name: string, value: number, tags?: Attributes): void;\n};\n\n/**\n * Errors extension API (kind-specific methods only).\n */\nexport type Errors = {\n captureException(error: Error, attributes?: Attributes): void;\n};\n\n/**\n * Events extension API (kind-specific methods only).\n */\nexport type Events = {\n captureEvent(event: string, attributes?: Attributes): void;\n};\n\n/**\n * Feedback extension API (kind-specific methods only).\n */\nexport type Feedback = {\n captureUserFeedback(form: FeedbackForm): void;\n};\n\nexport type ExtensionApi =\n | (ExtensionApiBase<'errors'> & Errors)\n | (ExtensionApiBase<'events'> & Events)\n | (ExtensionApiBase<'feedback'> & Feedback)\n // TODO(wittjosiah): Direct logs api?\n | ExtensionApiBase<'logs'>\n | (ExtensionApiBase<'metrics'> & Metrics)\n // TODO(wittjosiah): Direct traces api?\n | ExtensionApiBase<'traces'>;\n\n/**\n * Feedback form to be captured by the feedback extension.\n */\n// TODO(wittjosiah): Support more form fields (e.g., PostHog custom surveys).\nexport type FeedbackForm = { message: string; includeLogs?: boolean };\n\n/**\n * Attributes to be attached to observability events.\n */\nexport type Attributes = Record<string, string | number | boolean | undefined>;\n\n/**\n * Implementation of an observability extension API.\n */\nexport type Extension = {\n initialize?(): Effect.Effect<void, Error>;\n close?(): Effect.Effect<void>;\n enable?(): Effect.Effect<void>;\n disable?(): Effect.Effect<void>;\n flush?(): Effect.Effect<void>;\n identify?(distinctId: string, attributes?: Attributes, setOnceAttributes?: Attributes): void;\n alias?(distinctId: string, previousId?: string): void;\n setTags?(tags: Record<string, string>): void;\n enabled: boolean;\n apis: ExtensionApi[];\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nexport * from './extension';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';\nimport { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';\nimport * as Effect from 'effect/Effect';\nimport * as Match from 'effect/Match';\nimport * as Option from 'effect/Option';\nimport * as Ref from 'effect/Ref';\n\nimport { type Config } from '@dxos/config';\nimport { LogLevel, log } from '@dxos/log';\nimport { isNode, isNonNullable } from '@dxos/util';\n\nimport buildSecrets from '../../cli-observability-secrets.json';\nimport { type Extension, type ExtensionApi } from '../../observability-extension';\nimport { isObservabilityDisabled, storeObservabilityDisabled } from '../../storage';\nimport { stubExtension } from '../stub';\n\nexport type ExtensionsOptions = {\n /** For the OTEL, the name of the entity for which signals (metrics or trace) are collected. */\n serviceName: string;\n /** For the OTEL, the version of the entity for which signals (metrics or trace) are collected. */\n serviceVersion: string;\n /** For the OTEL, the environment of the entity for which signals (metrics or trace) are collected. */\n environment: string;\n config: Config;\n endpoint?: string;\n headers?: Record<string, string>;\n logs?: boolean;\n /** Minimum log level to export. Defaults to INFO (i.e. info, warn, error). */\n logLevel?: LogLevel;\n metrics?: boolean;\n traces?: boolean;\n};\n\n/** Create an OTEL-backed observability extension for logs, metrics, and/or traces. */\nexport const extensions: (options: ExtensionsOptions) => Effect.Effect<Extension> = Effect.fn(function* ({\n serviceName,\n serviceVersion,\n environment,\n config,\n endpoint: _endpoint,\n headers: _headers,\n // TODO(wittjosiah): Logging integration.\n // - logger should run even if observability is disabled\n // - logs should be cached locally in a circular buffer\n // - logs should be flushed to the server if user opts to include them in a bug report\n logs: logsEnabled = false,\n logLevel = LogLevel.INFO,\n metrics: metricsEnabled = false,\n traces: tracesEnabled = false,\n}) {\n const { OtelLogs } = yield* Effect.promise(() => import('./logs'));\n const { OtelMetrics } = yield* Effect.promise(() => import('./metrics'));\n const { OtelTraces } = yield* Effect.promise(() => import('./traces'));\n\n const cachedDisabled = yield* Effect.promise(() => isObservabilityDisabled(serviceName));\n const enabledRef = yield* Ref.make(!cachedDisabled);\n const tags = new Map<string, string>();\n\n const endpoint = isNode()\n ? (process.env.DX_OTEL_ENDPOINT ?? _endpoint ?? buildSecrets.OTEL_ENDPOINT)\n : config.values.runtime?.app?.env?.DX_OTEL_ENDPOINT;\n const headers =\n _headers ??\n Match.value(isNode()).pipe(\n Match.when(true, () => Option.fromNullable(process.env.DX_OTEL_HEADERS ?? buildSecrets.OTEL_HEADERS)),\n Match.when(false, () => Option.fromNullable(config.values.runtime?.app?.env?.DX_OTEL_HEADERS)),\n Match.exhaustive,\n Option.map((raw) => parseHeaders(raw)),\n Option.getOrElse(() => undefined),\n );\n\n if (!endpoint || !headers) {\n log.info('Missing OTEL_ENDPOINT or OTEL_HEADERS');\n return stubExtension;\n }\n\n const resource = defaultResource().merge(\n resourceFromAttributes({\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_SERVICE_VERSION]: serviceVersion,\n 'deployment.environment': environment,\n }),\n );\n\n const logs = logsEnabled\n ? new OtelLogs({\n endpoint,\n headers,\n resource,\n getTags: () => Object.fromEntries(tags),\n logLevel,\n })\n : undefined;\n\n const metrics = metricsEnabled\n ? new OtelMetrics({\n endpoint,\n headers,\n resource,\n getTags: () => Object.fromEntries(tags),\n })\n : undefined;\n\n const traces = tracesEnabled\n ? new OtelTraces({\n endpoint,\n headers,\n resource,\n getTags: () => Object.fromEntries(tags),\n })\n : undefined;\n\n return {\n initialize: () =>\n Effect.sync(() => {\n if (logs) {\n log.runtimeConfig.processors.push(logs.logProcessor);\n }\n if (traces) {\n traces.start();\n }\n }),\n enable: Effect.fn(function* () {\n yield* Effect.promise(() => storeObservabilityDisabled(serviceName, false));\n yield* Ref.update(enabledRef, () => true);\n }),\n disable: Effect.fn(function* () {\n yield* Effect.promise(() => storeObservabilityDisabled(serviceName, true));\n yield* Ref.update(enabledRef, () => false);\n }),\n close: () =>\n Effect.promise(async () => {\n await logs?.close();\n await metrics?.close();\n }),\n flush: () =>\n Effect.promise(async () => {\n await logs?.flush();\n await metrics?.flush();\n }),\n setTags: (incomingTags) => {\n for (const [key, value] of Object.entries(incomingTags)) {\n tags.set(key, value);\n }\n },\n get enabled() {\n return Ref.get(enabledRef).pipe(Effect.runSync);\n },\n apis: [\n { kind: 'logs', isAvailable: () => Effect.succeed(!!logs) } satisfies ExtensionApi,\n metrics\n ? ({\n kind: 'metrics',\n isAvailable: () => Effect.succeed(true),\n gauge: (name, value, tags) => metrics.gauge(name, value, tags),\n increment: (name, value, tags) => metrics.increment(name, value, tags),\n distribution: (name, value, tags) => metrics.distribution(name, value, tags),\n } satisfies ExtensionApi)\n : undefined,\n traces ? ({ kind: 'traces', isAvailable: () => Effect.succeed(true) } satisfies ExtensionApi) : undefined,\n ].filter(isNonNullable),\n };\n});\n\nconst parseHeaders = (unparsedHeaders: string): Record<string, string> => {\n return unparsedHeaders.split(';').reduce((acc: Record<string, string>, header) => {\n const [key, ...rest] = header.split(':');\n if (key && rest.length > 0) {\n acc[key.trim().toLowerCase()] = rest.join(':').trim();\n }\n\n return acc;\n }, {});\n};\n", "{\n \"POSTHOG_API_KEY\": null,\n \"IPDATA_API_KEY\": \"73dfdecdf979c18f07d50cf841bbdd9e589f237256326ac8cca23786\",\n \"OTEL_ENDPOINT\": \"https://ingest.eu.signoz.cloud:443\",\n \"OTEL_HEADERS\": \"signoz-ingestion-key: 5300e0c9-a5e8-4a10-9c61-f473e539c0b7\"\n}", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { type Extension } from '../observability-extension';\n\nexport const stubExtension: Extension = {\n initialize: () => Effect.succeed(undefined),\n enable: () => Effect.succeed(undefined),\n disable: () => Effect.succeed(undefined),\n flush: () => Effect.succeed(undefined),\n setTags: () => undefined,\n get enabled() {\n return true;\n },\n apis: [],\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport * from './extension';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport { type PostHogConfig } from 'posthog-js';\n\nimport { type Config } from '@dxos/config';\nimport { log } from '@dxos/log';\n\nimport { LogBuffer } from '../../log-buffer';\nimport { type Extension } from '../../observability-extension';\nimport { stubExtension } from '../stub';\n\nexport type ExtensionsOptions = {\n config: Config;\n /** Release identifier, e.g. `composer@0.8.3`. */\n release?: string;\n /** Deployment environment, e.g. `production` or `staging`. */\n environment?: string;\n posthog?: Partial<PostHogConfig>;\n};\n\n/** Upload serialized logs to the feedback-logs endpoint. Returns the R2 key on success. */\nconst uploadLogs = async (body: string): Promise<string | undefined> => {\n try {\n const response = await fetch('/api/feedback-logs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-ndjson' },\n body,\n });\n if (!response.ok) {\n log.warn('feedback log upload failed', { status: response.status });\n return undefined;\n }\n const { key } = await response.json();\n return key;\n } catch (err) {\n log.warn('feedback log upload error', { error: err });\n return undefined;\n }\n};\n\n/** Create a PostHog-backed observability extension for events, errors, and feedback. */\nexport const extensions: (options: ExtensionsOptions) => Effect.Effect<Extension> = Effect.fn(function* ({\n config,\n release,\n environment,\n posthog: posthogConfig,\n}) {\n if (typeof window === 'undefined') {\n log('PostHog is being stubbed because it is running in a worker.');\n return stubExtension;\n }\n\n const feedbackSurveyId = config.get('runtime.app.env.DX_POSTHOG_FEEDBACK_SURVEY_ID');\n const apiKey = config.get('runtime.app.env.DX_POSTHOG_API_KEY');\n const api_host = config.get('runtime.app.env.DX_POSTHOG_API_HOST');\n if (!apiKey || !api_host) {\n log.info('Missing POSTHOG_API_KEY or POSTHOG_API_HOST');\n return stubExtension;\n }\n\n const { default: posthog } = yield* Effect.promise(() => import('posthog-js'));\n const { logProcessor } = yield* Effect.promise(() => import('./log-processor'));\n const logBuffer = new LogBuffer();\n let feedbackSurveyAvailable: boolean | null = null;\n\n const checkFeedbackSurveyAvailable = (): Effect.Effect<boolean> =>\n feedbackSurveyId\n ? Effect.promise(() => {\n if (feedbackSurveyAvailable !== null) {\n return Promise.resolve(feedbackSurveyAvailable);\n }\n return new Promise<boolean>((resolve) => {\n posthog.getSurveys((surveys) => {\n const found = surveys.some((s) => s.id === feedbackSurveyId);\n feedbackSurveyAvailable = found;\n resolve(found);\n });\n });\n })\n : Effect.succeed(false);\n\n return {\n initialize: () =>\n Effect.sync(() => {\n // https://posthog.com/docs/libraries/js/config\n posthog.init(apiKey, {\n api_host,\n mask_all_text: true,\n capture_exceptions: true,\n ...posthogConfig,\n });\n if (release || environment) {\n posthog.register({\n ...(release ? { release } : {}),\n ...(environment ? { environment } : {}),\n });\n }\n log.runtimeConfig.processors.push(logProcessor);\n log.runtimeConfig.processors.push(logBuffer.logProcessor);\n }),\n close: () =>\n Effect.sync(() => {\n for (const processor of [logProcessor, logBuffer.logProcessor]) {\n const index = log.runtimeConfig.processors.indexOf(processor);\n if (index !== -1) {\n log.runtimeConfig.processors.splice(index, 1);\n }\n }\n }),\n enable: () => Effect.sync(() => posthog.opt_in_capturing()),\n disable: () => Effect.sync(() => posthog.opt_out_capturing()),\n identify: (distinctId, attributes, setOnceAttributes) => {\n posthog.identify(distinctId, attributes, setOnceAttributes);\n },\n alias: (distinctId, previousId) => {\n posthog.alias(distinctId, previousId);\n },\n setTags: (tags) => {\n posthog.register_for_session(tags);\n },\n get enabled(): boolean {\n return posthog.is_capturing();\n },\n apis: [\n {\n kind: 'events',\n isAvailable: () => Effect.succeed(true),\n captureEvent: (event, attributes) => {\n posthog.capture(event, attributes);\n },\n },\n {\n kind: 'errors',\n isAvailable: () => Effect.succeed(true),\n captureException: (error, attributes) => {\n posthog.captureException(error, attributes);\n },\n },\n {\n kind: 'feedback',\n // TODO(wittjosiah): Support custom surveys.\n captureUserFeedback: (form) => {\n posthog.getSurveys(async (surveys) => {\n const survey = surveys.find((survey) => survey.id === feedbackSurveyId);\n if (!survey || survey.questions.length === 0) {\n log.error('Missing feedback survey or survey has no questions', { feedbackSurveyId });\n return;\n }\n\n let debugLogDumpKey: string | undefined;\n if (form.includeLogs !== false && logBuffer.size > 0) {\n debugLogDumpKey = await uploadLogs(logBuffer.serialize());\n }\n\n // https://posthog.com/docs/surveys/implementing-custom-surveys\n const question = survey.questions[0];\n posthog.capture('survey sent', {\n $survey_id: survey.id,\n $survey_questions: [{ id: question.id, question: question.question }],\n [`$survey_response_${question.id}`]: form.message,\n ...(debugLogDumpKey ? { debug_log_dump_key: debugLogDumpKey } : {}),\n });\n });\n },\n isAvailable: checkFeedbackSurveyAvailable,\n },\n ],\n };\n});\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport * as Client from './client-observability';\nexport * as IPData from './ip-data';\nexport * as Storage from './storage';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Event, scheduleTaskInterval } from '@dxos/async';\nimport { type Client, type ClientServices } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { DeviceKind } from '@dxos/client/halo';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ConnectionState, type NetworkStatus, Platform } from '@dxos/protocols/proto/dxos/client/services';\n\nimport { type DataProvider } from '../observability';\n\nconst SPACE_METRICS_MIN_INTERVAL = 1000 * 60 * 10; // 10 minutes\nconst NETWORK_METRICS_MIN_INTERVAL = 1000 * 60 * 10; // 10 minutes\nconst RUNTIME_METRICS_MIN_INTERVAL = 1000 * 60 * 10; // 10 minutes\n\n// TODO(wittjosiah): Improve privacy of telemetry identifiers.\n// - Identifier should be generated client-side with no attachment to identity.\n// - Identifier can then be reset by user.\n// - Identifier can be synced via HALO to allow for correlation of events bewteen devices.\n// - Identifier should also be stored outside of HALO such that it is available immediately on startup.\n/** Subscribes to identity and device changes and sets observability tags accordingly. */\nexport const identityProvider = (clientServices: Partial<ClientServices>): DataProvider =>\n Effect.fn(function* (observability) {\n // TODO(wittjosiah): RPC subscribe returns void; cleanup requires upstream API change.\n clientServices.IdentityService!.queryIdentity().subscribe((idqr) => {\n if (!idqr?.identity?.did) {\n return;\n }\n\n observability.identify(idqr.identity.did);\n observability.setTags({ did: idqr.identity.did });\n });\n\n // TODO(wittjosiah): RPC subscribe returns void; cleanup requires upstream API change.\n clientServices.DevicesService!.queryDevices().subscribe((dqr) => {\n if (!dqr?.devices || dqr.devices.length === 0) {\n return;\n }\n\n const thisDevice = dqr.devices.find((device) => device.kind === DeviceKind.CURRENT);\n if (!thisDevice) {\n return;\n }\n\n observability.setTags({ deviceKey: thisDevice.deviceKey.truncate() });\n if (thisDevice.profile?.label) {\n observability.setTags({ deviceProfile: thisDevice.profile.label });\n }\n });\n });\n\n/** Periodically publishes network connection and buffer metrics. */\nexport const networkMetricsProvider = (clientServices: Partial<ClientServices>): DataProvider =>\n Effect.fn(function* (observability) {\n const ctx = new Context();\n let lastNetworkStatus: NetworkStatus | undefined;\n\n // TODO(nf): support type in debounce()\n const updateSignalMetrics = new Event<NetworkStatus>().debounce(NETWORK_METRICS_MIN_INTERVAL);\n updateSignalMetrics.on(ctx, async () => {\n log('send signal metrics');\n (lastNetworkStatus?.signaling as NetworkStatus.Signal[])?.forEach(({ server, state }) => {\n observability.metrics.gauge('dxos.client.network.signal.connectionState', state, { server });\n });\n\n let swarmCount = 0;\n const connectionStates = new Map<string, number>();\n for (const state in ConnectionState) {\n connectionStates.set(state, 0);\n }\n\n let totalReadBufferSize = 0;\n let totalWriteBufferSize = 0;\n let totalChannelBufferSize = 0;\n\n lastNetworkStatus?.connectionInfo?.forEach((connectionInfo) => {\n swarmCount++;\n\n for (const conn of connectionInfo.connections ?? []) {\n connectionStates.set(conn.state, (connectionStates.get(conn.state) ?? 0) + 1);\n totalReadBufferSize += conn.readBufferSize ?? 0;\n totalWriteBufferSize += conn.writeBufferSize ?? 0;\n for (const stream of conn.streams ?? []) {\n totalChannelBufferSize += stream.writeBufferSize ?? 0;\n }\n }\n\n observability.metrics.gauge('dxos.client.network.swarm.count', swarmCount);\n for (const state in ConnectionState) {\n observability.metrics.gauge('dxos.client.network.connection.count', connectionStates.get(state) ?? 0, {\n state,\n });\n }\n observability.metrics.gauge('dxos.client.network.totalReadBufferSize', totalReadBufferSize);\n observability.metrics.gauge('dxos.client.network.totalWriteBufferSize', totalWriteBufferSize);\n observability.metrics.gauge('dxos.client.network.totalChannelBufferSize', totalChannelBufferSize);\n });\n });\n\n clientServices.NetworkService!.queryStatus().subscribe((networkStatus) => {\n lastNetworkStatus = networkStatus;\n updateSignalMetrics.emit();\n });\n\n scheduleTaskInterval(ctx, async () => updateSignalMetrics.emit(), NETWORK_METRICS_MIN_INTERVAL);\n\n return async () => {\n await ctx.dispose();\n };\n });\n\n/** Periodically publishes platform and heap memory metrics. */\nexport const runtimeMetricsProvider = (clientServices: Partial<ClientServices>): DataProvider =>\n Effect.fn(function* (observability) {\n const ctx = new Context();\n const platform = yield* Effect.promise(() => clientServices.SystemService!.getPlatform());\n invariant(platform, 'platform is required');\n\n observability.setTags({\n platformType: Platform.PLATFORM_TYPE[platform.type as number].toLowerCase(),\n platform: platform.platform,\n arch: platform.arch,\n runtime: platform.runtime,\n });\n\n scheduleTaskInterval(\n ctx,\n async () => {\n if (clientServices.constructor.name === 'WorkerClientServices') {\n const memory = (window.performance as any).memory;\n if (memory) {\n observability.metrics.gauge('dxos.client.runtime.heapTotal', memory.totalJSHeapSize);\n observability.metrics.gauge('dxos.client.runtime.heapUsed', memory.usedJSHeapSize);\n observability.metrics.gauge('dxos.client.runtime.heapSizeLimit', memory.jsHeapSizeLimit);\n }\n }\n\n clientServices.SystemService?.getPlatform()\n .then((platform) => {\n if (platform.memory) {\n observability.metrics.gauge('dxos.client.services.runtime.rss', platform.memory.rss);\n observability.metrics.gauge('dxos.client.services.runtime.heapTotal', platform.memory.heapTotal);\n observability.metrics.gauge('dxos.client.services.runtime.heapUsed', platform.memory.heapUsed);\n }\n })\n .catch((error) => log('platform error', { error }));\n },\n RUNTIME_METRICS_MIN_INTERVAL,\n );\n\n return async () => {\n await ctx.dispose();\n };\n });\n\n/** Periodically publishes space membership, object count, and pipeline progress metrics. */\nexport const spacesMetricsProvider = (client: Client): DataProvider =>\n Effect.fn(function* (observability) {\n const ctx = new Context();\n // TODO(nf): update subscription on new spaces\n const spaces = client.spaces.get();\n const subscriptions = new Map<string, { unsubscribe: () => void }>();\n ctx.onDispose(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));\n\n const updateSpaceMetrics = new Event<Space>().debounce(SPACE_METRICS_MIN_INTERVAL);\n updateSpaceMetrics.on(ctx, async () => {\n log('send space metrics');\n for (const data of mapSpaces(spaces, { truncateKeys: true })) {\n observability.metrics.gauge('dxos.client.space.members', data.members, { key: data.key });\n observability.metrics.gauge('dxos.client.space.objects', data.objects, { key: data.key });\n observability.metrics.gauge('dxos.client.space.epoch', data.epoch, { key: data.key });\n observability.metrics.gauge('dxos.client.space.currentDataMutations', data.currentDataMutations, {\n key: data.key,\n });\n }\n });\n\n const subscribeToSpaceUpdate = (space: Space) =>\n space.pipeline.subscribe({\n next: () => {\n updateSpaceMetrics.emit();\n },\n });\n\n spaces.forEach((space) => {\n subscriptions.set(space.id, subscribeToSpaceUpdate(space));\n });\n\n client.spaces.subscribe({\n next: async (spaces) => {\n spaces\n .filter((space) => !subscriptions.has(space.id))\n .forEach((space) => {\n subscriptions.set(space.id, subscribeToSpaceUpdate(space));\n });\n },\n });\n\n scheduleTaskInterval(ctx, async () => updateSpaceMetrics.emit(), SPACE_METRICS_MIN_INTERVAL);\n\n return async () => {\n await ctx.dispose();\n };\n });\n\ntype MapSpacesOptions = {\n verbose?: boolean;\n truncateKeys?: boolean;\n};\n\nconst mapSpaces = (spaces: Space[], options: MapSpacesOptions = { verbose: false, truncateKeys: false }) => {\n return spaces.map((space) => {\n // TODO(burdon): Factor out.\n // TODO(burdon): Agent needs to restart before `ready` is available.\n const { open, ready } = space.internal.data.metrics ?? {};\n const startup = open && ready && ready.getTime() - open.getTime();\n\n // TODO(burdon): Get feeds from client-services if verbose (factor out from devtools/diagnostics).\n // const host = client.services.services.DevtoolsHost!;\n const pipeline = space.internal.data.pipeline;\n const startDataMutations = pipeline?.currentEpoch?.subject.assertion.timeframe.totalMessages() ?? 0;\n const epoch = pipeline?.currentEpoch?.subject.assertion.number;\n // const appliedEpoch = pipeline?.appliedEpoch?.subject.assertion.number;\n const currentDataMutations = pipeline?.currentDataTimeframe?.totalMessages() ?? 0;\n const totalDataMutations = pipeline?.targetDataTimeframe?.totalMessages() ?? 0;\n\n return {\n // TODO(nf): truncate keys for DD?\n key: space.key.truncate(),\n open: space.isOpen,\n members: space.members.get().length,\n objects: space.internal.db.coreDatabase.getAllObjectIds().length,\n startup,\n epoch,\n // appliedEpoch,\n startDataMutations,\n currentDataMutations,\n totalDataMutations,\n\n // TODO(burdon): Negative?\n progress: (\n Math.min(Math.abs((currentDataMutations - startDataMutations) / (totalDataMutations - startDataMutations)), 1) *\n 100\n ).toFixed(0),\n };\n });\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as FetchHttpClient from '@effect/platform/FetchHttpClient';\nimport * as HttpClient from '@effect/platform/HttpClient';\nimport * as HttpClientRequest from '@effect/platform/HttpClientRequest';\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n// NOTE: localStorage is not available in web workers.\nimport * as localForage from 'localforage';\n\nimport { type Config } from '@dxos/config';\nimport { log } from '@dxos/log';\n\nimport { type DataProvider } from '../observability';\n\nconst IP_DATA_CACHE_TIMEOUT = 6 * 60 * 60 * 1000; // 6 hours\n\nconst IPData = Schema.Struct({\n city: Schema.String,\n region: Schema.String,\n country: Schema.String,\n latitude: Schema.optional(Schema.Number),\n longitude: Schema.optional(Schema.Number),\n});\ntype IPData = Schema.Schema.Type<typeof IPData>;\n\ntype CachedIPData = {\n data: IPData;\n timestamp: number;\n};\n\nconst getIPData = Effect.fn(function* (config: Config) {\n const httpClient = yield* HttpClient.HttpClient;\n\n // Check cache first.\n const cachedData = yield* Effect.promise(() => localForage.getItem<CachedIPData>('dxos:observability:ipdata'));\n if (cachedData && cachedData.timestamp > Date.now() - IP_DATA_CACHE_TIMEOUT) {\n return cachedData.data;\n }\n\n // Fetch data if not cached.\n const IPDATA_API_KEY = config.get('runtime.app.env.DX_IPDATA_API_KEY');\n if (IPDATA_API_KEY) {\n const data = yield* HttpClientRequest.get(`https://api.ipdata.co?api-key=${IPDATA_API_KEY}`).pipe(\n httpClient.execute,\n Effect.flatMap((res) => res.json),\n Effect.flatMap(Schema.decodeUnknown(IPData)),\n );\n\n // Cache data.\n yield* Effect.promise(() =>\n localForage.setItem('dxos:observability:ipdata', {\n data,\n timestamp: Date.now(),\n }),\n );\n\n return data;\n }\n});\n\n/** Fetches IP geolocation data and sets city/region/country tags on the observability instance. */\nexport const provider =\n (config: Config): DataProvider =>\n (observability) =>\n Effect.gen(function* () {\n const ipData = yield* getIPData(config);\n if (!ipData) {\n return;\n }\n\n observability.setTags({\n city: ipData.city,\n region: ipData.region,\n country: ipData.country,\n latitude: ipData.latitude,\n longitude: ipData.longitude,\n });\n }).pipe(\n Effect.provide(FetchHttpClient.layer),\n Effect.catchAll((err) =>\n Effect.sync(() => {\n log.catch(err);\n }),\n ),\n );\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as Schedule from 'effect/Schedule';\n\nimport { type DataProvider } from '../observability';\n\nexport const provider: DataProvider = Effect.fn(function* (observability) {\n if (typeof navigator !== 'undefined' && navigator.storage?.estimate) {\n const action = Effect.gen(function* () {\n const storageEstimate = yield* Effect.tryPromise(() => navigator.storage.estimate());\n storageEstimate.usage && observability.metrics.gauge('storageUsage', storageEstimate.usage);\n storageEstimate.quota && observability.metrics.gauge('storageQuota', storageEstimate.quota);\n });\n\n const fiber = action.pipe(Effect.repeat(Schedule.fixed(Duration.hours(1))), Effect.runFork);\n return () => Effect.runSync(Fiber.interrupt(fiber));\n }\n});\n"],
5
- "mappings": "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",
6
- "names": ["LogLevel", "shortLevelName", "CircularBuffer", "DEFAULT_BUFFER_SIZE", "MAX_CONTEXT_LENGTH", "LogBuffer", "_buffer", "size", "CircularBuffer", "logProcessor", "_config", "entry", "level", "LogLevel", "TRACE", "record", "t", "Date", "toISOString", "l", "shortLevelName", "m", "message", "meta", "f", "getRelativeFilename", "F", "n", "L", "error", "e", "stack", "context", "ctx", "Error", "json", "JSON", "stringify", "length", "slice", "c", "push", "elementCount", "serialize", "lines", "join", "filename", "match", "Array", "Effect", "Function", "SubscriptionList", "invariant", "log", "localForage", "log", "OBSERVABILITY_DISABLED_KEY", "OBSERVABILITY_GROUP_KEY", "showObservabilityBanner", "warn", "isObservabilityDisabled", "namespace", "getItem", "err", "catch", "storeObservabilityDisabled", "value", "setItem", "String", "getObservabilityGroup", "undefined", "storeObservabilityGroup", "ObservabilityImpl", "_initialized", "_extensions", "_dataProviders", "_subscriptions", "SubscriptionList", "initialize", "succeed", "undefined", "initializedExtensions", "gen", "extension", "push", "cleanups", "all", "map", "provider", "add", "filter", "cleanup", "pipe", "catchAll", "error", "log", "catch", "close", "clear", "length", "enable", "disable", "flush", "_addExtension", "invariant", "_addDataProvider", "dataProvider", "addDataProvider", "identify", "distinctId", "attributes", "setOnceAttributes", "alias", "previousId", "setTags", "tags", "kind", "apis", "some", "api", "processedTags", "Object", "fromEntries", "entries", "entry", "key", "value", "toString", "enabled", "every", "errors", "captureException", "_getExtensions", "events", "captureEvent", "event", "feedback", "captureUserFeedback", "form", "isAvailable", "available", "metrics", "gauge", "name", "increment", "distribution", "flatMap", "make", "addExtension", "_extension", "fn", "_observability", "observability", "defaultResource", "resourceFromAttributes", "ATTR_SERVICE_NAME", "ATTR_SERVICE_VERSION", "Effect", "Match", "Option", "Ref", "LogLevel", "log", "isNode", "isNonNullable", "Effect", "stubExtension", "initialize", "succeed", "undefined", "enable", "disable", "flush", "setTags", "enabled", "apis", "extensions", "fn", "serviceName", "serviceVersion", "environment", "config", "endpoint", "_endpoint", "headers", "_headers", "logs", "logsEnabled", "logLevel", "LogLevel", "INFO", "metrics", "metricsEnabled", "traces", "tracesEnabled", "OtelLogs", "promise", "OtelMetrics", "OtelTraces", "cachedDisabled", "isObservabilityDisabled", "enabledRef", "make", "tags", "Map", "isNode", "process", "env", "DX_OTEL_ENDPOINT", "buildSecrets", "OTEL_ENDPOINT", "values", "runtime", "app", "value", "pipe", "when", "fromNullable", "DX_OTEL_HEADERS", "OTEL_HEADERS", "exhaustive", "map", "raw", "parseHeaders", "getOrElse", "undefined", "log", "info", "stubExtension", "resource", "defaultResource", "merge", "resourceFromAttributes", "ATTR_SERVICE_NAME", "ATTR_SERVICE_VERSION", "getTags", "Object", "fromEntries", "initialize", "sync", "runtimeConfig", "processors", "push", "logProcessor", "start", "enable", "storeObservabilityDisabled", "update", "disable", "close", "flush", "setTags", "incomingTags", "key", "entries", "set", "enabled", "get", "runSync", "apis", "kind", "isAvailable", "succeed", "gauge", "name", "increment", "distribution", "filter", "isNonNullable", "unparsedHeaders", "split", "reduce", "acc", "header", "rest", "length", "trim", "toLowerCase", "join", "extensions", "Effect", "log", "uploadLogs", "body", "response", "fetch", "method", "headers", "ok", "log", "warn", "status", "undefined", "key", "json", "err", "error", "extensions", "fn", "config", "release", "environment", "posthog", "posthogConfig", "window", "stubExtension", "feedbackSurveyId", "get", "apiKey", "api_host", "info", "default", "promise", "logProcessor", "logBuffer", "LogBuffer", "feedbackSurveyAvailable", "checkFeedbackSurveyAvailable", "Promise", "resolve", "getSurveys", "surveys", "found", "some", "s", "id", "succeed", "initialize", "sync", "init", "mask_all_text", "capture_exceptions", "register", "runtimeConfig", "processors", "push", "close", "processor", "index", "indexOf", "splice", "enable", "opt_in_capturing", "disable", "opt_out_capturing", "identify", "distinctId", "attributes", "setOnceAttributes", "alias", "previousId", "setTags", "tags", "register_for_session", "enabled", "is_capturing", "apis", "kind", "isAvailable", "captureEvent", "event", "capture", "captureException", "captureUserFeedback", "form", "survey", "find", "questions", "length", "debugLogDumpKey", "includeLogs", "size", "serialize", "question", "$survey_id", "$survey_questions", "message", "debug_log_dump_key", "Effect", "Event", "scheduleTaskInterval", "DeviceKind", "Context", "invariant", "log", "ConnectionState", "Platform", "SPACE_METRICS_MIN_INTERVAL", "NETWORK_METRICS_MIN_INTERVAL", "RUNTIME_METRICS_MIN_INTERVAL", "identityProvider", "clientServices", "fn", "observability", "IdentityService", "queryIdentity", "subscribe", "idqr", "identity", "did", "identify", "setTags", "DevicesService", "queryDevices", "dqr", "devices", "length", "thisDevice", "find", "device", "kind", "CURRENT", "deviceKey", "truncate", "profile", "label", "deviceProfile", "networkMetricsProvider", "ctx", "lastNetworkStatus", "updateSignalMetrics", "debounce", "on", "signaling", "forEach", "server", "state", "metrics", "gauge", "swarmCount", "connectionStates", "Map", "set", "totalReadBufferSize", "totalWriteBufferSize", "totalChannelBufferSize", "connectionInfo", "conn", "connections", "get", "readBufferSize", "writeBufferSize", "stream", "streams", "NetworkService", "queryStatus", "networkStatus", "emit", "dispose", "runtimeMetricsProvider", "platform", "promise", "SystemService", "getPlatform", "platformType", "PLATFORM_TYPE", "type", "toLowerCase", "arch", "runtime", "name", "memory", "window", "performance", "totalJSHeapSize", "usedJSHeapSize", "jsHeapSizeLimit", "then", "rss", "heapTotal", "heapUsed", "catch", "error", "spacesMetricsProvider", "client", "spaces", "subscriptions", "onDispose", "subscription", "unsubscribe", "updateSpaceMetrics", "data", "mapSpaces", "truncateKeys", "members", "key", "objects", "epoch", "currentDataMutations", "subscribeToSpaceUpdate", "space", "pipeline", "next", "id", "filter", "has", "options", "verbose", "map", "open", "ready", "internal", "startup", "getTime", "startDataMutations", "currentEpoch", "subject", "assertion", "timeframe", "totalMessages", "number", "currentDataTimeframe", "totalDataMutations", "targetDataTimeframe", "isOpen", "db", "coreDatabase", "getAllObjectIds", "progress", "Math", "min", "abs", "toFixed", "FetchHttpClient", "HttpClient", "HttpClientRequest", "Effect", "Schema", "localForage", "log", "IP_DATA_CACHE_TIMEOUT", "IPData", "Struct", "city", "String", "region", "country", "latitude", "optional", "Number", "longitude", "getIPData", "fn", "config", "httpClient", "cachedData", "promise", "getItem", "timestamp", "Date", "now", "data", "IPDATA_API_KEY", "get", "pipe", "execute", "flatMap", "res", "json", "decodeUnknown", "setItem", "provider", "observability", "gen", "ipData", "setTags", "provide", "layer", "catchAll", "err", "sync", "catch", "provider", "Duration", "Effect", "Fiber", "Schedule", "provider", "fn", "observability", "navigator", "storage", "estimate", "action", "gen", "storageEstimate", "tryPromise", "usage", "metrics", "gauge", "quota", "fiber", "pipe", "repeat", "fixed", "hours", "runFork", "runSync", "interrupt"]
3
+ "sources": ["../../../src/observability.ts", "../../../src/storage/browser.ts", "../../../src/observability-extension.ts", "../../../src/extensions/otel/index.ts", "../../../src/extensions/otel/extension.ts", "../../../src/cli-observability-secrets.json", "../../../src/extensions/stub.ts", "../../../src/extensions/posthog/index.ts", "../../../src/extensions/posthog/extension.ts", "../../../src/providers/index.ts", "../../../src/providers/client-observability.ts", "../../../src/providers/ip-data.ts", "../../../src/providers/storage.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Array from 'effect/Array';\nimport * as Effect from 'effect/Effect';\nimport * as Function from 'effect/Function';\n\nimport { type CleanupFn, SubscriptionList } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport {\n type Attributes,\n type Errors,\n type Events,\n type Extension,\n type ExtensionApi,\n type Feedback,\n type Kind,\n type Metrics,\n} from './observability-extension';\n\nexport * from './storage';\n\n// TODO(wittjosiah): Figure out how to handle when telemetry is disabled.\n// In theory the setting should be both persisted and synchronized.\n// Initialize probably should still run for the cases where data is emitted manually (e.g., feedback).\n\n/**\n * Provider of observability data.\n */\nexport type DataProvider = (observability: Observability) => Effect.Effect<CleanupFn | void, Error>;\n\n/**\n * Extensible observability provider.\n */\n// TODO(wittjosiah): Add pipe method.\nexport interface Observability {\n initialize(): Effect.Effect<void>;\n close(): Effect.Effect<void>;\n enable(): Effect.Effect<void>;\n disable(): Effect.Effect<void>;\n flush(): Effect.Effect<void>;\n addDataProvider(dataProvider: DataProvider): Effect.Effect<void, Error>;\n identify(distinctId: string, attributes?: Attributes, setOnceAttributes?: Attributes): void;\n alias(distinctId: string, previousId?: string): void;\n setTags(tags: Attributes, kind?: Kind): void;\n enabled: boolean;\n errors: Errors;\n events: Events;\n feedback: Feedback;\n /** True if at least one extension of the given kind reports as available. */\n isAvailable(kind: Kind): Effect.Effect<boolean>;\n metrics: Metrics;\n}\n\nclass ObservabilityImpl implements Observability {\n private _initialized = false;\n private readonly _extensions: Extension[] = [];\n private readonly _dataProviders: DataProvider[] = [];\n private readonly _subscriptions = new SubscriptionList();\n\n initialize(): Effect.Effect<void> {\n if (this._initialized) {\n return Effect.succeed(undefined);\n }\n\n const initializedExtensions: Extension[] = [];\n\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.initialize) {\n yield* extension.initialize();\n }\n initializedExtensions.push(extension);\n }\n\n const cleanups = yield* Effect.all(this._dataProviders.map((provider) => provider(this)));\n this._subscriptions.add(...cleanups.filter((cleanup) => cleanup !== undefined));\n this._initialized = true;\n }).pipe(\n Effect.catchAll((error) =>\n Effect.gen(this, function* () {\n log.catch(error);\n // Roll back already-initialized extensions.\n for (const extension of initializedExtensions) {\n if (extension.close) {\n yield* extension.close().pipe(Effect.catchAll(() => Effect.succeed(undefined)));\n }\n }\n this._subscriptions.clear();\n }),\n ),\n );\n }\n\n close(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n this._subscriptions.clear();\n this._dataProviders.length = 0;\n for (const extension of this._extensions) {\n if (extension.close) {\n yield* extension.close();\n }\n }\n this._initialized = false;\n });\n }\n\n enable(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.enable) {\n yield* extension.enable();\n }\n }\n });\n }\n\n disable(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.disable) {\n yield* extension.disable();\n }\n }\n });\n }\n\n flush(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n for (const extension of this._extensions) {\n if (extension.flush) {\n yield* extension.flush();\n }\n }\n });\n }\n\n _addExtension(extension: Extension): void {\n invariant(!this._initialized, 'Observability is already initialized');\n this._extensions.push(extension);\n }\n\n _addDataProvider(dataProvider: DataProvider): void {\n invariant(!this._initialized, 'Observability is already initialized');\n this._dataProviders.push(dataProvider);\n }\n\n /**\n * Adds a data provider and initializes it.\n */\n addDataProvider(dataProvider: DataProvider): Effect.Effect<void, Error> {\n return Effect.gen(this, function* () {\n this._dataProviders.push(dataProvider);\n const cleanup = yield* dataProvider(this);\n if (cleanup) {\n this._subscriptions.add(cleanup);\n }\n });\n }\n\n identify(distinctId: string, attributes?: Attributes, setOnceAttributes?: Attributes): void {\n for (const extension of this._extensions) {\n extension.identify?.(distinctId, attributes, setOnceAttributes);\n }\n }\n\n alias(distinctId: string, previousId?: string): void {\n for (const extension of this._extensions) {\n extension.alias?.(distinctId, previousId);\n }\n }\n\n setTags(tags: Attributes, kind?: Kind): void {\n for (const extension of this._extensions) {\n if (kind && !extension.apis.some((api) => api.kind === kind)) {\n continue;\n }\n\n const processedTags = Object.fromEntries(\n Object.entries(tags)\n .filter((entry): entry is [string, string | number | boolean] => entry[1] !== undefined)\n .map(([key, value]) => [key, value.toString()]),\n );\n extension.setTags?.(processedTags);\n }\n }\n\n get enabled(): boolean {\n return this._extensions.every((extension) => extension.enabled);\n }\n\n get errors(): Errors {\n return {\n captureException: (error, attributes) => {\n for (const extension of this._getExtensions('errors')) {\n extension.captureException(error, attributes);\n }\n },\n };\n }\n\n get events(): Events {\n return {\n captureEvent: (event, attributes) => {\n for (const extension of this._getExtensions('events')) {\n extension.captureEvent(event, attributes);\n }\n },\n };\n }\n\n get feedback(): Feedback {\n return {\n captureUserFeedback: (form) => {\n for (const extension of this._getExtensions('feedback')) {\n extension.captureUserFeedback(form);\n }\n },\n };\n }\n\n isAvailable(kind: Kind): Effect.Effect<boolean> {\n const apis = this._getExtensions(kind);\n if (apis.length === 0) {\n return Effect.succeed(false);\n }\n return Effect.gen(this, function* () {\n for (const api of apis) {\n const available = yield* api.isAvailable();\n if (available) {\n return true;\n }\n }\n return false;\n });\n }\n\n get metrics(): Metrics {\n return {\n gauge: (name, value, attributes) => {\n for (const extension of this._getExtensions('metrics')) {\n extension.gauge(name, value, attributes);\n }\n },\n increment: (name, value, attributes) => {\n for (const extension of this._getExtensions('metrics')) {\n extension.increment(name, value, attributes);\n }\n },\n distribution: (name, value, attributes) => {\n for (const extension of this._getExtensions('metrics')) {\n extension.distribution(name, value, attributes);\n }\n },\n };\n }\n\n private _getExtensions<T extends Kind>(kind: T): Extract<ExtensionApi, { kind: T }>[] {\n return Function.pipe(\n this._extensions,\n Array.flatMap((extension) => extension.apis),\n Array.filter((api): api is Extract<ExtensionApi, { kind: T }> => api.kind === kind),\n );\n }\n}\n\nexport const make = (): Effect.Effect<Observability> => Effect.succeed(new ObservabilityImpl());\n\nexport const addExtension = (_extension: Effect.Effect<Extension>) =>\n Effect.fn(function* (_observability: Effect.Effect<Observability>) {\n const observability = yield* _observability;\n const extension = yield* _extension;\n invariant('_addExtension' in observability && typeof observability._addExtension === 'function');\n observability._addExtension(extension);\n return observability;\n });\n\nexport const addDataProvider = (dataProvider: DataProvider) =>\n Effect.fn(function* (_observability: Effect.Effect<Observability>) {\n const observability = yield* _observability;\n invariant('_addDataProvider' in observability && typeof observability._addDataProvider === 'function');\n observability._addDataProvider(dataProvider);\n return observability;\n });\n\nexport const initialize = Effect.fn(function* (_observability: Effect.Effect<Observability>) {\n const observability = yield* _observability;\n yield* observability.initialize();\n return observability;\n});\n", "//\n// Copyright 2022 DXOS.org\n//\n\n// NOTE: localStorage is not available in web workers.\nimport * as localForage from 'localforage';\n\nimport { log } from '@dxos/log';\n\nconst OBSERVABILITY_DISABLED_KEY = 'observability-disabled';\nconst OBSERVABILITY_GROUP_KEY = 'observability-group';\n\n/** No-op in browser contexts. */\nexport const showObservabilityBanner = () => {\n log.warn('showObservabilityBanner is not supported in browser contexts.');\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const isObservabilityDisabled = async (namespace: string): Promise<boolean> => {\n try {\n return (await localForage.getItem(`${namespace}:${OBSERVABILITY_DISABLED_KEY}`)) === 'true';\n } catch (err) {\n log.catch('Failed to check if observability is disabled, assuming it is', err);\n return true;\n }\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const storeObservabilityDisabled = async (namespace: string, value: boolean) => {\n try {\n await localForage.setItem(`${namespace}:${OBSERVABILITY_DISABLED_KEY}`, String(value));\n } catch (err) {\n log.catch('Failed to store observability disabled', err);\n }\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const getObservabilityGroup = async (namespace: string): Promise<string | undefined> => {\n try {\n return (await localForage.getItem(`${namespace}:${OBSERVABILITY_GROUP_KEY}`)) ?? undefined;\n } catch (err) {\n log.catch('Failed to get observability group', err);\n }\n};\n\n/**\n * @param namespace - localForage key prefix used to scope the observability state in browser storage.\n */\nexport const storeObservabilityGroup = async (namespace: string, value: string) => {\n try {\n await localForage.setItem(`${namespace}:${OBSERVABILITY_GROUP_KEY}`, value);\n } catch (err) {\n log.catch('Failed to store observability group', err);\n }\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport type * as Effect from 'effect/Effect';\n\nexport * from './extensions';\n\n/**\n * Kind of observability extension.\n *\n * - errors: Error tracking (e.g., PostHog)\n * - events: Product usage event tracking (e.g., PostHog)\n * - feedback: User feedback submission (e.g., PostHog)\n * - logs: Structured logging (e.g., OTEL)\n * - metrics: Metric data (e.g., OTEL)\n * - traces: Distributed tracing (e.g., OTEL)\n */\nexport type Kind = 'errors' | 'events' | 'feedback' | 'logs' | 'metrics' | 'traces';\n\n/**\n * Base for every extension API variant. All kinds implement availability the same way.\n */\nexport type ExtensionApiBase<K extends Kind = Kind> = {\n kind: K;\n isAvailable(): Effect.Effect<boolean>;\n};\n\n/**\n * Metrics extension API (kind-specific methods only).\n */\nexport type Metrics = {\n gauge(name: string, value: number, tags?: Attributes): void;\n increment(name: string, value?: number, tags?: Attributes): void;\n distribution(name: string, value: number, tags?: Attributes): void;\n};\n\n/**\n * Errors extension API (kind-specific methods only).\n */\nexport type Errors = {\n captureException(error: Error, attributes?: Attributes): void;\n};\n\n/**\n * Events extension API (kind-specific methods only).\n */\nexport type Events = {\n captureEvent(event: string, attributes?: Attributes): void;\n};\n\n/**\n * Feedback extension API (kind-specific methods only).\n */\nexport type Feedback = {\n captureUserFeedback(form: FeedbackForm): void;\n};\n\nexport type ExtensionApi =\n | (ExtensionApiBase<'errors'> & Errors)\n | (ExtensionApiBase<'events'> & Events)\n | (ExtensionApiBase<'feedback'> & Feedback)\n // TODO(wittjosiah): Direct logs api?\n | ExtensionApiBase<'logs'>\n | (ExtensionApiBase<'metrics'> & Metrics)\n // TODO(wittjosiah): Direct traces api?\n | ExtensionApiBase<'traces'>;\n\n/**\n * Feedback form to be captured by the feedback extension.\n */\n// TODO(wittjosiah): Support more form fields (e.g., PostHog custom surveys).\nexport type FeedbackForm = { message: string; includeLogs?: boolean };\n\n/**\n * Attributes to be attached to observability events.\n */\nexport type Attributes = Record<string, string | number | boolean | undefined>;\n\n/**\n * Implementation of an observability extension API.\n */\nexport type Extension = {\n initialize?(): Effect.Effect<void, Error>;\n close?(): Effect.Effect<void>;\n enable?(): Effect.Effect<void>;\n disable?(): Effect.Effect<void>;\n flush?(): Effect.Effect<void>;\n identify?(distinctId: string, attributes?: Attributes, setOnceAttributes?: Attributes): void;\n alias?(distinctId: string, previousId?: string): void;\n setTags?(tags: Record<string, string>): void;\n enabled: boolean;\n apis: ExtensionApi[];\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nexport * from './extension';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';\nimport { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';\nimport * as Effect from 'effect/Effect';\nimport * as Match from 'effect/Match';\nimport * as Option from 'effect/Option';\nimport * as Ref from 'effect/Ref';\n\nimport { type Config } from '@dxos/config';\nimport { LogLevel, log } from '@dxos/log';\nimport { isNode, isNonNullable } from '@dxos/util';\n\nimport buildSecrets from '../../cli-observability-secrets.json';\nimport { type Extension, type ExtensionApi } from '../../observability-extension';\nimport { isObservabilityDisabled, storeObservabilityDisabled } from '../../storage';\nimport { stubExtension } from '../stub';\n\nexport type ExtensionsOptions = {\n /** For the OTEL, the name of the entity for which signals (metrics or trace) are collected. */\n serviceName: string;\n /** For the OTEL, the version of the entity for which signals (metrics or trace) are collected. */\n serviceVersion: string;\n /** For the OTEL, the environment of the entity for which signals (metrics or trace) are collected. */\n environment: string;\n config: Config;\n endpoint?: string;\n headers?: Record<string, string>;\n logs?: boolean;\n /** Minimum log level to export. Defaults to INFO (i.e. info, warn, error). */\n logLevel?: LogLevel;\n metrics?: boolean;\n traces?: boolean;\n};\n\n/** Create an OTEL-backed observability extension for logs, metrics, and/or traces. */\nexport const extensions: (options: ExtensionsOptions) => Effect.Effect<Extension> = Effect.fn(function* ({\n serviceName,\n serviceVersion,\n environment,\n config,\n endpoint: _endpoint,\n headers: _headers,\n // TODO(wittjosiah): Logging integration.\n // - logger should run even if observability is disabled\n // - logs should be cached locally in a circular buffer\n // - logs should be flushed to the server if user opts to include them in a bug report\n logs: logsEnabled = false,\n logLevel = LogLevel.INFO,\n metrics: metricsEnabled = false,\n traces: tracesEnabled = false,\n}) {\n const { OtelLogs } = yield* Effect.promise(() => import('./logs'));\n const { OtelMetrics } = yield* Effect.promise(() => import('./metrics'));\n const { OtelTraces } = yield* Effect.promise(() => import('./traces'));\n\n const cachedDisabled = yield* Effect.promise(() => isObservabilityDisabled(serviceName));\n const enabledRef = yield* Ref.make(!cachedDisabled);\n const tags = new Map<string, string>();\n\n const endpoint = isNode()\n ? (process.env.DX_OTEL_ENDPOINT ?? _endpoint ?? buildSecrets.OTEL_ENDPOINT)\n : config.values.runtime?.app?.env?.DX_OTEL_ENDPOINT;\n const headers =\n _headers ??\n Match.value(isNode()).pipe(\n Match.when(true, () => Option.fromNullable(process.env.DX_OTEL_HEADERS ?? buildSecrets.OTEL_HEADERS)),\n Match.when(false, () => Option.fromNullable(config.values.runtime?.app?.env?.DX_OTEL_HEADERS)),\n Match.exhaustive,\n Option.map((raw) => parseHeaders(raw)),\n Option.getOrElse(() => undefined),\n );\n\n if (!endpoint || !headers) {\n log.info('Missing OTEL_ENDPOINT or OTEL_HEADERS');\n return stubExtension;\n }\n\n const resource = defaultResource().merge(\n resourceFromAttributes({\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_SERVICE_VERSION]: serviceVersion,\n 'deployment.environment': environment,\n }),\n );\n\n const logs = logsEnabled\n ? new OtelLogs({\n endpoint,\n headers,\n resource,\n getTags: () => Object.fromEntries(tags),\n logLevel,\n })\n : undefined;\n\n const metrics = metricsEnabled\n ? new OtelMetrics({\n endpoint,\n headers,\n resource,\n getTags: () => Object.fromEntries(tags),\n })\n : undefined;\n\n const traces = tracesEnabled\n ? new OtelTraces({\n endpoint,\n headers,\n resource,\n getTags: () => Object.fromEntries(tags),\n })\n : undefined;\n\n return {\n initialize: () =>\n Effect.sync(() => {\n if (logs) {\n log.runtimeConfig.processors.push(logs.logProcessor);\n }\n if (traces) {\n traces.start();\n }\n }),\n enable: Effect.fn(function* () {\n yield* Effect.promise(() => storeObservabilityDisabled(serviceName, false));\n yield* Ref.update(enabledRef, () => true);\n }),\n disable: Effect.fn(function* () {\n yield* Effect.promise(() => storeObservabilityDisabled(serviceName, true));\n yield* Ref.update(enabledRef, () => false);\n }),\n close: () =>\n Effect.promise(async () => {\n await logs?.close();\n await metrics?.close();\n }),\n flush: () =>\n Effect.promise(async () => {\n await logs?.flush();\n await metrics?.flush();\n }),\n setTags: (incomingTags) => {\n for (const [key, value] of Object.entries(incomingTags)) {\n tags.set(key, value);\n }\n },\n get enabled() {\n return Ref.get(enabledRef).pipe(Effect.runSync);\n },\n apis: [\n { kind: 'logs', isAvailable: () => Effect.succeed(!!logs) } satisfies ExtensionApi,\n metrics\n ? ({\n kind: 'metrics',\n isAvailable: () => Effect.succeed(true),\n gauge: (name, value, tags) => metrics.gauge(name, value, tags),\n increment: (name, value, tags) => metrics.increment(name, value, tags),\n distribution: (name, value, tags) => metrics.distribution(name, value, tags),\n } satisfies ExtensionApi)\n : undefined,\n traces ? ({ kind: 'traces', isAvailable: () => Effect.succeed(true) } satisfies ExtensionApi) : undefined,\n ].filter(isNonNullable),\n };\n});\n\nconst parseHeaders = (unparsedHeaders: string): Record<string, string> => {\n return unparsedHeaders.split(';').reduce((acc: Record<string, string>, header) => {\n const [key, ...rest] = header.split(':');\n if (key && rest.length > 0) {\n acc[key.trim().toLowerCase()] = rest.join(':').trim();\n }\n\n return acc;\n }, {});\n};\n", "{\n \"POSTHOG_API_KEY\": null,\n \"IPDATA_API_KEY\": \"73dfdecdf979c18f07d50cf841bbdd9e589f237256326ac8cca23786\",\n \"OTEL_ENDPOINT\": \"https://ingest.eu.signoz.cloud:443\",\n \"OTEL_HEADERS\": \"signoz-ingestion-key: 5300e0c9-a5e8-4a10-9c61-f473e539c0b7\"\n}", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { type Extension } from '../observability-extension';\n\nexport const stubExtension: Extension = {\n initialize: () => Effect.succeed(undefined),\n enable: () => Effect.succeed(undefined),\n disable: () => Effect.succeed(undefined),\n flush: () => Effect.succeed(undefined),\n setTags: () => undefined,\n get enabled() {\n return true;\n },\n apis: [],\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport * from './extension';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport { type PostHogConfig } from 'posthog-js';\n\nimport { type Config } from '@dxos/config';\nimport { LogBuffer, log } from '@dxos/log';\n\nimport { type Extension } from '../../observability-extension';\nimport { stubExtension } from '../stub';\n\nexport type ExtensionsOptions = {\n config: Config;\n /** Release identifier, e.g. `composer@0.8.3`. */\n release?: string;\n /** Deployment environment, e.g. `production` or `staging`. */\n environment?: string;\n posthog?: Partial<PostHogConfig>;\n /** Shared log buffer for debug log dumps. Creates a local one if not provided. */\n logBuffer?: LogBuffer;\n};\n\n/** Upload serialized logs to the feedback-logs endpoint. Returns the R2 key on success. */\nconst uploadLogs = async (body: string): Promise<string | undefined> => {\n try {\n const response = await fetch('/api/feedback-logs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-ndjson' },\n body,\n });\n if (!response.ok) {\n log.warn('feedback log upload failed', { status: response.status });\n return undefined;\n }\n const { key } = await response.json();\n return key;\n } catch (err) {\n log.warn('feedback log upload error', { error: err });\n return undefined;\n }\n};\n\n/** Create a PostHog-backed observability extension for events, errors, and feedback. */\nexport const extensions: (options: ExtensionsOptions) => Effect.Effect<Extension> = Effect.fn(function* ({\n config,\n release,\n environment,\n posthog: posthogConfig,\n logBuffer: externalLogBuffer,\n}) {\n if (typeof window === 'undefined') {\n log('PostHog is being stubbed because it is running in a worker.');\n return stubExtension;\n }\n\n const feedbackSurveyId = config.get('runtime.app.env.DX_POSTHOG_FEEDBACK_SURVEY_ID');\n const apiKey = config.get('runtime.app.env.DX_POSTHOG_API_KEY');\n const api_host = config.get('runtime.app.env.DX_POSTHOG_API_HOST');\n if (!apiKey || !api_host) {\n log.info('Missing POSTHOG_API_KEY or POSTHOG_API_HOST');\n return stubExtension;\n }\n\n const { default: posthog } = yield* Effect.promise(() => import('posthog-js'));\n const { logProcessor } = yield* Effect.promise(() => import('./log-processor'));\n const logBuffer = externalLogBuffer ?? new LogBuffer();\n let feedbackSurveyAvailable: boolean | null = null;\n\n const checkFeedbackSurveyAvailable = (): Effect.Effect<boolean> =>\n feedbackSurveyId\n ? Effect.promise(() => {\n if (feedbackSurveyAvailable !== null) {\n return Promise.resolve(feedbackSurveyAvailable);\n }\n return new Promise<boolean>((resolve) => {\n posthog.getSurveys((surveys) => {\n const found = surveys.some((s) => s.id === feedbackSurveyId);\n feedbackSurveyAvailable = found;\n resolve(found);\n });\n });\n })\n : Effect.succeed(false);\n\n return {\n initialize: () =>\n Effect.sync(() => {\n // https://posthog.com/docs/libraries/js/config\n posthog.init(apiKey, {\n api_host,\n mask_all_text: true,\n capture_exceptions: true,\n ...posthogConfig,\n });\n if (release || environment) {\n posthog.register({\n ...(release ? { release } : {}),\n ...(environment ? { environment } : {}),\n });\n }\n log.runtimeConfig.processors.push(logProcessor);\n log.runtimeConfig.processors.push(logBuffer.logProcessor);\n }),\n close: () =>\n Effect.sync(() => {\n for (const processor of [logProcessor, logBuffer.logProcessor]) {\n const index = log.runtimeConfig.processors.indexOf(processor);\n if (index !== -1) {\n log.runtimeConfig.processors.splice(index, 1);\n }\n }\n }),\n enable: () => Effect.sync(() => posthog.opt_in_capturing()),\n disable: () => Effect.sync(() => posthog.opt_out_capturing()),\n identify: (distinctId, attributes, setOnceAttributes) => {\n posthog.identify(distinctId, attributes, setOnceAttributes);\n },\n alias: (distinctId, previousId) => {\n posthog.alias(distinctId, previousId);\n },\n setTags: (tags) => {\n posthog.register_for_session(tags);\n },\n get enabled(): boolean {\n return posthog.is_capturing();\n },\n apis: [\n {\n kind: 'events',\n isAvailable: () => Effect.succeed(true),\n captureEvent: (event, attributes) => {\n posthog.capture(event, attributes);\n },\n },\n {\n kind: 'errors',\n isAvailable: () => Effect.succeed(true),\n captureException: (error, attributes) => {\n posthog.captureException(error, attributes);\n },\n },\n {\n kind: 'feedback',\n // TODO(wittjosiah): Support custom surveys.\n captureUserFeedback: (form) => {\n posthog.getSurveys(async (surveys) => {\n const survey = surveys.find((survey) => survey.id === feedbackSurveyId);\n if (!survey || survey.questions.length === 0) {\n log.error('Missing feedback survey or survey has no questions', { feedbackSurveyId });\n return;\n }\n\n let debugLogDumpKey: string | undefined;\n if (form.includeLogs !== false && logBuffer.size > 0) {\n debugLogDumpKey = await uploadLogs(logBuffer.serialize());\n }\n\n // https://posthog.com/docs/surveys/implementing-custom-surveys\n const question = survey.questions[0];\n posthog.capture('survey sent', {\n $survey_id: survey.id,\n $survey_questions: [{ id: question.id, question: question.question }],\n [`$survey_response_${question.id}`]: form.message,\n ...(debugLogDumpKey ? { debug_log_dump_key: debugLogDumpKey } : {}),\n });\n });\n },\n isAvailable: checkFeedbackSurveyAvailable,\n },\n ],\n };\n});\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport * as Client from './client-observability';\nexport * as IPData from './ip-data';\nexport * as Storage from './storage';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Event, scheduleTaskInterval } from '@dxos/async';\nimport { type Client, type ClientServices } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { DeviceKind } from '@dxos/client/halo';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ConnectionState, type NetworkStatus, Platform } from '@dxos/protocols/proto/dxos/client/services';\n\nimport { type DataProvider } from '../observability';\n\nconst SPACE_METRICS_MIN_INTERVAL = 1000 * 60 * 10; // 10 minutes\nconst NETWORK_METRICS_MIN_INTERVAL = 1000 * 60 * 10; // 10 minutes\nconst RUNTIME_METRICS_MIN_INTERVAL = 1000 * 60 * 10; // 10 minutes\n\n// TODO(wittjosiah): Improve privacy of telemetry identifiers.\n// - Identifier should be generated client-side with no attachment to identity.\n// - Identifier can then be reset by user.\n// - Identifier can be synced via HALO to allow for correlation of events bewteen devices.\n// - Identifier should also be stored outside of HALO such that it is available immediately on startup.\n/** Subscribes to identity and device changes and sets observability tags accordingly. */\nexport const identityProvider = (clientServices: Partial<ClientServices>): DataProvider =>\n Effect.fn(function* (observability) {\n // TODO(wittjosiah): RPC subscribe returns void; cleanup requires upstream API change.\n clientServices.IdentityService!.queryIdentity().subscribe((idqr) => {\n if (!idqr?.identity?.did) {\n return;\n }\n\n observability.identify(idqr.identity.did);\n observability.setTags({ did: idqr.identity.did });\n });\n\n // TODO(wittjosiah): RPC subscribe returns void; cleanup requires upstream API change.\n clientServices.DevicesService!.queryDevices().subscribe((dqr) => {\n if (!dqr?.devices || dqr.devices.length === 0) {\n return;\n }\n\n const thisDevice = dqr.devices.find((device) => device.kind === DeviceKind.CURRENT);\n if (!thisDevice) {\n return;\n }\n\n observability.setTags({ deviceKey: thisDevice.deviceKey.truncate() });\n if (thisDevice.profile?.label) {\n observability.setTags({ deviceProfile: thisDevice.profile.label });\n }\n });\n });\n\n/** Periodically publishes network connection and buffer metrics. */\nexport const networkMetricsProvider = (clientServices: Partial<ClientServices>): DataProvider =>\n Effect.fn(function* (observability) {\n const ctx = new Context();\n let lastNetworkStatus: NetworkStatus | undefined;\n\n // TODO(nf): support type in debounce()\n const updateSignalMetrics = new Event<NetworkStatus>().debounce(NETWORK_METRICS_MIN_INTERVAL);\n updateSignalMetrics.on(ctx, async () => {\n log('send signal metrics');\n (lastNetworkStatus?.signaling as NetworkStatus.Signal[])?.forEach(({ server, state }) => {\n observability.metrics.gauge('dxos.client.network.signal.connectionState', state, { server });\n });\n\n let swarmCount = 0;\n const connectionStates = new Map<string, number>();\n for (const state in ConnectionState) {\n connectionStates.set(state, 0);\n }\n\n let totalReadBufferSize = 0;\n let totalWriteBufferSize = 0;\n let totalChannelBufferSize = 0;\n\n lastNetworkStatus?.connectionInfo?.forEach((connectionInfo) => {\n swarmCount++;\n\n for (const conn of connectionInfo.connections ?? []) {\n connectionStates.set(conn.state, (connectionStates.get(conn.state) ?? 0) + 1);\n totalReadBufferSize += conn.readBufferSize ?? 0;\n totalWriteBufferSize += conn.writeBufferSize ?? 0;\n for (const stream of conn.streams ?? []) {\n totalChannelBufferSize += stream.writeBufferSize ?? 0;\n }\n }\n\n observability.metrics.gauge('dxos.client.network.swarm.count', swarmCount);\n for (const state in ConnectionState) {\n observability.metrics.gauge('dxos.client.network.connection.count', connectionStates.get(state) ?? 0, {\n state,\n });\n }\n observability.metrics.gauge('dxos.client.network.totalReadBufferSize', totalReadBufferSize);\n observability.metrics.gauge('dxos.client.network.totalWriteBufferSize', totalWriteBufferSize);\n observability.metrics.gauge('dxos.client.network.totalChannelBufferSize', totalChannelBufferSize);\n });\n });\n\n clientServices.NetworkService!.queryStatus().subscribe((networkStatus) => {\n lastNetworkStatus = networkStatus;\n updateSignalMetrics.emit();\n });\n\n scheduleTaskInterval(ctx, async () => updateSignalMetrics.emit(), NETWORK_METRICS_MIN_INTERVAL);\n\n return async () => {\n await ctx.dispose();\n };\n });\n\n/** Periodically publishes platform and heap memory metrics. */\nexport const runtimeMetricsProvider = (clientServices: Partial<ClientServices>): DataProvider =>\n Effect.fn(function* (observability) {\n const ctx = new Context();\n const platform = yield* Effect.promise(() => clientServices.SystemService!.getPlatform());\n invariant(platform, 'platform is required');\n\n observability.setTags({\n platformType: Platform.PLATFORM_TYPE[platform.type as number].toLowerCase(),\n platform: platform.platform,\n arch: platform.arch,\n runtime: platform.runtime,\n });\n\n scheduleTaskInterval(\n ctx,\n async () => {\n if (clientServices.constructor.name === 'WorkerClientServices') {\n const memory = (window.performance as any).memory;\n if (memory) {\n observability.metrics.gauge('dxos.client.runtime.heapTotal', memory.totalJSHeapSize);\n observability.metrics.gauge('dxos.client.runtime.heapUsed', memory.usedJSHeapSize);\n observability.metrics.gauge('dxos.client.runtime.heapSizeLimit', memory.jsHeapSizeLimit);\n }\n }\n\n clientServices.SystemService?.getPlatform()\n .then((platform) => {\n if (platform.memory) {\n observability.metrics.gauge('dxos.client.services.runtime.rss', platform.memory.rss);\n observability.metrics.gauge('dxos.client.services.runtime.heapTotal', platform.memory.heapTotal);\n observability.metrics.gauge('dxos.client.services.runtime.heapUsed', platform.memory.heapUsed);\n }\n })\n .catch((error) => log('platform error', { error }));\n },\n RUNTIME_METRICS_MIN_INTERVAL,\n );\n\n return async () => {\n await ctx.dispose();\n };\n });\n\n/** Periodically publishes space membership, object count, and pipeline progress metrics. */\nexport const spacesMetricsProvider = (client: Client): DataProvider =>\n Effect.fn(function* (observability) {\n const ctx = new Context();\n // TODO(nf): update subscription on new spaces\n const spaces = client.spaces.get();\n const subscriptions = new Map<string, { unsubscribe: () => void }>();\n ctx.onDispose(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));\n\n const updateSpaceMetrics = new Event<Space>().debounce(SPACE_METRICS_MIN_INTERVAL);\n updateSpaceMetrics.on(ctx, async () => {\n log('send space metrics');\n for (const data of mapSpaces(spaces, { truncateKeys: true })) {\n observability.metrics.gauge('dxos.client.space.members', data.members, { key: data.key });\n observability.metrics.gauge('dxos.client.space.objects', data.objects, { key: data.key });\n observability.metrics.gauge('dxos.client.space.epoch', data.epoch, { key: data.key });\n observability.metrics.gauge('dxos.client.space.currentDataMutations', data.currentDataMutations, {\n key: data.key,\n });\n }\n });\n\n const subscribeToSpaceUpdate = (space: Space) =>\n space.pipeline.subscribe({\n next: () => {\n updateSpaceMetrics.emit();\n },\n });\n\n spaces.forEach((space) => {\n subscriptions.set(space.id, subscribeToSpaceUpdate(space));\n });\n\n client.spaces.subscribe({\n next: async (spaces) => {\n spaces\n .filter((space) => !subscriptions.has(space.id))\n .forEach((space) => {\n subscriptions.set(space.id, subscribeToSpaceUpdate(space));\n });\n },\n });\n\n scheduleTaskInterval(ctx, async () => updateSpaceMetrics.emit(), SPACE_METRICS_MIN_INTERVAL);\n\n return async () => {\n await ctx.dispose();\n };\n });\n\ntype MapSpacesOptions = {\n verbose?: boolean;\n truncateKeys?: boolean;\n};\n\nconst mapSpaces = (spaces: Space[], options: MapSpacesOptions = { verbose: false, truncateKeys: false }) => {\n return spaces.map((space) => {\n // TODO(burdon): Factor out.\n // TODO(burdon): Agent needs to restart before `ready` is available.\n const { open, ready } = space.internal.data.metrics ?? {};\n const startup = open && ready && ready.getTime() - open.getTime();\n\n // TODO(burdon): Get feeds from client-services if verbose (factor out from devtools/diagnostics).\n // const host = client.services.services.DevtoolsHost!;\n const pipeline = space.internal.data.pipeline;\n const startDataMutations = pipeline?.currentEpoch?.subject.assertion.timeframe.totalMessages() ?? 0;\n const epoch = pipeline?.currentEpoch?.subject.assertion.number;\n // const appliedEpoch = pipeline?.appliedEpoch?.subject.assertion.number;\n const currentDataMutations = pipeline?.currentDataTimeframe?.totalMessages() ?? 0;\n const totalDataMutations = pipeline?.targetDataTimeframe?.totalMessages() ?? 0;\n\n return {\n // TODO(nf): truncate keys for DD?\n key: space.key.truncate(),\n open: space.isOpen,\n members: space.members.get().length,\n objects: space.internal.db.coreDatabase.getAllObjectIds().length,\n startup,\n epoch,\n // appliedEpoch,\n startDataMutations,\n currentDataMutations,\n totalDataMutations,\n\n // TODO(burdon): Negative?\n progress: (\n Math.min(Math.abs((currentDataMutations - startDataMutations) / (totalDataMutations - startDataMutations)), 1) *\n 100\n ).toFixed(0),\n };\n });\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as FetchHttpClient from '@effect/platform/FetchHttpClient';\nimport * as HttpClient from '@effect/platform/HttpClient';\nimport * as HttpClientRequest from '@effect/platform/HttpClientRequest';\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n// NOTE: localStorage is not available in web workers.\nimport * as localForage from 'localforage';\n\nimport { type Config } from '@dxos/config';\nimport { log } from '@dxos/log';\n\nimport { type DataProvider } from '../observability';\n\nconst IP_DATA_CACHE_TIMEOUT = 6 * 60 * 60 * 1000; // 6 hours\n\nconst IPData = Schema.Struct({\n city: Schema.String,\n region: Schema.String,\n country: Schema.String,\n latitude: Schema.optional(Schema.Number),\n longitude: Schema.optional(Schema.Number),\n});\ntype IPData = Schema.Schema.Type<typeof IPData>;\n\ntype CachedIPData = {\n data: IPData;\n timestamp: number;\n};\n\nconst getIPData = Effect.fn(function* (config: Config) {\n const httpClient = yield* HttpClient.HttpClient;\n\n // Disable tracing to avoid CORS errors from traceparent header on cross-origin requests.\n const httpClientNoTrace = httpClient.pipe(HttpClient.withTracerDisabledWhen(() => true));\n\n // Check cache first.\n const cachedData = yield* Effect.promise(() => localForage.getItem<CachedIPData>('dxos:observability:ipdata'));\n if (cachedData && cachedData.timestamp > Date.now() - IP_DATA_CACHE_TIMEOUT) {\n return cachedData.data;\n }\n\n // Fetch data if not cached.\n const IPDATA_API_KEY = config.get('runtime.app.env.DX_IPDATA_API_KEY');\n if (IPDATA_API_KEY) {\n const data = yield* HttpClientRequest.get(`https://api.ipdata.co?api-key=${IPDATA_API_KEY}`).pipe(\n httpClientNoTrace.execute,\n Effect.flatMap((res) => res.json),\n Effect.flatMap(Schema.decodeUnknown(IPData)),\n );\n\n // Cache data.\n yield* Effect.promise(() =>\n localForage.setItem('dxos:observability:ipdata', {\n data,\n timestamp: Date.now(),\n }),\n );\n\n return data;\n }\n});\n\n/** Fetches IP geolocation data and sets city/region/country tags on the observability instance. */\nexport const provider =\n (config: Config): DataProvider =>\n (observability) =>\n Effect.gen(function* () {\n const ipData = yield* getIPData(config);\n if (!ipData) {\n return;\n }\n\n observability.setTags({\n city: ipData.city,\n region: ipData.region,\n country: ipData.country,\n latitude: ipData.latitude,\n longitude: ipData.longitude,\n });\n }).pipe(\n Effect.provide(FetchHttpClient.layer),\n Effect.catchAll((err) =>\n Effect.sync(() => {\n log.verbose('ipdata fetch failed', { err });\n }),\n ),\n );\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as Schedule from 'effect/Schedule';\n\nimport { type DataProvider } from '../observability';\n\nexport const provider: DataProvider = Effect.fn(function* (observability) {\n if (typeof navigator !== 'undefined' && navigator.storage?.estimate) {\n const action = Effect.gen(function* () {\n const storageEstimate = yield* Effect.tryPromise(() => navigator.storage.estimate());\n storageEstimate.usage && observability.metrics.gauge('storageUsage', storageEstimate.usage);\n storageEstimate.quota && observability.metrics.gauge('storageQuota', storageEstimate.quota);\n });\n\n const fiber = action.pipe(Effect.repeat(Schedule.fixed(Duration.hours(1))), Effect.runFork);\n return () => Effect.runSync(Fiber.interrupt(fiber));\n }\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["Array", "Effect", "Function", "SubscriptionList", "invariant", "log", "localForage", "log", "OBSERVABILITY_DISABLED_KEY", "OBSERVABILITY_GROUP_KEY", "showObservabilityBanner", "warn", "isObservabilityDisabled", "namespace", "getItem", "err", "catch", "storeObservabilityDisabled", "value", "setItem", "String", "getObservabilityGroup", "undefined", "storeObservabilityGroup", "ObservabilityImpl", "_initialized", "_extensions", "_dataProviders", "_subscriptions", "SubscriptionList", "initialize", "succeed", "undefined", "initializedExtensions", "gen", "extension", "push", "cleanups", "all", "map", "provider", "add", "filter", "cleanup", "pipe", "catchAll", "error", "log", "catch", "close", "clear", "length", "enable", "disable", "flush", "_addExtension", "invariant", "_addDataProvider", "dataProvider", "addDataProvider", "identify", "distinctId", "attributes", "setOnceAttributes", "alias", "previousId", "setTags", "tags", "kind", "apis", "some", "api", "processedTags", "Object", "fromEntries", "entries", "entry", "key", "value", "toString", "enabled", "every", "errors", "captureException", "_getExtensions", "events", "captureEvent", "event", "feedback", "captureUserFeedback", "form", "isAvailable", "available", "metrics", "gauge", "name", "increment", "distribution", "flatMap", "make", "addExtension", "_extension", "fn", "_observability", "observability", "defaultResource", "resourceFromAttributes", "ATTR_SERVICE_NAME", "ATTR_SERVICE_VERSION", "Effect", "Match", "Option", "Ref", "LogLevel", "log", "isNode", "isNonNullable", "Effect", "stubExtension", "initialize", "succeed", "undefined", "enable", "disable", "flush", "setTags", "enabled", "apis", "extensions", "fn", "serviceName", "serviceVersion", "environment", "config", "endpoint", "_endpoint", "headers", "_headers", "logs", "logsEnabled", "logLevel", "LogLevel", "INFO", "metrics", "metricsEnabled", "traces", "tracesEnabled", "OtelLogs", "promise", "OtelMetrics", "OtelTraces", "cachedDisabled", "isObservabilityDisabled", "enabledRef", "make", "tags", "Map", "isNode", "process", "env", "DX_OTEL_ENDPOINT", "buildSecrets", "OTEL_ENDPOINT", "values", "runtime", "app", "value", "pipe", "when", "fromNullable", "DX_OTEL_HEADERS", "OTEL_HEADERS", "exhaustive", "map", "raw", "parseHeaders", "getOrElse", "undefined", "log", "info", "stubExtension", "resource", "defaultResource", "merge", "resourceFromAttributes", "ATTR_SERVICE_NAME", "ATTR_SERVICE_VERSION", "getTags", "Object", "fromEntries", "initialize", "sync", "runtimeConfig", "processors", "push", "logProcessor", "start", "enable", "storeObservabilityDisabled", "update", "disable", "close", "flush", "setTags", "incomingTags", "key", "entries", "set", "enabled", "get", "runSync", "apis", "kind", "isAvailable", "succeed", "gauge", "name", "increment", "distribution", "filter", "isNonNullable", "unparsedHeaders", "split", "reduce", "acc", "header", "rest", "length", "trim", "toLowerCase", "join", "extensions", "Effect", "LogBuffer", "log", "uploadLogs", "body", "response", "fetch", "method", "headers", "ok", "log", "warn", "status", "undefined", "key", "json", "err", "error", "extensions", "fn", "config", "release", "environment", "posthog", "posthogConfig", "logBuffer", "externalLogBuffer", "window", "stubExtension", "feedbackSurveyId", "get", "apiKey", "api_host", "info", "default", "promise", "logProcessor", "LogBuffer", "feedbackSurveyAvailable", "checkFeedbackSurveyAvailable", "Promise", "resolve", "getSurveys", "surveys", "found", "some", "s", "id", "succeed", "initialize", "sync", "init", "mask_all_text", "capture_exceptions", "register", "runtimeConfig", "processors", "push", "close", "processor", "index", "indexOf", "splice", "enable", "opt_in_capturing", "disable", "opt_out_capturing", "identify", "distinctId", "attributes", "setOnceAttributes", "alias", "previousId", "setTags", "tags", "register_for_session", "enabled", "is_capturing", "apis", "kind", "isAvailable", "captureEvent", "event", "capture", "captureException", "captureUserFeedback", "form", "survey", "find", "questions", "length", "debugLogDumpKey", "includeLogs", "size", "serialize", "question", "$survey_id", "$survey_questions", "message", "debug_log_dump_key", "Effect", "Event", "scheduleTaskInterval", "DeviceKind", "Context", "invariant", "log", "ConnectionState", "Platform", "SPACE_METRICS_MIN_INTERVAL", "NETWORK_METRICS_MIN_INTERVAL", "RUNTIME_METRICS_MIN_INTERVAL", "identityProvider", "clientServices", "fn", "observability", "IdentityService", "queryIdentity", "subscribe", "idqr", "identity", "did", "identify", "setTags", "DevicesService", "queryDevices", "dqr", "devices", "length", "thisDevice", "find", "device", "kind", "CURRENT", "deviceKey", "truncate", "profile", "label", "deviceProfile", "networkMetricsProvider", "ctx", "lastNetworkStatus", "updateSignalMetrics", "debounce", "on", "signaling", "forEach", "server", "state", "metrics", "gauge", "swarmCount", "connectionStates", "Map", "set", "totalReadBufferSize", "totalWriteBufferSize", "totalChannelBufferSize", "connectionInfo", "conn", "connections", "get", "readBufferSize", "writeBufferSize", "stream", "streams", "NetworkService", "queryStatus", "networkStatus", "emit", "dispose", "runtimeMetricsProvider", "platform", "promise", "SystemService", "getPlatform", "platformType", "PLATFORM_TYPE", "type", "toLowerCase", "arch", "runtime", "name", "memory", "window", "performance", "totalJSHeapSize", "usedJSHeapSize", "jsHeapSizeLimit", "then", "rss", "heapTotal", "heapUsed", "catch", "error", "spacesMetricsProvider", "client", "spaces", "subscriptions", "onDispose", "subscription", "unsubscribe", "updateSpaceMetrics", "data", "mapSpaces", "truncateKeys", "members", "key", "objects", "epoch", "currentDataMutations", "subscribeToSpaceUpdate", "space", "pipeline", "next", "id", "filter", "has", "options", "verbose", "map", "open", "ready", "internal", "startup", "getTime", "startDataMutations", "currentEpoch", "subject", "assertion", "timeframe", "totalMessages", "number", "currentDataTimeframe", "totalDataMutations", "targetDataTimeframe", "isOpen", "db", "coreDatabase", "getAllObjectIds", "progress", "Math", "min", "abs", "toFixed", "FetchHttpClient", "HttpClient", "HttpClientRequest", "Effect", "Schema", "localForage", "log", "IP_DATA_CACHE_TIMEOUT", "IPData", "Struct", "city", "String", "region", "country", "latitude", "optional", "Number", "longitude", "getIPData", "fn", "config", "httpClient", "httpClientNoTrace", "pipe", "withTracerDisabledWhen", "cachedData", "promise", "getItem", "timestamp", "Date", "now", "data", "IPDATA_API_KEY", "get", "execute", "flatMap", "res", "json", "decodeUnknown", "setItem", "provider", "observability", "gen", "ipData", "setTags", "provide", "layer", "catchAll", "err", "sync", "verbose", "provider", "Duration", "Effect", "Fiber", "Schedule", "provider", "fn", "observability", "navigator", "storage", "estimate", "action", "gen", "storageEstimate", "tryPromise", "usage", "metrics", "gauge", "quota", "fiber", "pipe", "repeat", "fixed", "hours", "runFork", "runSync", "interrupt"]
7
7
  }