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