@fluidframework/telemetry-utils 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.225277
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 +12 -13
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +249 -0
- package/README.md +68 -1
- package/api-extractor-esm.json +5 -0
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/telemetry-utils.api.md +444 -0
- package/dist/config.d.ts +47 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +88 -38
- package/dist/config.js.map +1 -1
- package/dist/error.d.ts +112 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +159 -0
- package/dist/error.js.map +1 -0
- package/dist/errorLogging.d.ts +86 -20
- package/dist/errorLogging.d.ts.map +1 -1
- package/dist/errorLogging.js +190 -60
- package/dist/errorLogging.js.map +1 -1
- package/dist/eventEmitterWithErrorHandling.d.ts +9 -3
- package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
- package/dist/eventEmitterWithErrorHandling.js +16 -3
- package/dist/eventEmitterWithErrorHandling.js.map +1 -1
- package/dist/events.d.ts +27 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +26 -2
- package/dist/events.js.map +1 -1
- package/dist/fluidErrorBase.d.ts +57 -16
- package/dist/fluidErrorBase.d.ts.map +1 -1
- package/dist/fluidErrorBase.js +27 -14
- package/dist/fluidErrorBase.js.map +1 -1
- package/dist/index.d.ts +12 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -21
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +269 -53
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +423 -132
- package/dist/logger.js.map +1 -1
- package/dist/mockLogger.d.ts +39 -12
- package/dist/mockLogger.d.ts.map +1 -1
- package/dist/mockLogger.js +105 -22
- package/dist/mockLogger.js.map +1 -1
- package/dist/sampledTelemetryHelper.d.ts +18 -12
- package/dist/sampledTelemetryHelper.d.ts.map +1 -1
- package/dist/sampledTelemetryHelper.js +28 -19
- package/dist/sampledTelemetryHelper.js.map +1 -1
- package/dist/telemetry-utils-alpha.d.ts +290 -0
- package/dist/telemetry-utils-beta.d.ts +264 -0
- package/dist/telemetry-utils-public.d.ts +264 -0
- package/dist/telemetry-utils-untrimmed.d.ts +1102 -0
- package/dist/telemetryTypes.d.ts +115 -0
- package/dist/telemetryTypes.d.ts.map +1 -0
- package/dist/telemetryTypes.js +7 -0
- package/dist/telemetryTypes.js.map +1 -0
- package/dist/thresholdCounter.d.ts +6 -5
- package/dist/thresholdCounter.d.ts.map +1 -1
- package/dist/thresholdCounter.js +4 -3
- package/dist/thresholdCounter.js.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/utils.d.ts +54 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +58 -3
- package/dist/utils.js.map +1 -1
- package/lib/config.d.ts +47 -16
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +85 -36
- package/lib/config.js.map +1 -1
- package/lib/error.d.ts +112 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +150 -0
- package/lib/error.js.map +1 -0
- package/lib/errorLogging.d.ts +86 -20
- package/lib/errorLogging.d.ts.map +1 -1
- package/lib/errorLogging.js +189 -60
- package/lib/errorLogging.js.map +1 -1
- package/lib/eventEmitterWithErrorHandling.d.ts +9 -3
- package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
- package/lib/eventEmitterWithErrorHandling.js +15 -2
- package/lib/eventEmitterWithErrorHandling.js.map +1 -1
- package/lib/events.d.ts +27 -3
- package/lib/events.d.ts.map +1 -1
- package/lib/events.js +26 -2
- package/lib/events.js.map +1 -1
- package/lib/fluidErrorBase.d.ts +57 -16
- package/lib/fluidErrorBase.d.ts.map +1 -1
- package/lib/fluidErrorBase.js +27 -14
- package/lib/fluidErrorBase.js.map +1 -1
- package/lib/index.d.ts +12 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +11 -11
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +269 -53
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +415 -131
- package/lib/logger.js.map +1 -1
- package/lib/mockLogger.d.ts +39 -12
- package/lib/mockLogger.d.ts.map +1 -1
- package/lib/mockLogger.js +106 -23
- package/lib/mockLogger.js.map +1 -1
- package/lib/sampledTelemetryHelper.d.ts +18 -12
- package/lib/sampledTelemetryHelper.d.ts.map +1 -1
- package/lib/sampledTelemetryHelper.js +26 -17
- package/lib/sampledTelemetryHelper.js.map +1 -1
- package/lib/telemetry-utils-alpha.d.mts +290 -0
- package/lib/telemetry-utils-beta.d.mts +264 -0
- package/lib/telemetry-utils-public.d.mts +264 -0
- package/lib/telemetry-utils-untrimmed.d.mts +1102 -0
- package/lib/telemetryTypes.d.ts +115 -0
- package/lib/telemetryTypes.d.ts.map +1 -0
- package/lib/telemetryTypes.js +6 -0
- package/lib/telemetryTypes.js.map +1 -0
- package/lib/thresholdCounter.d.ts +6 -5
- package/lib/thresholdCounter.d.ts.map +1 -1
- package/lib/thresholdCounter.js +4 -3
- package/lib/thresholdCounter.js.map +1 -1
- package/lib/utils.d.ts +54 -3
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +56 -2
- package/lib/utils.js.map +1 -1
- package/package.json +86 -57
- package/prettier.config.cjs +8 -0
- package/src/config.ts +254 -189
- package/src/error.ts +235 -0
- package/src/errorLogging.ts +440 -290
- package/src/eventEmitterWithErrorHandling.ts +26 -14
- package/src/events.ts +54 -25
- package/src/fluidErrorBase.ts +94 -46
- package/src/index.ts +76 -17
- package/src/logger.ts +972 -505
- package/src/mockLogger.ts +225 -83
- package/src/sampledTelemetryHelper.ts +136 -128
- package/src/telemetryTypes.ts +140 -0
- package/src/thresholdCounter.ts +38 -37
- package/src/utils.ts +108 -17
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/debugLogger.d.ts +0 -39
- package/dist/debugLogger.d.ts.map +0 -1
- package/dist/debugLogger.js +0 -101
- package/dist/debugLogger.js.map +0 -1
- package/dist/packageVersion.d.ts +0 -9
- package/dist/packageVersion.d.ts.map +0 -1
- package/dist/packageVersion.js +0 -12
- package/dist/packageVersion.js.map +0 -1
- package/lib/debugLogger.d.ts +0 -39
- package/lib/debugLogger.d.ts.map +0 -1
- package/lib/debugLogger.js +0 -97
- package/lib/debugLogger.js.map +0 -1
- package/lib/packageVersion.d.ts +0 -9
- package/lib/packageVersion.d.ts.map +0 -1
- package/lib/packageVersion.js +0 -9
- package/lib/packageVersion.js.map +0 -1
- package/src/debugLogger.ts +0 -126
- package/src/packageVersion.ts +0 -9
package/lib/logger.js
CHANGED
|
@@ -2,51 +2,65 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { LogLevel, } from "@fluidframework/core-interfaces";
|
|
6
|
+
import { performance } from "@fluid-internal/client-utils";
|
|
7
|
+
import { CachedConfigProvider, loggerIsMonitoringContext, mixinMonitoringContext } from "./config";
|
|
8
|
+
import { isILoggingError, extractLogSafeErrorProperties, generateStack, isTaggedTelemetryPropertyValue, } from "./errorLogging";
|
|
8
9
|
/**
|
|
9
10
|
* Broad classifications to be applied to individual properties as they're prepared to be logged to telemetry.
|
|
10
|
-
*
|
|
11
|
+
*
|
|
12
|
+
* @privateRemarks Please do not modify existing entries, to maintain backwards compatibility.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
11
15
|
*/
|
|
12
16
|
export var TelemetryDataTag;
|
|
13
17
|
(function (TelemetryDataTag) {
|
|
14
18
|
/**
|
|
15
|
-
* Data containing terms from code packages that may have been dynamically loaded
|
|
16
|
-
* @deprecated 1.0, will be removed in next release (see issue #6603). Use `TelemetryDataTag.CodeArtifact` instead.
|
|
19
|
+
* Data containing terms or IDs from code packages that may have been dynamically loaded
|
|
17
20
|
*/
|
|
18
|
-
TelemetryDataTag["PackageData"] = "PackageData";
|
|
19
|
-
/** Data containing terms or IDs from code packages that may have been dynamically loaded */
|
|
20
21
|
TelemetryDataTag["CodeArtifact"] = "CodeArtifact";
|
|
21
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Personal data of a variety of classifications that pertains to the user
|
|
24
|
+
*/
|
|
22
25
|
TelemetryDataTag["UserData"] = "UserData";
|
|
23
26
|
})(TelemetryDataTag || (TelemetryDataTag = {}));
|
|
27
|
+
/**
|
|
28
|
+
* Attempts to parse number from string.
|
|
29
|
+
* If it fails, it will return the original string.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Used to make telemetry data typed (and support math operations, like comparison),
|
|
33
|
+
* in places where we do expect numbers (like contentsize/duration property in http header).
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
38
|
+
export function numberFromString(str) {
|
|
39
|
+
if (str === undefined || str === null) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const num = Number(str);
|
|
43
|
+
return Number.isNaN(num) ? str : num;
|
|
44
|
+
}
|
|
45
|
+
// TODO: add docs
|
|
46
|
+
// eslint-disable-next-line jsdoc/require-description
|
|
47
|
+
/**
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export function formatTick(tick) {
|
|
51
|
+
return Math.floor(tick);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* String used to concatenate the namespace of parent loggers and their child loggers.
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export const eventNamespaceSeparator = ":";
|
|
24
58
|
/**
|
|
25
59
|
* TelemetryLogger class contains various helper telemetry methods,
|
|
26
60
|
* encoding in one place schemas for various types of Fluid telemetry events.
|
|
27
61
|
* Creates sub-logger that appends properties to all events
|
|
28
62
|
*/
|
|
29
63
|
export class TelemetryLogger {
|
|
30
|
-
constructor(namespace, properties) {
|
|
31
|
-
this.namespace = namespace;
|
|
32
|
-
this.properties = properties;
|
|
33
|
-
}
|
|
34
|
-
static formatTick(tick) {
|
|
35
|
-
return Math.floor(tick);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Attempts to parse number from string.
|
|
39
|
-
* If fails,returns original string.
|
|
40
|
-
* Used to make telemetry data typed (and support math operations, like comparison),
|
|
41
|
-
* in places where we do expect numbers (like contentsize/duration property in http header)
|
|
42
|
-
*/
|
|
43
|
-
static numberFromString(str) {
|
|
44
|
-
if (str === undefined || str === null) {
|
|
45
|
-
return undefined;
|
|
46
|
-
}
|
|
47
|
-
const num = Number(str);
|
|
48
|
-
return Number.isNaN(num) ? str : num;
|
|
49
|
-
}
|
|
50
64
|
static sanitizePkgName(name) {
|
|
51
65
|
return name.replace("@", "").replace("/", "-");
|
|
52
66
|
}
|
|
@@ -79,32 +93,38 @@ export class TelemetryLogger {
|
|
|
79
93
|
event.stack = generateStack();
|
|
80
94
|
}
|
|
81
95
|
}
|
|
96
|
+
constructor(namespace, properties) {
|
|
97
|
+
this.namespace = namespace;
|
|
98
|
+
this.properties = properties;
|
|
99
|
+
}
|
|
82
100
|
/**
|
|
83
101
|
* Send a telemetry event with the logger
|
|
84
102
|
*
|
|
85
103
|
* @param event - the event to send
|
|
86
104
|
* @param error - optional error object to log
|
|
105
|
+
* @param logLevel - optional level of the log. It category of event is set as error,
|
|
106
|
+
* then the logLevel will be upgraded to be an error.
|
|
87
107
|
*/
|
|
88
|
-
sendTelemetryEvent(event, error) {
|
|
89
|
-
|
|
90
|
-
this.sendTelemetryEventCore(Object.assign(Object.assign({}, event), { category: (_a = event.category) !== null && _a !== void 0 ? _a : "generic" }), error);
|
|
108
|
+
sendTelemetryEvent(event, error, logLevel = LogLevel.default) {
|
|
109
|
+
this.sendTelemetryEventCore({ ...event, category: event.category ?? "generic" }, error, event.category === "error" ? LogLevel.error : logLevel);
|
|
91
110
|
}
|
|
92
111
|
/**
|
|
93
112
|
* Send a telemetry event with the logger
|
|
94
113
|
*
|
|
95
114
|
* @param event - the event to send
|
|
96
115
|
* @param error - optional error object to log
|
|
116
|
+
* @param logLevel - optional level of the log.
|
|
97
117
|
*/
|
|
98
|
-
sendTelemetryEventCore(event, error) {
|
|
99
|
-
const newEvent =
|
|
118
|
+
sendTelemetryEventCore(event, error, logLevel) {
|
|
119
|
+
const newEvent = convertToBaseEvent(event);
|
|
100
120
|
if (error !== undefined) {
|
|
101
121
|
TelemetryLogger.prepareErrorObject(newEvent, error, false);
|
|
102
122
|
}
|
|
103
123
|
// Will include Nan & Infinity, but probably we do not care
|
|
104
124
|
if (typeof newEvent.duration === "number") {
|
|
105
|
-
newEvent.duration =
|
|
125
|
+
newEvent.duration = formatTick(newEvent.duration);
|
|
106
126
|
}
|
|
107
|
-
this.send(newEvent);
|
|
127
|
+
this.send(newEvent, logLevel);
|
|
108
128
|
}
|
|
109
129
|
/**
|
|
110
130
|
* Send an error telemetry event with the logger
|
|
@@ -113,28 +133,41 @@ export class TelemetryLogger {
|
|
|
113
133
|
* @param error - optional error object to log
|
|
114
134
|
*/
|
|
115
135
|
sendErrorEvent(event, error) {
|
|
116
|
-
this.sendTelemetryEventCore(
|
|
136
|
+
this.sendTelemetryEventCore({
|
|
117
137
|
// ensure the error field has some value,
|
|
118
138
|
// this can and will be overridden by event, or error
|
|
119
|
-
error: event.eventName
|
|
139
|
+
error: event.eventName,
|
|
140
|
+
...event,
|
|
141
|
+
category: "error",
|
|
142
|
+
}, error, LogLevel.error);
|
|
120
143
|
}
|
|
121
144
|
/**
|
|
122
145
|
* Send a performance telemetry event with the logger
|
|
123
146
|
*
|
|
124
147
|
* @param event - Event to send
|
|
125
148
|
* @param error - optional error object to log
|
|
149
|
+
* @param logLevel - optional level of the log. It category of event is set as error,
|
|
150
|
+
* then the logLevel will be upgraded to be an error.
|
|
126
151
|
*/
|
|
127
|
-
sendPerformanceEvent(event, error) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
152
|
+
sendPerformanceEvent(event, error, logLevel = LogLevel.default) {
|
|
153
|
+
const perfEvent = {
|
|
154
|
+
...event,
|
|
155
|
+
category: event.category ?? "performance",
|
|
156
|
+
};
|
|
157
|
+
this.sendTelemetryEventCore(perfEvent, error, perfEvent.category === "error" ? LogLevel.error : logLevel);
|
|
131
158
|
}
|
|
132
159
|
prepareEvent(event) {
|
|
133
160
|
const includeErrorProps = event.category === "error" || event.error !== undefined;
|
|
134
|
-
const newEvent =
|
|
161
|
+
const newEvent = {
|
|
162
|
+
...event,
|
|
163
|
+
};
|
|
135
164
|
if (this.namespace !== undefined) {
|
|
136
165
|
newEvent.eventName = `${this.namespace}${TelemetryLogger.eventNamespaceSeparator}${newEvent.eventName}`;
|
|
137
166
|
}
|
|
167
|
+
return this.extendProperties(newEvent, includeErrorProps);
|
|
168
|
+
}
|
|
169
|
+
extendProperties(toExtend, includeErrorProps) {
|
|
170
|
+
const eventLike = toExtend;
|
|
138
171
|
if (this.properties) {
|
|
139
172
|
const properties = [];
|
|
140
173
|
properties.push(this.properties.all);
|
|
@@ -144,32 +177,40 @@ export class TelemetryLogger {
|
|
|
144
177
|
for (const props of properties) {
|
|
145
178
|
if (props !== undefined) {
|
|
146
179
|
for (const key of Object.keys(props)) {
|
|
147
|
-
if (
|
|
180
|
+
if (eventLike[key] !== undefined) {
|
|
148
181
|
continue;
|
|
149
182
|
}
|
|
150
183
|
const getterOrValue = props[key];
|
|
151
184
|
// If this throws, hopefully it is handled elsewhere
|
|
152
185
|
const value = typeof getterOrValue === "function" ? getterOrValue() : getterOrValue;
|
|
153
186
|
if (value !== undefined) {
|
|
154
|
-
|
|
187
|
+
eventLike[key] = value;
|
|
155
188
|
}
|
|
156
189
|
}
|
|
157
190
|
}
|
|
158
191
|
}
|
|
159
192
|
}
|
|
160
|
-
return
|
|
193
|
+
return toExtend;
|
|
161
194
|
}
|
|
162
195
|
}
|
|
163
|
-
|
|
196
|
+
/**
|
|
197
|
+
* {@inheritDoc eventNamespaceSeparator}
|
|
198
|
+
*/
|
|
199
|
+
TelemetryLogger.eventNamespaceSeparator = eventNamespaceSeparator;
|
|
164
200
|
/**
|
|
165
201
|
* @deprecated 0.56, remove TaggedLoggerAdapter once its usage is removed from
|
|
166
202
|
* container-runtime. Issue: #8191
|
|
167
203
|
* TaggedLoggerAdapter class can add tag handling to your logger.
|
|
204
|
+
*
|
|
205
|
+
* @internal
|
|
168
206
|
*/
|
|
169
207
|
export class TaggedLoggerAdapter {
|
|
170
208
|
constructor(logger) {
|
|
171
209
|
this.logger = logger;
|
|
172
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* {@inheritDoc @fluidframework/core-interfaces#ITelemetryBaseLogger.send}
|
|
213
|
+
*/
|
|
173
214
|
send(eventWithTagsMaybe) {
|
|
174
215
|
const newEvent = {
|
|
175
216
|
category: eventWithTagsMaybe.category,
|
|
@@ -177,55 +218,64 @@ export class TaggedLoggerAdapter {
|
|
|
177
218
|
};
|
|
178
219
|
for (const key of Object.keys(eventWithTagsMaybe)) {
|
|
179
220
|
const taggableProp = eventWithTagsMaybe[key];
|
|
180
|
-
const { value, tag } =
|
|
221
|
+
const { value, tag } = typeof taggableProp === "object"
|
|
181
222
|
? taggableProp
|
|
182
223
|
: { value: taggableProp, tag: undefined };
|
|
183
224
|
switch (tag) {
|
|
184
|
-
case undefined:
|
|
225
|
+
case undefined: {
|
|
185
226
|
// No tag means we can log plainly
|
|
186
227
|
newEvent[key] = value;
|
|
187
228
|
break;
|
|
188
|
-
|
|
189
|
-
|
|
229
|
+
}
|
|
230
|
+
case "PackageData": // For back-compat
|
|
231
|
+
case TelemetryDataTag.CodeArtifact: {
|
|
232
|
+
// For Microsoft applications, CodeArtifact is safe for now
|
|
190
233
|
// (we don't load 3P code in 1P apps)
|
|
191
234
|
newEvent[key] = value;
|
|
192
235
|
break;
|
|
193
|
-
|
|
194
|
-
|
|
236
|
+
}
|
|
237
|
+
case TelemetryDataTag.UserData: {
|
|
238
|
+
// Strip out anything tagged explicitly as UserData.
|
|
195
239
|
// Alternate strategy would be to hash these props
|
|
196
240
|
newEvent[key] = "REDACTED (UserData)";
|
|
197
241
|
break;
|
|
198
|
-
|
|
242
|
+
}
|
|
243
|
+
default: {
|
|
199
244
|
// If we encounter a tag we don't recognize
|
|
200
245
|
// then we must assume we should scrub.
|
|
201
246
|
newEvent[key] = "REDACTED (unknown tag)";
|
|
202
247
|
break;
|
|
248
|
+
}
|
|
203
249
|
}
|
|
204
250
|
}
|
|
205
251
|
this.logger.send(newEvent);
|
|
206
252
|
}
|
|
207
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Create a child logger based on the provided props object.
|
|
256
|
+
*
|
|
257
|
+
* @remarks
|
|
258
|
+
* Passing in no props object (i.e. undefined) will return a logger that is effectively a no-op.
|
|
259
|
+
*
|
|
260
|
+
* @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.
|
|
261
|
+
*
|
|
262
|
+
* @alpha
|
|
263
|
+
*/
|
|
264
|
+
export function createChildLogger(props) {
|
|
265
|
+
return ChildLogger.create(props?.logger, props?.namespace, props?.properties);
|
|
266
|
+
}
|
|
208
267
|
/**
|
|
209
268
|
* ChildLogger class contains various helper telemetry methods,
|
|
210
269
|
* encoding in one place schemas for various types of Fluid telemetry events.
|
|
211
|
-
* Creates sub-logger that appends properties to all events
|
|
270
|
+
* Creates sub-logger that appends properties to all events.
|
|
212
271
|
*/
|
|
213
272
|
export class ChildLogger extends TelemetryLogger {
|
|
214
|
-
constructor(baseLogger, namespace, properties) {
|
|
215
|
-
super(namespace, properties);
|
|
216
|
-
this.baseLogger = baseLogger;
|
|
217
|
-
// propagate the monitoring context
|
|
218
|
-
if (loggerIsMonitoringContext(baseLogger)) {
|
|
219
|
-
mixinMonitoringContext(this, new CachedConfigProvider(baseLogger.config));
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
273
|
/**
|
|
223
274
|
* Create child logger
|
|
224
275
|
* @param baseLogger - Base logger to use to output events. If undefined, proper child logger
|
|
225
|
-
* is created, but it does not
|
|
276
|
+
* is created, but it does not send telemetry events anywhere.
|
|
226
277
|
* @param namespace - Telemetry event name prefix to add to all events
|
|
227
278
|
* @param properties - Base properties to add to all events
|
|
228
|
-
* @param propertyGetters - Getters to add additional properties to all events
|
|
229
279
|
*/
|
|
230
280
|
static create(baseLogger, namespace, properties) {
|
|
231
281
|
// if we are creating a child of a child, rather than nest, which will increase
|
|
@@ -235,10 +285,16 @@ export class ChildLogger extends TelemetryLogger {
|
|
|
235
285
|
for (const extendedProps of [baseLogger.properties, properties]) {
|
|
236
286
|
if (extendedProps !== undefined) {
|
|
237
287
|
if (extendedProps.all !== undefined) {
|
|
238
|
-
combinedProperties.all =
|
|
288
|
+
combinedProperties.all = {
|
|
289
|
+
...combinedProperties.all,
|
|
290
|
+
...extendedProps.all,
|
|
291
|
+
};
|
|
239
292
|
}
|
|
240
293
|
if (extendedProps.error !== undefined) {
|
|
241
|
-
combinedProperties.error =
|
|
294
|
+
combinedProperties.error = {
|
|
295
|
+
...combinedProperties.error,
|
|
296
|
+
...extendedProps.error,
|
|
297
|
+
};
|
|
242
298
|
}
|
|
243
299
|
}
|
|
244
300
|
}
|
|
@@ -247,34 +303,95 @@ export class ChildLogger extends TelemetryLogger {
|
|
|
247
303
|
: namespace === undefined
|
|
248
304
|
? baseLogger.namespace
|
|
249
305
|
: `${baseLogger.namespace}${TelemetryLogger.eventNamespaceSeparator}${namespace}`;
|
|
250
|
-
|
|
306
|
+
const child = new ChildLogger(baseLogger.baseLogger, combinedNamespace, combinedProperties);
|
|
307
|
+
if (!loggerIsMonitoringContext(child) && loggerIsMonitoringContext(baseLogger)) {
|
|
308
|
+
mixinMonitoringContext(child, baseLogger.config);
|
|
309
|
+
}
|
|
310
|
+
return child;
|
|
311
|
+
}
|
|
312
|
+
return new ChildLogger(baseLogger ?? { send() { } }, namespace, properties);
|
|
313
|
+
}
|
|
314
|
+
constructor(baseLogger, namespace, properties) {
|
|
315
|
+
super(namespace, properties);
|
|
316
|
+
this.baseLogger = baseLogger;
|
|
317
|
+
// propagate the monitoring context
|
|
318
|
+
if (loggerIsMonitoringContext(baseLogger)) {
|
|
319
|
+
mixinMonitoringContext(this, new CachedConfigProvider(this, baseLogger.config));
|
|
251
320
|
}
|
|
252
|
-
|
|
321
|
+
}
|
|
322
|
+
get minLogLevel() {
|
|
323
|
+
return this.baseLogger.minLogLevel;
|
|
324
|
+
}
|
|
325
|
+
shouldFilterOutEvent(event, logLevel) {
|
|
326
|
+
const eventLogLevel = logLevel ?? LogLevel.default;
|
|
327
|
+
const configLogLevel = this.baseLogger.minLogLevel ?? LogLevel.default;
|
|
328
|
+
// Filter out in case event log level is below what is wanted in config.
|
|
329
|
+
return eventLogLevel < configLogLevel;
|
|
253
330
|
}
|
|
254
331
|
/**
|
|
255
332
|
* Send an event with the logger
|
|
256
333
|
*
|
|
257
334
|
* @param event - the event to send
|
|
258
335
|
*/
|
|
259
|
-
send(event) {
|
|
260
|
-
|
|
336
|
+
send(event, logLevel) {
|
|
337
|
+
if (this.shouldFilterOutEvent(event, logLevel)) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
this.baseLogger.send(this.prepareEvent(event), logLevel);
|
|
261
341
|
}
|
|
262
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Create a logger which logs to multiple other loggers based on the provided props object.
|
|
345
|
+
*
|
|
346
|
+
* @internal
|
|
347
|
+
*/
|
|
348
|
+
export function createMultiSinkLogger(props) {
|
|
349
|
+
return new MultiSinkLogger(props.namespace, props.properties, props.loggers?.filter((l) => l !== undefined), props.tryInheritProperties);
|
|
350
|
+
}
|
|
263
351
|
/**
|
|
264
352
|
* Multi-sink logger
|
|
265
353
|
* Takes multiple ITelemetryBaseLogger objects (sinks) and logs all events into each sink
|
|
266
|
-
* Implements ITelemetryBaseLogger (through static create() method)
|
|
267
354
|
*/
|
|
268
355
|
export class MultiSinkLogger extends TelemetryLogger {
|
|
269
356
|
/**
|
|
270
357
|
* Create multiple sink logger (i.e. logger that sends events to multiple sinks)
|
|
271
358
|
* @param namespace - Telemetry event name prefix to add to all events
|
|
272
359
|
* @param properties - Base properties to add to all events
|
|
273
|
-
* @param
|
|
360
|
+
* @param loggers - The list of loggers to use as sinks
|
|
361
|
+
* @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
|
|
274
362
|
*/
|
|
275
|
-
constructor(namespace, properties) {
|
|
276
|
-
|
|
277
|
-
|
|
363
|
+
constructor(namespace, properties, loggers = [], tryInheritProperties) {
|
|
364
|
+
let realProperties = properties === undefined ? undefined : { ...properties };
|
|
365
|
+
if (tryInheritProperties === true) {
|
|
366
|
+
const merge = (realProperties ?? (realProperties = {}));
|
|
367
|
+
loggers
|
|
368
|
+
.filter((l) => l instanceof TelemetryLogger)
|
|
369
|
+
.map((l) => l.properties ?? {})
|
|
370
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
371
|
+
.forEach((cv) => {
|
|
372
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
373
|
+
Object.keys(cv).forEach((k) => {
|
|
374
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
375
|
+
merge[k] = { ...cv[k], ...merge?.[k] };
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
super(namespace, realProperties);
|
|
380
|
+
this.loggers = loggers;
|
|
381
|
+
this._minLogLevelOfAllLoggers = LogLevel.default;
|
|
382
|
+
this.calculateMinLogLevel();
|
|
383
|
+
}
|
|
384
|
+
get minLogLevel() {
|
|
385
|
+
return this._minLogLevelOfAllLoggers;
|
|
386
|
+
}
|
|
387
|
+
calculateMinLogLevel() {
|
|
388
|
+
if (this.loggers.length > 0) {
|
|
389
|
+
const logLevels = [];
|
|
390
|
+
for (const logger of this.loggers) {
|
|
391
|
+
logLevels.push(logger.minLogLevel ?? LogLevel.default);
|
|
392
|
+
}
|
|
393
|
+
this._minLogLevelOfAllLoggers = Math.min(...logLevels);
|
|
394
|
+
}
|
|
278
395
|
}
|
|
279
396
|
/**
|
|
280
397
|
* Add logger to send all events to
|
|
@@ -283,6 +400,8 @@ export class MultiSinkLogger extends TelemetryLogger {
|
|
|
283
400
|
addLogger(logger) {
|
|
284
401
|
if (logger !== undefined && logger !== null) {
|
|
285
402
|
this.loggers.push(logger);
|
|
403
|
+
// Update in case the logLevel of added logger is less than the current.
|
|
404
|
+
this.calculateMinLogLevel();
|
|
286
405
|
}
|
|
287
406
|
}
|
|
288
407
|
/**
|
|
@@ -292,33 +411,48 @@ export class MultiSinkLogger extends TelemetryLogger {
|
|
|
292
411
|
*/
|
|
293
412
|
send(event) {
|
|
294
413
|
const newEvent = this.prepareEvent(event);
|
|
295
|
-
this.loggers
|
|
414
|
+
for (const logger of this.loggers) {
|
|
296
415
|
logger.send(newEvent);
|
|
297
|
-
}
|
|
416
|
+
}
|
|
298
417
|
}
|
|
299
418
|
}
|
|
300
419
|
/**
|
|
301
|
-
* Helper class to log performance events
|
|
420
|
+
* Helper class to log performance events.
|
|
421
|
+
*
|
|
422
|
+
* @internal
|
|
302
423
|
*/
|
|
303
424
|
export class PerformanceEvent {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
static start(logger, event, markers) {
|
|
318
|
-
return new PerformanceEvent(logger, event, markers);
|
|
425
|
+
/**
|
|
426
|
+
* Creates an instance of {@link PerformanceEvent} and starts measurements
|
|
427
|
+
* @param logger - the logger to be used for publishing events
|
|
428
|
+
* @param event - the logging event details which will be published with the performance measurements
|
|
429
|
+
* @param markers - See {@link IPerformanceEventMarkers}
|
|
430
|
+
* @param recordHeapSize - whether or not to also record memory performance
|
|
431
|
+
* @param emitLogs - should this instance emit logs. If set to false, logs will not be emitted to the logger,
|
|
432
|
+
* but measurements will still be performed and any specified markers will be generated.
|
|
433
|
+
* @returns An instance of {@link PerformanceEvent}
|
|
434
|
+
*/
|
|
435
|
+
static start(logger, event, markers, recordHeapSize = false, emitLogs = true) {
|
|
436
|
+
return new PerformanceEvent(logger, event, markers, recordHeapSize, emitLogs);
|
|
319
437
|
}
|
|
320
|
-
|
|
321
|
-
|
|
438
|
+
/**
|
|
439
|
+
* Measure a synchronous task
|
|
440
|
+
* @param logger - the logger to be used for publishing events
|
|
441
|
+
* @param event - the logging event details which will be published with the performance measurements
|
|
442
|
+
* @param callback - the task to be executed and measured
|
|
443
|
+
* @param markers - See {@link IPerformanceEventMarkers}
|
|
444
|
+
* @param sampleThreshold - events with the same name and category will be sent to the logger
|
|
445
|
+
* only when we hit this many executions of the task. If unspecified, all events will be sent.
|
|
446
|
+
* @returns The results of the executed task
|
|
447
|
+
*
|
|
448
|
+
* @remarks Note that if the "same" event (category + eventName) would be emitted by different
|
|
449
|
+
* tasks (`callback`), `sampleThreshold` is still applied only based on the event's category + eventName,
|
|
450
|
+
* so executing either of the tasks will increase the internal counter and they
|
|
451
|
+
* effectively "share" the sampling rate for the event.
|
|
452
|
+
*/
|
|
453
|
+
static timedExec(logger, event, callback, markers, sampleThreshold = 1) {
|
|
454
|
+
const perfEvent = PerformanceEvent.start(logger, event, markers, undefined, // recordHeapSize
|
|
455
|
+
PerformanceEvent.shouldReport(event, sampleThreshold));
|
|
322
456
|
try {
|
|
323
457
|
const ret = callback(perfEvent);
|
|
324
458
|
perfEvent.autoEnd();
|
|
@@ -329,8 +463,24 @@ export class PerformanceEvent {
|
|
|
329
463
|
throw error;
|
|
330
464
|
}
|
|
331
465
|
}
|
|
332
|
-
|
|
333
|
-
|
|
466
|
+
/**
|
|
467
|
+
* Measure an asynchronous task
|
|
468
|
+
* @param logger - the logger to be used for publishing events
|
|
469
|
+
* @param event - the logging event details which will be published with the performance measurements
|
|
470
|
+
* @param callback - the task to be executed and measured
|
|
471
|
+
* @param markers - See {@link IPerformanceEventMarkers}
|
|
472
|
+
* @param recordHeapSize - whether or not to also record memory performance
|
|
473
|
+
* @param sampleThreshold - events with the same name and category will be sent to the logger
|
|
474
|
+
* only when we hit this many executions of the task. If unspecified, all events will be sent.
|
|
475
|
+
* @returns The results of the executed task
|
|
476
|
+
*
|
|
477
|
+
* @remarks Note that if the "same" event (category + eventName) would be emitted by different
|
|
478
|
+
* tasks (`callback`), `sampleThreshold` is still applied only based on the event's category + eventName,
|
|
479
|
+
* so executing either of the tasks will increase the internal counter and they
|
|
480
|
+
* effectively "share" the sampling rate for the event.
|
|
481
|
+
*/
|
|
482
|
+
static async timedExecAsync(logger, event, callback, markers, recordHeapSize, sampleThreshold = 1) {
|
|
483
|
+
const perfEvent = PerformanceEvent.start(logger, event, markers, recordHeapSize, PerformanceEvent.shouldReport(event, sampleThreshold));
|
|
334
484
|
try {
|
|
335
485
|
const ret = await callback(perfEvent);
|
|
336
486
|
perfEvent.autoEnd();
|
|
@@ -341,7 +491,25 @@ export class PerformanceEvent {
|
|
|
341
491
|
throw error;
|
|
342
492
|
}
|
|
343
493
|
}
|
|
344
|
-
get duration() {
|
|
494
|
+
get duration() {
|
|
495
|
+
return performance.now() - this.startTime;
|
|
496
|
+
}
|
|
497
|
+
constructor(logger, event, markers = { end: true, cancel: "generic" }, recordHeapSize = false, emitLogs = true) {
|
|
498
|
+
this.logger = logger;
|
|
499
|
+
this.markers = markers;
|
|
500
|
+
this.recordHeapSize = recordHeapSize;
|
|
501
|
+
this.emitLogs = emitLogs;
|
|
502
|
+
this.startTime = performance.now();
|
|
503
|
+
this.startMemoryCollection = 0;
|
|
504
|
+
this.event = { ...event };
|
|
505
|
+
if (this.markers.start) {
|
|
506
|
+
this.reportEvent("start");
|
|
507
|
+
}
|
|
508
|
+
if (typeof window === "object" && window?.performance?.mark) {
|
|
509
|
+
this.startMark = `${event.eventName}-start`;
|
|
510
|
+
window.performance.mark(this.startMark);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
345
513
|
reportProgress(props, eventNameSuffix = "update") {
|
|
346
514
|
this.reportEvent(eventNameSuffix, props);
|
|
347
515
|
}
|
|
@@ -368,7 +536,7 @@ export class PerformanceEvent {
|
|
|
368
536
|
}
|
|
369
537
|
cancel(props, error) {
|
|
370
538
|
if (this.markers.cancel !== undefined) {
|
|
371
|
-
this.reportEvent("cancel",
|
|
539
|
+
this.reportEvent("cancel", { category: this.markers.cancel, ...props }, error);
|
|
372
540
|
}
|
|
373
541
|
this.event = undefined;
|
|
374
542
|
}
|
|
@@ -382,48 +550,164 @@ export class PerformanceEvent {
|
|
|
382
550
|
if (!this.event) {
|
|
383
551
|
return;
|
|
384
552
|
}
|
|
385
|
-
|
|
553
|
+
if (!this.emitLogs) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const event = { ...this.event, ...props };
|
|
386
557
|
event.eventName = `${event.eventName}_${eventNameSuffix}`;
|
|
387
558
|
if (eventNameSuffix !== "start") {
|
|
388
559
|
event.duration = this.duration;
|
|
560
|
+
if (this.startMemoryCollection) {
|
|
561
|
+
const currentMemory = performance?.memory
|
|
562
|
+
?.usedJSHeapSize;
|
|
563
|
+
const differenceInKBytes = Math.floor((currentMemory - this.startMemoryCollection) / 1024);
|
|
564
|
+
if (differenceInKBytes > 0) {
|
|
565
|
+
event.usedJSHeapSize = differenceInKBytes;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
else if (this.recordHeapSize) {
|
|
570
|
+
this.startMemoryCollection = performance?.memory
|
|
571
|
+
?.usedJSHeapSize;
|
|
389
572
|
}
|
|
390
573
|
this.logger.sendPerformanceEvent(event, error);
|
|
391
574
|
}
|
|
575
|
+
static shouldReport(event, sampleThreshold) {
|
|
576
|
+
const eventKey = `.${event.category}.${event.eventName}`;
|
|
577
|
+
const hitCount = PerformanceEvent.eventHits.get(eventKey) ?? 0;
|
|
578
|
+
PerformanceEvent.eventHits.set(eventKey, hitCount >= sampleThreshold ? 1 : hitCount + 1);
|
|
579
|
+
return hitCount % sampleThreshold === 0;
|
|
580
|
+
}
|
|
392
581
|
}
|
|
582
|
+
PerformanceEvent.eventHits = new Map();
|
|
393
583
|
/**
|
|
394
|
-
*
|
|
395
|
-
*
|
|
584
|
+
* Null logger that no-ops for all telemetry events passed to it.
|
|
585
|
+
*
|
|
586
|
+
* @deprecated This will be removed in a future release.
|
|
587
|
+
* For internal use within the FluidFramework codebase, use {@link createChildLogger} with no arguments instead.
|
|
588
|
+
* For external consumers we recommend writing a trivial implementation of {@link @fluidframework/core-interfaces#ITelemetryBaseLogger}
|
|
589
|
+
* where the send() method does nothing and using that.
|
|
590
|
+
*
|
|
591
|
+
* @internal
|
|
396
592
|
*/
|
|
397
|
-
export class
|
|
398
|
-
send(event) {
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
593
|
+
export class TelemetryNullLogger {
|
|
594
|
+
send(event) { }
|
|
595
|
+
sendTelemetryEvent(event, error) { }
|
|
596
|
+
sendErrorEvent(event, error) { }
|
|
597
|
+
sendPerformanceEvent(event, error) { }
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Takes in an event object, and converts all of its values to a basePropertyType.
|
|
601
|
+
* In the case of an invalid property type, the value will be converted to an error string.
|
|
602
|
+
* @param event - Event with fields you want to stringify.
|
|
603
|
+
*/
|
|
604
|
+
function convertToBaseEvent({ category, eventName, ...props }) {
|
|
605
|
+
const newEvent = { category, eventName };
|
|
606
|
+
for (const key of Object.keys(props)) {
|
|
607
|
+
newEvent[key] = convertToBasePropertyType(props[key]);
|
|
412
608
|
}
|
|
413
|
-
|
|
414
|
-
|
|
609
|
+
return newEvent;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Takes in value, and does one of 4 things.
|
|
613
|
+
* if value is of primitive type - returns the original value.
|
|
614
|
+
* If the value is a flat array or object - returns a stringified version of the array/object.
|
|
615
|
+
* If the value is an object of type Tagged<TelemetryEventPropertyType> - returns the object
|
|
616
|
+
* with its values recursively converted to base property Type.
|
|
617
|
+
* If none of these cases are reached - returns an error string
|
|
618
|
+
* @param x - value passed in to convert to a base property type
|
|
619
|
+
*/
|
|
620
|
+
export function convertToBasePropertyType(x) {
|
|
621
|
+
return isTaggedTelemetryPropertyValue(x)
|
|
622
|
+
? {
|
|
623
|
+
value: convertToBasePropertyTypeUntagged(x.value),
|
|
624
|
+
tag: x.tag,
|
|
625
|
+
}
|
|
626
|
+
: convertToBasePropertyTypeUntagged(x);
|
|
627
|
+
}
|
|
628
|
+
function convertToBasePropertyTypeUntagged(x) {
|
|
629
|
+
switch (typeof x) {
|
|
630
|
+
case "string":
|
|
631
|
+
case "number":
|
|
632
|
+
case "boolean":
|
|
633
|
+
case "undefined": {
|
|
634
|
+
return x;
|
|
635
|
+
}
|
|
636
|
+
case "object": {
|
|
637
|
+
// We assume this is an array or flat object based on the input types
|
|
638
|
+
return JSON.stringify(x);
|
|
639
|
+
}
|
|
640
|
+
default: {
|
|
641
|
+
// should never reach this case based on the input types
|
|
642
|
+
console.error(`convertToBasePropertyTypeUntagged: INVALID PROPERTY (typed as ${typeof x})`);
|
|
643
|
+
return `INVALID PROPERTY (typed as ${typeof x})`;
|
|
644
|
+
}
|
|
415
645
|
}
|
|
416
|
-
|
|
417
|
-
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Tags all given `values` with the same `tag`.
|
|
649
|
+
*
|
|
650
|
+
* @param tag - The tag with which all `values` will be annotated.
|
|
651
|
+
* @param values - The values to be tagged.
|
|
652
|
+
*
|
|
653
|
+
* @remarks
|
|
654
|
+
* It supports properties of type {@link @fluidframework/core-interfaces#TelemetryBaseEventPropertyType},
|
|
655
|
+
* as well as callbacks that return that type.
|
|
656
|
+
*
|
|
657
|
+
* @example Sample usage
|
|
658
|
+
* ```typescript
|
|
659
|
+
* {
|
|
660
|
+
* // ...Other properties being added to a telemetry event
|
|
661
|
+
* ...tagData("someTag", {foo: 1, bar: 2}),
|
|
662
|
+
* // ...
|
|
663
|
+
* }
|
|
664
|
+
* ```
|
|
665
|
+
* This will result in `foo` and `bar` added to the event with their values tagged.
|
|
666
|
+
*
|
|
667
|
+
* @internal
|
|
668
|
+
*/
|
|
669
|
+
export const tagData = (tag, values) =>
|
|
670
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
671
|
+
Object.entries(values)
|
|
672
|
+
.filter((e) => e[1] !== undefined)
|
|
673
|
+
// eslint-disable-next-line unicorn/no-array-reduce, unicorn/prefer-object-from-entries
|
|
674
|
+
.reduce((pv, cv) => {
|
|
675
|
+
const [key, value] = cv;
|
|
676
|
+
// The ternary form is less legible in this case.
|
|
677
|
+
// eslint-disable-next-line unicorn/prefer-ternary
|
|
678
|
+
if (typeof value === "function") {
|
|
679
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
680
|
+
pv[key] = () => {
|
|
681
|
+
return { tag, value: value() };
|
|
682
|
+
};
|
|
418
683
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
error.error = error;
|
|
422
|
-
error.event = event;
|
|
423
|
-
// report to console as exception can be eaten
|
|
424
|
-
console.error(message);
|
|
425
|
-
console.error(error);
|
|
426
|
-
throw error;
|
|
684
|
+
else {
|
|
685
|
+
pv[key] = { tag, value };
|
|
427
686
|
}
|
|
428
|
-
|
|
687
|
+
return pv;
|
|
688
|
+
}, {});
|
|
689
|
+
/**
|
|
690
|
+
* Tags all provided `values` as {@link TelemetryDataTag.CodeArtifact}.
|
|
691
|
+
*
|
|
692
|
+
* @param values - The values to be tagged.
|
|
693
|
+
*
|
|
694
|
+
* @remarks
|
|
695
|
+
* It supports properties of type {@link @fluidframework/core-interfaces#TelemetryBaseEventPropertyType},
|
|
696
|
+
* as well as callbacks that return that type.
|
|
697
|
+
*
|
|
698
|
+
* @example Sample usage
|
|
699
|
+
* ```typescript
|
|
700
|
+
* {
|
|
701
|
+
* // ...Other properties being added to a telemetry event
|
|
702
|
+
* ...tagCodeArtifacts("someTag", {foo: 1, bar: 2}),
|
|
703
|
+
* // ...
|
|
704
|
+
* }
|
|
705
|
+
* ```
|
|
706
|
+
* This will result in `foo` and `bar` added to the event with their values tagged as {@link TelemetryDataTag.CodeArtifact}.
|
|
707
|
+
*
|
|
708
|
+
* @see {@link tagData}
|
|
709
|
+
*
|
|
710
|
+
* @internal
|
|
711
|
+
*/
|
|
712
|
+
export const tagCodeArtifacts = (values) => tagData(TelemetryDataTag.CodeArtifact, values);
|
|
429
713
|
//# sourceMappingURL=logger.js.map
|