@fluidframework/telemetry-utils 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258
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/.eslintrc.js +2 -1
- package/CHANGELOG.md +126 -0
- package/README.md +4 -3
- package/dist/config.d.ts +4 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +36 -38
- package/dist/config.js.map +1 -1
- package/dist/error.d.ts +92 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +133 -0
- package/dist/error.js.map +1 -0
- package/dist/errorLogging.d.ts +44 -19
- package/dist/errorLogging.d.ts.map +1 -1
- package/dist/errorLogging.js +70 -31
- package/dist/errorLogging.js.map +1 -1
- package/dist/eventEmitterWithErrorHandling.d.ts +3 -3
- package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
- package/dist/eventEmitterWithErrorHandling.js +10 -3
- package/dist/eventEmitterWithErrorHandling.js.map +1 -1
- package/dist/events.d.ts +1 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/fluidErrorBase.d.ts +49 -16
- package/dist/fluidErrorBase.d.ts.map +1 -1
- package/dist/fluidErrorBase.js +21 -14
- package/dist/fluidErrorBase.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -8
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +98 -60
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +193 -124
- package/dist/logger.js.map +1 -1
- package/dist/mockLogger.d.ts +17 -8
- package/dist/mockLogger.d.ts.map +1 -1
- package/dist/mockLogger.js +49 -28
- package/dist/mockLogger.js.map +1 -1
- package/dist/sampledTelemetryHelper.d.ts +9 -8
- package/dist/sampledTelemetryHelper.d.ts.map +1 -1
- package/dist/sampledTelemetryHelper.js +21 -16
- package/dist/sampledTelemetryHelper.js.map +1 -1
- package/dist/telemetryTypes.d.ts +20 -6
- package/dist/telemetryTypes.d.ts.map +1 -1
- package/dist/telemetryTypes.js.map +1 -1
- package/dist/thresholdCounter.d.ts.map +1 -1
- package/dist/thresholdCounter.js.map +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -2
- package/dist/utils.js.map +1 -1
- package/lib/config.d.ts +4 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +34 -37
- package/lib/config.js.map +1 -1
- package/lib/error.d.ts +92 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +125 -0
- package/lib/error.js.map +1 -0
- package/lib/errorLogging.d.ts +44 -19
- package/lib/errorLogging.d.ts.map +1 -1
- package/lib/errorLogging.js +69 -31
- package/lib/errorLogging.js.map +1 -1
- package/lib/eventEmitterWithErrorHandling.d.ts +3 -3
- package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
- package/lib/eventEmitterWithErrorHandling.js +9 -2
- package/lib/eventEmitterWithErrorHandling.js.map +1 -1
- package/lib/events.d.ts +1 -1
- package/lib/events.d.ts.map +1 -1
- package/lib/events.js.map +1 -1
- package/lib/fluidErrorBase.d.ts +49 -16
- package/lib/fluidErrorBase.d.ts.map +1 -1
- package/lib/fluidErrorBase.js +21 -14
- package/lib/fluidErrorBase.js.map +1 -1
- package/lib/index.d.ts +5 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -4
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +98 -60
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +184 -119
- package/lib/logger.js.map +1 -1
- package/lib/mockLogger.d.ts +17 -8
- package/lib/mockLogger.d.ts.map +1 -1
- package/lib/mockLogger.js +50 -29
- package/lib/mockLogger.js.map +1 -1
- package/lib/sampledTelemetryHelper.d.ts +9 -8
- package/lib/sampledTelemetryHelper.d.ts.map +1 -1
- package/lib/sampledTelemetryHelper.js +19 -14
- package/lib/sampledTelemetryHelper.js.map +1 -1
- package/lib/telemetryTypes.d.ts +20 -6
- package/lib/telemetryTypes.d.ts.map +1 -1
- package/lib/telemetryTypes.js.map +1 -1
- package/lib/thresholdCounter.d.ts.map +1 -1
- package/lib/thresholdCounter.js.map +1 -1
- package/lib/utils.d.ts +3 -3
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -2
- package/lib/utils.js.map +1 -1
- package/package.json +21 -44
- package/src/config.ts +25 -15
- package/src/error.ts +202 -0
- package/src/errorLogging.ts +102 -57
- package/src/eventEmitterWithErrorHandling.ts +5 -3
- package/src/events.ts +3 -3
- package/src/fluidErrorBase.ts +63 -27
- package/src/index.ts +17 -6
- package/src/logger.ts +291 -121
- package/src/mockLogger.ts +65 -24
- package/src/sampledTelemetryHelper.ts +20 -16
- package/src/telemetryTypes.ts +29 -6
- package/src/thresholdCounter.ts +2 -2
- package/src/utils.ts +3 -3
- package/dist/debugLogger.d.ts +0 -39
- package/dist/debugLogger.d.ts.map +0 -1
- package/dist/debugLogger.js +0 -112
- package/dist/debugLogger.js.map +0 -1
- package/lib/debugLogger.d.ts +0 -39
- package/lib/debugLogger.d.ts.map +0 -1
- package/lib/debugLogger.js +0 -108
- package/lib/debugLogger.js.map +0 -1
- package/src/debugLogger.ts +0 -143
package/lib/logger.js
CHANGED
|
@@ -2,18 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
8
|
-
t[p] = s[p];
|
|
9
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
10
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
11
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
12
|
-
t[p[i]] = s[p[i]];
|
|
13
|
-
}
|
|
14
|
-
return t;
|
|
15
|
-
};
|
|
16
|
-
import { performance } from "@fluidframework/common-utils";
|
|
5
|
+
import { LogLevel, } from "@fluidframework/core-interfaces";
|
|
6
|
+
import { performance } from "@fluid-internal/client-utils";
|
|
17
7
|
import { CachedConfigProvider, loggerIsMonitoringContext, mixinMonitoringContext } from "./config";
|
|
18
8
|
import { isILoggingError, extractLogSafeErrorProperties, generateStack, isTaggedTelemetryPropertyValue, } from "./errorLogging";
|
|
19
9
|
/**
|
|
@@ -22,11 +12,33 @@ import { isILoggingError, extractLogSafeErrorProperties, generateStack, isTagged
|
|
|
22
12
|
*/
|
|
23
13
|
export var TelemetryDataTag;
|
|
24
14
|
(function (TelemetryDataTag) {
|
|
25
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Data containing terms or IDs from code packages that may have been dynamically loaded
|
|
17
|
+
*/
|
|
26
18
|
TelemetryDataTag["CodeArtifact"] = "CodeArtifact";
|
|
27
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Personal data of a variety of classifications that pertains to the user
|
|
21
|
+
*/
|
|
28
22
|
TelemetryDataTag["UserData"] = "UserData";
|
|
29
23
|
})(TelemetryDataTag || (TelemetryDataTag = {}));
|
|
24
|
+
/**
|
|
25
|
+
* Attempts to parse number from string.
|
|
26
|
+
* If fails,returns original string.
|
|
27
|
+
* Used to make telemetry data typed (and support math operations, like comparison),
|
|
28
|
+
* in places where we do expect numbers (like contentsize/duration property in http header)
|
|
29
|
+
*/
|
|
30
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
31
|
+
export function numberFromString(str) {
|
|
32
|
+
if (str === undefined || str === null) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const num = Number(str);
|
|
36
|
+
return Number.isNaN(num) ? str : num;
|
|
37
|
+
}
|
|
38
|
+
export function formatTick(tick) {
|
|
39
|
+
return Math.floor(tick);
|
|
40
|
+
}
|
|
41
|
+
export const eventNamespaceSeparator = ":";
|
|
30
42
|
/**
|
|
31
43
|
* TelemetryLogger class contains various helper telemetry methods,
|
|
32
44
|
* encoding in one place schemas for various types of Fluid telemetry events.
|
|
@@ -37,22 +49,6 @@ export class TelemetryLogger {
|
|
|
37
49
|
this.namespace = namespace;
|
|
38
50
|
this.properties = properties;
|
|
39
51
|
}
|
|
40
|
-
static formatTick(tick) {
|
|
41
|
-
return Math.floor(tick);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Attempts to parse number from string.
|
|
45
|
-
* If fails,returns original string.
|
|
46
|
-
* Used to make telemetry data typed (and support math operations, like comparison),
|
|
47
|
-
* in places where we do expect numbers (like contentsize/duration property in http header)
|
|
48
|
-
*/
|
|
49
|
-
static numberFromString(str) {
|
|
50
|
-
if (str === undefined || str === null) {
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
const num = Number(str);
|
|
54
|
-
return Number.isNaN(num) ? str : num;
|
|
55
|
-
}
|
|
56
52
|
static sanitizePkgName(name) {
|
|
57
53
|
return name.replace("@", "").replace("/", "-");
|
|
58
54
|
}
|
|
@@ -90,27 +86,29 @@ export class TelemetryLogger {
|
|
|
90
86
|
*
|
|
91
87
|
* @param event - the event to send
|
|
92
88
|
* @param error - optional error object to log
|
|
89
|
+
* @param logLevel - optional level of the log. It category of event is set as error,
|
|
90
|
+
* then the logLevel will be upgraded to be an error.
|
|
93
91
|
*/
|
|
94
|
-
sendTelemetryEvent(event, error) {
|
|
95
|
-
|
|
96
|
-
this.sendTelemetryEventCore(Object.assign(Object.assign({}, event), { category: (_a = event.category) !== null && _a !== void 0 ? _a : "generic" }), error);
|
|
92
|
+
sendTelemetryEvent(event, error, logLevel = LogLevel.default) {
|
|
93
|
+
this.sendTelemetryEventCore({ ...event, category: event.category ?? "generic" }, error, event.category === "error" ? LogLevel.error : logLevel);
|
|
97
94
|
}
|
|
98
95
|
/**
|
|
99
96
|
* Send a telemetry event with the logger
|
|
100
97
|
*
|
|
101
98
|
* @param event - the event to send
|
|
102
99
|
* @param error - optional error object to log
|
|
100
|
+
* @param logLevel - optional level of the log.
|
|
103
101
|
*/
|
|
104
|
-
sendTelemetryEventCore(event, error) {
|
|
102
|
+
sendTelemetryEventCore(event, error, logLevel) {
|
|
105
103
|
const newEvent = convertToBaseEvent(event);
|
|
106
104
|
if (error !== undefined) {
|
|
107
105
|
TelemetryLogger.prepareErrorObject(newEvent, error, false);
|
|
108
106
|
}
|
|
109
107
|
// Will include Nan & Infinity, but probably we do not care
|
|
110
108
|
if (typeof newEvent.duration === "number") {
|
|
111
|
-
newEvent.duration =
|
|
109
|
+
newEvent.duration = formatTick(newEvent.duration);
|
|
112
110
|
}
|
|
113
|
-
this.send(newEvent);
|
|
111
|
+
this.send(newEvent, logLevel);
|
|
114
112
|
}
|
|
115
113
|
/**
|
|
116
114
|
* Send an error telemetry event with the logger
|
|
@@ -119,28 +117,41 @@ export class TelemetryLogger {
|
|
|
119
117
|
* @param error - optional error object to log
|
|
120
118
|
*/
|
|
121
119
|
sendErrorEvent(event, error) {
|
|
122
|
-
this.sendTelemetryEventCore(
|
|
120
|
+
this.sendTelemetryEventCore({
|
|
123
121
|
// ensure the error field has some value,
|
|
124
122
|
// this can and will be overridden by event, or error
|
|
125
|
-
error: event.eventName
|
|
123
|
+
error: event.eventName,
|
|
124
|
+
...event,
|
|
125
|
+
category: "error",
|
|
126
|
+
}, error, LogLevel.error);
|
|
126
127
|
}
|
|
127
128
|
/**
|
|
128
129
|
* Send a performance telemetry event with the logger
|
|
129
130
|
*
|
|
130
131
|
* @param event - Event to send
|
|
131
132
|
* @param error - optional error object to log
|
|
133
|
+
* @param logLevel - optional level of the log. It category of event is set as error,
|
|
134
|
+
* then the logLevel will be upgraded to be an error.
|
|
132
135
|
*/
|
|
133
|
-
sendPerformanceEvent(event, error) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
sendPerformanceEvent(event, error, logLevel = LogLevel.default) {
|
|
137
|
+
const perfEvent = {
|
|
138
|
+
...event,
|
|
139
|
+
category: event.category ?? "performance",
|
|
140
|
+
};
|
|
141
|
+
this.sendTelemetryEventCore(perfEvent, error, perfEvent.category === "error" ? LogLevel.error : logLevel);
|
|
137
142
|
}
|
|
138
143
|
prepareEvent(event) {
|
|
139
144
|
const includeErrorProps = event.category === "error" || event.error !== undefined;
|
|
140
|
-
const newEvent =
|
|
145
|
+
const newEvent = {
|
|
146
|
+
...event,
|
|
147
|
+
};
|
|
141
148
|
if (this.namespace !== undefined) {
|
|
142
149
|
newEvent.eventName = `${this.namespace}${TelemetryLogger.eventNamespaceSeparator}${newEvent.eventName}`;
|
|
143
150
|
}
|
|
151
|
+
return this.extendProperties(newEvent, includeErrorProps);
|
|
152
|
+
}
|
|
153
|
+
extendProperties(toExtend, includeErrorProps) {
|
|
154
|
+
const eventLike = toExtend;
|
|
144
155
|
if (this.properties) {
|
|
145
156
|
const properties = [];
|
|
146
157
|
properties.push(this.properties.all);
|
|
@@ -150,23 +161,23 @@ export class TelemetryLogger {
|
|
|
150
161
|
for (const props of properties) {
|
|
151
162
|
if (props !== undefined) {
|
|
152
163
|
for (const key of Object.keys(props)) {
|
|
153
|
-
if (
|
|
164
|
+
if (eventLike[key] !== undefined) {
|
|
154
165
|
continue;
|
|
155
166
|
}
|
|
156
167
|
const getterOrValue = props[key];
|
|
157
168
|
// If this throws, hopefully it is handled elsewhere
|
|
158
169
|
const value = typeof getterOrValue === "function" ? getterOrValue() : getterOrValue;
|
|
159
170
|
if (value !== undefined) {
|
|
160
|
-
|
|
171
|
+
eventLike[key] = value;
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
174
|
}
|
|
164
175
|
}
|
|
165
176
|
}
|
|
166
|
-
return
|
|
177
|
+
return toExtend;
|
|
167
178
|
}
|
|
168
179
|
}
|
|
169
|
-
TelemetryLogger.eventNamespaceSeparator =
|
|
180
|
+
TelemetryLogger.eventNamespaceSeparator = eventNamespaceSeparator;
|
|
170
181
|
/**
|
|
171
182
|
* @deprecated 0.56, remove TaggedLoggerAdapter once its usage is removed from
|
|
172
183
|
* container-runtime. Issue: #8191
|
|
@@ -176,6 +187,9 @@ export class TaggedLoggerAdapter {
|
|
|
176
187
|
constructor(logger) {
|
|
177
188
|
this.logger = logger;
|
|
178
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* {@inheritDoc @fluidframework/core-interfaces#ITelemetryBaseLogger.send}
|
|
192
|
+
*/
|
|
179
193
|
send(eventWithTagsMaybe) {
|
|
180
194
|
const newEvent = {
|
|
181
195
|
category: eventWithTagsMaybe.category,
|
|
@@ -212,6 +226,16 @@ export class TaggedLoggerAdapter {
|
|
|
212
226
|
this.logger.send(newEvent);
|
|
213
227
|
}
|
|
214
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Create a child logger based on the provided props object
|
|
231
|
+
* @param props - logger is the base logger the child will log to after it's processing, namespace will be prefixed to all event names, properties are default properties that will be applied events.
|
|
232
|
+
*
|
|
233
|
+
* @remarks
|
|
234
|
+
* Passing in no props object (i.e. undefined) will return a logger that is effectively a no-op.
|
|
235
|
+
*/
|
|
236
|
+
export function createChildLogger(props) {
|
|
237
|
+
return ChildLogger.create(props?.logger, props?.namespace, props?.properties);
|
|
238
|
+
}
|
|
215
239
|
/**
|
|
216
240
|
* ChildLogger class contains various helper telemetry methods,
|
|
217
241
|
* encoding in one place schemas for various types of Fluid telemetry events.
|
|
@@ -241,10 +265,16 @@ export class ChildLogger extends TelemetryLogger {
|
|
|
241
265
|
for (const extendedProps of [baseLogger.properties, properties]) {
|
|
242
266
|
if (extendedProps !== undefined) {
|
|
243
267
|
if (extendedProps.all !== undefined) {
|
|
244
|
-
combinedProperties.all =
|
|
268
|
+
combinedProperties.all = {
|
|
269
|
+
...combinedProperties.all,
|
|
270
|
+
...extendedProps.all,
|
|
271
|
+
};
|
|
245
272
|
}
|
|
246
273
|
if (extendedProps.error !== undefined) {
|
|
247
|
-
combinedProperties.error =
|
|
274
|
+
combinedProperties.error = {
|
|
275
|
+
...combinedProperties.error,
|
|
276
|
+
...extendedProps.error,
|
|
277
|
+
};
|
|
248
278
|
}
|
|
249
279
|
}
|
|
250
280
|
}
|
|
@@ -253,19 +283,43 @@ export class ChildLogger extends TelemetryLogger {
|
|
|
253
283
|
: namespace === undefined
|
|
254
284
|
? baseLogger.namespace
|
|
255
285
|
: `${baseLogger.namespace}${TelemetryLogger.eventNamespaceSeparator}${namespace}`;
|
|
256
|
-
|
|
286
|
+
const child = new ChildLogger(baseLogger.baseLogger, combinedNamespace, combinedProperties);
|
|
287
|
+
if (!loggerIsMonitoringContext(child) && loggerIsMonitoringContext(baseLogger)) {
|
|
288
|
+
mixinMonitoringContext(child, baseLogger.config);
|
|
289
|
+
}
|
|
290
|
+
return child;
|
|
257
291
|
}
|
|
258
|
-
return new ChildLogger(baseLogger ? baseLogger :
|
|
292
|
+
return new ChildLogger(baseLogger ? baseLogger : { send() { } }, namespace, properties);
|
|
293
|
+
}
|
|
294
|
+
get minLogLevel() {
|
|
295
|
+
return this.baseLogger.minLogLevel;
|
|
296
|
+
}
|
|
297
|
+
shouldFilterOutEvent(event, logLevel) {
|
|
298
|
+
const eventLogLevel = logLevel ?? LogLevel.default;
|
|
299
|
+
const configLogLevel = this.baseLogger.minLogLevel ?? LogLevel.default;
|
|
300
|
+
// Filter out in case event log level is below what is wanted in config.
|
|
301
|
+
return eventLogLevel < configLogLevel;
|
|
259
302
|
}
|
|
260
303
|
/**
|
|
261
304
|
* Send an event with the logger
|
|
262
305
|
*
|
|
263
306
|
* @param event - the event to send
|
|
264
307
|
*/
|
|
265
|
-
send(event) {
|
|
266
|
-
|
|
308
|
+
send(event, logLevel) {
|
|
309
|
+
if (this.shouldFilterOutEvent(event, logLevel)) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
this.baseLogger.send(this.prepareEvent(event), logLevel);
|
|
267
313
|
}
|
|
268
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Create a logger which logs to multiple other loggers based on the provided props object
|
|
317
|
+
* @param props - loggers are the base loggers that will logged to after it's processing, namespace will be prefixed to all event names, properties are default properties that will be applied events.
|
|
318
|
+
* tryInheritProperties will attempted to copy those loggers properties to this loggers if they are of a known type e.g. one from this package
|
|
319
|
+
*/
|
|
320
|
+
export function createMultiSinkLogger(props) {
|
|
321
|
+
return new MultiSinkLogger(props.namespace, props.properties, props.loggers?.filter((l) => l !== undefined), props.tryInheritProperties);
|
|
322
|
+
}
|
|
269
323
|
/**
|
|
270
324
|
* Multi-sink logger
|
|
271
325
|
* Takes multiple ITelemetryBaseLogger objects (sinks) and logs all events into each sink
|
|
@@ -275,10 +329,41 @@ export class MultiSinkLogger extends TelemetryLogger {
|
|
|
275
329
|
* Create multiple sink logger (i.e. logger that sends events to multiple sinks)
|
|
276
330
|
* @param namespace - Telemetry event name prefix to add to all events
|
|
277
331
|
* @param properties - Base properties to add to all events
|
|
332
|
+
* @param loggers - The list of loggers to use as sinks
|
|
333
|
+
* @param tryInheritProperties - Will attempted to copy those loggers properties to this loggers if they are of a known type e.g. one from this package
|
|
278
334
|
*/
|
|
279
|
-
constructor(namespace, properties) {
|
|
280
|
-
|
|
281
|
-
|
|
335
|
+
constructor(namespace, properties, loggers = [], tryInheritProperties) {
|
|
336
|
+
let realProperties = properties !== undefined ? { ...properties } : undefined;
|
|
337
|
+
if (tryInheritProperties === true) {
|
|
338
|
+
const merge = (realProperties ?? (realProperties = {}));
|
|
339
|
+
loggers
|
|
340
|
+
.filter((l) => l instanceof TelemetryLogger)
|
|
341
|
+
.map((l) => l.properties ?? {})
|
|
342
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
343
|
+
.forEach((cv) => {
|
|
344
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
345
|
+
Object.keys(cv).forEach((k) => {
|
|
346
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
347
|
+
merge[k] = { ...cv[k], ...merge?.[k] };
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
super(namespace, realProperties);
|
|
352
|
+
this.loggers = loggers;
|
|
353
|
+
this._minLogLevelOfAllLoggers = LogLevel.default;
|
|
354
|
+
this.calculateMinLogLevel();
|
|
355
|
+
}
|
|
356
|
+
get minLogLevel() {
|
|
357
|
+
return this._minLogLevelOfAllLoggers;
|
|
358
|
+
}
|
|
359
|
+
calculateMinLogLevel() {
|
|
360
|
+
if (this.loggers.length > 0) {
|
|
361
|
+
const logLevels = [];
|
|
362
|
+
for (const logger of this.loggers) {
|
|
363
|
+
logLevels.push(logger.minLogLevel ?? LogLevel.default);
|
|
364
|
+
}
|
|
365
|
+
this._minLogLevelOfAllLoggers = Math.min(...logLevels);
|
|
366
|
+
}
|
|
282
367
|
}
|
|
283
368
|
/**
|
|
284
369
|
* Add logger to send all events to
|
|
@@ -287,6 +372,8 @@ export class MultiSinkLogger extends TelemetryLogger {
|
|
|
287
372
|
addLogger(logger) {
|
|
288
373
|
if (logger !== undefined && logger !== null) {
|
|
289
374
|
this.loggers.push(logger);
|
|
375
|
+
// Update in case the logLevel of added logger is less than the current.
|
|
376
|
+
this.calculateMinLogLevel();
|
|
290
377
|
}
|
|
291
378
|
}
|
|
292
379
|
/**
|
|
@@ -296,9 +383,9 @@ export class MultiSinkLogger extends TelemetryLogger {
|
|
|
296
383
|
*/
|
|
297
384
|
send(event) {
|
|
298
385
|
const newEvent = this.prepareEvent(event);
|
|
299
|
-
this.loggers
|
|
386
|
+
for (const logger of this.loggers) {
|
|
300
387
|
logger.send(newEvent);
|
|
301
|
-
}
|
|
388
|
+
}
|
|
302
389
|
}
|
|
303
390
|
}
|
|
304
391
|
/**
|
|
@@ -306,17 +393,17 @@ export class MultiSinkLogger extends TelemetryLogger {
|
|
|
306
393
|
*/
|
|
307
394
|
export class PerformanceEvent {
|
|
308
395
|
constructor(logger, event, markers = { end: true, cancel: "generic" }, recordHeapSize = false) {
|
|
309
|
-
var _a;
|
|
310
396
|
this.logger = logger;
|
|
311
397
|
this.markers = markers;
|
|
312
398
|
this.recordHeapSize = recordHeapSize;
|
|
313
399
|
this.startTime = performance.now();
|
|
314
400
|
this.startMemoryCollection = 0;
|
|
315
|
-
this.event =
|
|
401
|
+
this.event = { ...event };
|
|
316
402
|
if (this.markers.start) {
|
|
317
403
|
this.reportEvent("start");
|
|
318
404
|
}
|
|
319
|
-
|
|
405
|
+
// eslint-disable-next-line unicorn/no-null
|
|
406
|
+
if (typeof window === "object" && window != null && window.performance?.mark) {
|
|
320
407
|
this.startMark = `${event.eventName}-start`;
|
|
321
408
|
window.performance.mark(this.startMark);
|
|
322
409
|
}
|
|
@@ -377,7 +464,7 @@ export class PerformanceEvent {
|
|
|
377
464
|
}
|
|
378
465
|
cancel(props, error) {
|
|
379
466
|
if (this.markers.cancel !== undefined) {
|
|
380
|
-
this.reportEvent("cancel",
|
|
467
|
+
this.reportEvent("cancel", { category: this.markers.cancel, ...props }, error);
|
|
381
468
|
}
|
|
382
469
|
this.event = undefined;
|
|
383
470
|
}
|
|
@@ -385,19 +472,19 @@ export class PerformanceEvent {
|
|
|
385
472
|
* Report the event, if it hasn't already been reported.
|
|
386
473
|
*/
|
|
387
474
|
reportEvent(eventNameSuffix, props, error) {
|
|
388
|
-
var _a, _b, _c, _d;
|
|
389
475
|
// There are strange sequences involving multiple Promise chains
|
|
390
476
|
// where the event can be cancelled and then later a callback is invoked
|
|
391
477
|
// and the caller attempts to end directly, e.g. issue #3936. Just return.
|
|
392
478
|
if (!this.event) {
|
|
393
479
|
return;
|
|
394
480
|
}
|
|
395
|
-
const event =
|
|
481
|
+
const event = { ...this.event, ...props };
|
|
396
482
|
event.eventName = `${event.eventName}_${eventNameSuffix}`;
|
|
397
483
|
if (eventNameSuffix !== "start") {
|
|
398
484
|
event.duration = this.duration;
|
|
399
485
|
if (this.startMemoryCollection) {
|
|
400
|
-
const currentMemory =
|
|
486
|
+
const currentMemory = performance?.memory
|
|
487
|
+
?.usedJSHeapSize;
|
|
401
488
|
const differenceInKBytes = Math.floor((currentMemory - this.startMemoryCollection) / 1024);
|
|
402
489
|
if (differenceInKBytes > 0) {
|
|
403
490
|
event.usedJSHeapSize = differenceInKBytes;
|
|
@@ -405,61 +492,17 @@ export class PerformanceEvent {
|
|
|
405
492
|
}
|
|
406
493
|
}
|
|
407
494
|
else if (this.recordHeapSize) {
|
|
408
|
-
this.startMemoryCollection =
|
|
495
|
+
this.startMemoryCollection = performance?.memory?.usedJSHeapSize;
|
|
409
496
|
}
|
|
410
497
|
this.logger.sendPerformanceEvent(event, error);
|
|
411
498
|
}
|
|
412
499
|
}
|
|
413
500
|
/**
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
sendTelemetryEvent(event, error) { }
|
|
420
|
-
sendErrorEvent(event, error) {
|
|
421
|
-
this.reportError("errorEvent in UT logger!", event, error);
|
|
422
|
-
}
|
|
423
|
-
sendPerformanceEvent(event, error) { }
|
|
424
|
-
logGenericError(eventName, error) {
|
|
425
|
-
this.reportError(`genericError in UT logger!`, { eventName }, error);
|
|
426
|
-
}
|
|
427
|
-
logException(event, exception) {
|
|
428
|
-
this.reportError("exception in UT logger!", event, exception);
|
|
429
|
-
}
|
|
430
|
-
debugAssert(condition, event) {
|
|
431
|
-
this.reportError("debugAssert in UT logger!");
|
|
432
|
-
}
|
|
433
|
-
shipAssert(condition, event) {
|
|
434
|
-
this.reportError("shipAssert in UT logger!");
|
|
435
|
-
}
|
|
436
|
-
reportError(message, event, err) {
|
|
437
|
-
const error = new Error(message);
|
|
438
|
-
error.error = error;
|
|
439
|
-
error.event = event;
|
|
440
|
-
// report to console as exception can be eaten
|
|
441
|
-
console.error(message);
|
|
442
|
-
console.error(error);
|
|
443
|
-
throw error;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Null logger
|
|
448
|
-
* It can be used in places where logger instance is required, but events should be not send over.
|
|
449
|
-
*/
|
|
450
|
-
export class BaseTelemetryNullLogger {
|
|
451
|
-
/**
|
|
452
|
-
* Send an event with the logger
|
|
453
|
-
*
|
|
454
|
-
* @param event - the event to send
|
|
455
|
-
*/
|
|
456
|
-
send(event) {
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Null logger
|
|
462
|
-
* It can be used in places where logger instance is required, but events should be not send over.
|
|
501
|
+
* Null logger that no-ops for all telemetry events passed to it.
|
|
502
|
+
* @deprecated - This will be removed in a future release.
|
|
503
|
+
* For internal use within the FluidFramework codebase, use {@link createChildLogger} with no arguments instead.
|
|
504
|
+
* For external consumers we recommend writing a trivial implementation of {@link @fluidframework/core-interfaces#ITelemetryBaseLogger}
|
|
505
|
+
* where the send() method does nothing and using that.
|
|
463
506
|
*/
|
|
464
507
|
export class TelemetryNullLogger {
|
|
465
508
|
send(event) { }
|
|
@@ -472,8 +515,7 @@ export class TelemetryNullLogger {
|
|
|
472
515
|
* In the case of an invalid property type, the value will be converted to an error string.
|
|
473
516
|
* @param event - Event with fields you want to stringify.
|
|
474
517
|
*/
|
|
475
|
-
function convertToBaseEvent(
|
|
476
|
-
var { category, eventName } = _a, props = __rest(_a, ["category", "eventName"]);
|
|
518
|
+
function convertToBaseEvent({ category, eventName, ...props }) {
|
|
477
519
|
const newEvent = { category, eventName };
|
|
478
520
|
for (const key of Object.keys(props)) {
|
|
479
521
|
newEvent[key] = convertToBasePropertyType(props[key]);
|
|
@@ -483,8 +525,8 @@ function convertToBaseEvent(_a) {
|
|
|
483
525
|
/**
|
|
484
526
|
* Takes in value, and does one of 4 things.
|
|
485
527
|
* if value is of primitive type - returns the original value.
|
|
486
|
-
* If the value is
|
|
487
|
-
* If the value is an object of type
|
|
528
|
+
* If the value is a flat array or object - returns a stringified version of the array/object.
|
|
529
|
+
* If the value is an object of type Tagged<TelemetryEventPropertyType> - returns the object
|
|
488
530
|
* with its values recursively converted to base property Type.
|
|
489
531
|
* If none of these cases are reached - returns an error string
|
|
490
532
|
* @param x - value passed in to convert to a base property type
|
|
@@ -513,4 +555,27 @@ function convertToBasePropertyTypeUntagged(x) {
|
|
|
513
555
|
return `INVALID PROPERTY (typed as ${typeof x})`;
|
|
514
556
|
}
|
|
515
557
|
}
|
|
558
|
+
export const tagData = (tag, values) =>
|
|
559
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
560
|
+
Object.entries(values)
|
|
561
|
+
.filter((e) => e[1] !== undefined)
|
|
562
|
+
// eslint-disable-next-line unicorn/no-array-reduce, unicorn/prefer-object-from-entries
|
|
563
|
+
.reduce((pv, cv) => {
|
|
564
|
+
const [key, value] = cv;
|
|
565
|
+
if (typeof value === "function") {
|
|
566
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
567
|
+
pv[key] = () => {
|
|
568
|
+
return { tag, value: value() };
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
pv[key] = { tag, value };
|
|
573
|
+
}
|
|
574
|
+
return pv;
|
|
575
|
+
}, {});
|
|
576
|
+
/**
|
|
577
|
+
* Helper function to tag telemetry properties as CodeArtifacts. It supports properties of type
|
|
578
|
+
* TelemetryBaseEventPropertyType as well as getters that return TelemetryBaseEventPropertyType.
|
|
579
|
+
*/
|
|
580
|
+
export const tagCodeArtifacts = (values) => tagData(TelemetryDataTag.CodeArtifact, values);
|
|
516
581
|
//# sourceMappingURL=logger.js.map
|