@fluidframework/telemetry-utils 2.0.0-internal.3.0.0 → 2.0.0-internal.3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.eslintrc.js +11 -13
  2. package/.mocharc.js +2 -2
  3. package/api-extractor.json +2 -2
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +3 -3
  6. package/dist/config.js.map +1 -1
  7. package/dist/debugLogger.d.ts.map +1 -1
  8. package/dist/debugLogger.js.map +1 -1
  9. package/dist/errorLogging.d.ts +5 -5
  10. package/dist/errorLogging.d.ts.map +1 -1
  11. package/dist/errorLogging.js +20 -18
  12. package/dist/errorLogging.js.map +1 -1
  13. package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
  14. package/dist/eventEmitterWithErrorHandling.js.map +1 -1
  15. package/dist/events.d.ts.map +1 -1
  16. package/dist/events.js.map +1 -1
  17. package/dist/fluidErrorBase.d.ts.map +1 -1
  18. package/dist/fluidErrorBase.js +4 -4
  19. package/dist/fluidErrorBase.js.map +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/logger.d.ts.map +1 -1
  24. package/dist/logger.js +13 -12
  25. package/dist/logger.js.map +1 -1
  26. package/dist/mockLogger.d.ts +5 -5
  27. package/dist/mockLogger.d.ts.map +1 -1
  28. package/dist/mockLogger.js +5 -5
  29. package/dist/mockLogger.js.map +1 -1
  30. package/dist/packageVersion.d.ts +1 -1
  31. package/dist/packageVersion.js +1 -1
  32. package/dist/packageVersion.js.map +1 -1
  33. package/dist/sampledTelemetryHelper.d.ts.map +1 -1
  34. package/dist/sampledTelemetryHelper.js.map +1 -1
  35. package/dist/telemetryTypes.d.ts.map +1 -1
  36. package/dist/telemetryTypes.js.map +1 -1
  37. package/dist/thresholdCounter.d.ts.map +1 -1
  38. package/dist/thresholdCounter.js.map +1 -1
  39. package/dist/utils.d.ts.map +1 -1
  40. package/dist/utils.js.map +1 -1
  41. package/lib/config.d.ts.map +1 -1
  42. package/lib/config.js +3 -3
  43. package/lib/config.js.map +1 -1
  44. package/lib/debugLogger.d.ts.map +1 -1
  45. package/lib/debugLogger.js +1 -1
  46. package/lib/debugLogger.js.map +1 -1
  47. package/lib/errorLogging.d.ts +5 -5
  48. package/lib/errorLogging.d.ts.map +1 -1
  49. package/lib/errorLogging.js +20 -18
  50. package/lib/errorLogging.js.map +1 -1
  51. package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
  52. package/lib/eventEmitterWithErrorHandling.js.map +1 -1
  53. package/lib/events.d.ts.map +1 -1
  54. package/lib/events.js.map +1 -1
  55. package/lib/fluidErrorBase.d.ts.map +1 -1
  56. package/lib/fluidErrorBase.js +4 -4
  57. package/lib/fluidErrorBase.js.map +1 -1
  58. package/lib/index.d.ts +2 -2
  59. package/lib/index.d.ts.map +1 -1
  60. package/lib/index.js +2 -2
  61. package/lib/index.js.map +1 -1
  62. package/lib/logger.d.ts.map +1 -1
  63. package/lib/logger.js +14 -13
  64. package/lib/logger.js.map +1 -1
  65. package/lib/mockLogger.d.ts +5 -5
  66. package/lib/mockLogger.d.ts.map +1 -1
  67. package/lib/mockLogger.js +5 -5
  68. package/lib/mockLogger.js.map +1 -1
  69. package/lib/packageVersion.d.ts +1 -1
  70. package/lib/packageVersion.js +1 -1
  71. package/lib/packageVersion.js.map +1 -1
  72. package/lib/sampledTelemetryHelper.d.ts.map +1 -1
  73. package/lib/sampledTelemetryHelper.js.map +1 -1
  74. package/lib/telemetryTypes.d.ts.map +1 -1
  75. package/lib/telemetryTypes.js.map +1 -1
  76. package/lib/thresholdCounter.d.ts.map +1 -1
  77. package/lib/thresholdCounter.js.map +1 -1
  78. package/lib/utils.d.ts.map +1 -1
  79. package/lib/utils.js.map +1 -1
  80. package/package.json +107 -110
  81. package/prettier.config.cjs +1 -1
  82. package/src/config.ts +173 -172
  83. package/src/debugLogger.ts +118 -111
  84. package/src/errorLogging.ts +302 -299
  85. package/src/eventEmitterWithErrorHandling.ts +16 -12
  86. package/src/events.ts +26 -26
  87. package/src/fluidErrorBase.ts +42 -38
  88. package/src/index.ts +26 -16
  89. package/src/logger.ts +541 -533
  90. package/src/mockLogger.ts +113 -107
  91. package/src/packageVersion.ts +1 -1
  92. package/src/sampledTelemetryHelper.ts +122 -122
  93. package/src/telemetryTypes.ts +37 -37
  94. package/src/thresholdCounter.ts +34 -34
  95. package/src/utils.ts +15 -15
  96. package/tsconfig.esnext.json +6 -6
  97. package/tsconfig.json +9 -13
@@ -4,90 +4,89 @@
4
4
  */
5
5
 
6
6
  import {
7
- ILoggingError,
8
- ITaggedTelemetryPropertyType,
9
- ITelemetryLogger,
10
- ITelemetryProperties,
11
- TelemetryEventPropertyType,
7
+ ILoggingError,
8
+ ITaggedTelemetryPropertyType,
9
+ ITelemetryLogger,
10
+ ITelemetryProperties,
11
+ TelemetryEventPropertyType,
12
12
  } from "@fluidframework/common-definitions";
13
13
  import { v4 as uuid } from "uuid";
14
14
  import {
15
- hasErrorInstanceId,
16
- IFluidErrorBase,
17
- isFluidError,
18
- isValidLegacyError,
15
+ hasErrorInstanceId,
16
+ IFluidErrorBase,
17
+ isFluidError,
18
+ isValidLegacyError,
19
19
  } from "./fluidErrorBase";
20
20
  import { ITaggedTelemetryPropertyTypeExt, TelemetryEventPropertyTypeExt } from "./telemetryTypes";
21
21
 
22
22
  /** @returns true if value is an object but neither null nor an array */
23
23
  const isRegularObject = (value: any): boolean => {
24
- return value !== null && !Array.isArray(value) && typeof value === "object";
24
+ return value !== null && !Array.isArray(value) && typeof value === "object";
25
25
  };
26
26
 
27
27
  /** Inspect the given error for common "safe" props and return them */
28
28
  export function extractLogSafeErrorProperties(error: any, sanitizeStack: boolean) {
29
- const removeMessageFromStack = (stack: string, errorName?: string) => {
30
- if (!sanitizeStack) {
31
- return stack;
32
- }
33
- const stackFrames = stack.split("\n");
34
- stackFrames.shift(); // Remove "[ErrorName]: [ErrorMessage]"
35
- if (errorName !== undefined) {
36
- stackFrames.unshift(errorName); // Add "[ErrorName]"
37
- }
38
- return stackFrames.join("\n");
39
- };
40
-
41
- const message = (typeof error?.message === "string")
42
- ? error.message as string
43
- : String(error);
44
-
45
- const safeProps: { message: string; errorType?: string; stack?: string; } = {
46
- message,
47
- };
48
-
49
- if (isRegularObject(error)) {
50
- const { errorType, stack, name } = error;
51
-
52
- if (typeof errorType === "string") {
53
- safeProps.errorType = errorType;
54
- }
55
-
56
- if (typeof stack === "string") {
57
- const errorName = (typeof name === "string") ? name : undefined;
58
- safeProps.stack = removeMessageFromStack(stack, errorName);
59
- }
60
- }
61
-
62
- return safeProps;
29
+ const removeMessageFromStack = (stack: string, errorName?: string) => {
30
+ if (!sanitizeStack) {
31
+ return stack;
32
+ }
33
+ const stackFrames = stack.split("\n");
34
+ stackFrames.shift(); // Remove "[ErrorName]: [ErrorMessage]"
35
+ if (errorName !== undefined) {
36
+ stackFrames.unshift(errorName); // Add "[ErrorName]"
37
+ }
38
+ return stackFrames.join("\n");
39
+ };
40
+
41
+ const message = typeof error?.message === "string" ? (error.message as string) : String(error);
42
+
43
+ const safeProps: { message: string; errorType?: string; stack?: string } = {
44
+ message,
45
+ };
46
+
47
+ if (isRegularObject(error)) {
48
+ const { errorType, stack, name } = error;
49
+
50
+ if (typeof errorType === "string") {
51
+ safeProps.errorType = errorType;
52
+ }
53
+
54
+ if (typeof stack === "string") {
55
+ const errorName = typeof name === "string" ? name : undefined;
56
+ safeProps.stack = removeMessageFromStack(stack, errorName);
57
+ }
58
+ }
59
+
60
+ return safeProps;
63
61
  }
64
62
 
65
63
  /** type guard for ILoggingError interface */
66
- export const isILoggingError = (x: any): x is ILoggingError => typeof x?.getTelemetryProperties === "function";
64
+ export const isILoggingError = (x: any): x is ILoggingError =>
65
+ typeof x?.getTelemetryProperties === "function";
67
66
 
68
67
  /** Copy props from source onto target, but do not overwrite an existing prop that matches */
69
68
  function copyProps(target: ITelemetryProperties | LoggingError, source: ITelemetryProperties) {
70
- for (const key of Object.keys(source)) {
71
- if (target[key] === undefined) {
72
- target[key] = source[key];
73
- }
74
- }
69
+ for (const key of Object.keys(source)) {
70
+ if (target[key] === undefined) {
71
+ target[key] = source[key];
72
+ }
73
+ }
75
74
  }
76
75
 
77
76
  /** Metadata to annotate an error object when annotating or normalizing it */
78
77
  export interface IFluidErrorAnnotations {
79
- /** Telemetry props to log with the error */
80
- props?: ITelemetryProperties;
78
+ /** Telemetry props to log with the error */
79
+ props?: ITelemetryProperties;
81
80
  }
82
81
 
83
82
  /** For backwards compatibility with pre-errorInstanceId valid errors */
84
83
  function patchLegacyError(
85
- legacyError: Omit<IFluidErrorBase, "errorInstanceId">,
84
+ legacyError: Omit<IFluidErrorBase, "errorInstanceId">,
86
85
  ): asserts legacyError is IFluidErrorBase {
87
- const patchMe: { -readonly [P in "errorInstanceId"]?: IFluidErrorBase[P] } = legacyError as any;
88
- if (patchMe.errorInstanceId === undefined) {
89
- patchMe.errorInstanceId = uuid();
90
- }
86
+ const patchMe: { -readonly [P in "errorInstanceId"]?: IFluidErrorBase[P] } = legacyError as any;
87
+ if (patchMe.errorInstanceId === undefined) {
88
+ patchMe.errorInstanceId = uuid();
89
+ }
91
90
  }
92
91
 
93
92
  /**
@@ -97,50 +96,50 @@ function patchLegacyError(
97
96
  * @param annotations - Annotations to apply to the normalized error
98
97
  */
99
98
  export function normalizeError(
100
- error: unknown,
101
- annotations: IFluidErrorAnnotations = {},
99
+ error: unknown,
100
+ annotations: IFluidErrorAnnotations = {},
102
101
  ): IFluidErrorBase {
103
- // Back-compat, while IFluidErrorBase is rolled out
104
- if (isValidLegacyError(error)) {
105
- patchLegacyError(error);
106
- }
107
-
108
- if (isFluidError(error)) {
109
- // We can simply add the telemetry props to the error and return it
110
- error.addTelemetryProperties(annotations.props ?? {});
111
- return error;
112
- }
113
-
114
- // We have to construct a new Fluid Error, copying safe properties over
115
- const { message, stack } = extractLogSafeErrorProperties(error, false /* sanitizeStack */);
116
- const fluidError: IFluidErrorBase = new NormalizedLoggingError({
117
- message,
118
- stack,
119
- });
120
-
121
- // We need to preserve these properties which are used in a non-typesafe way throughout driver code (see #8743)
122
- // Anywhere they are set should be on a valid Fluid Error that would have been returned above,
123
- // but we can't prove it with the types, so adding this defensive measure.
124
- if (typeof error === "object" && error !== null) {
125
- const { canRetry, retryAfterSeconds } = error as any;
126
- Object.assign(normalizeError, { canRetry, retryAfterSeconds });
127
- }
128
-
129
- if (typeof (error) !== "object") {
130
- // This is only interesting for non-objects
131
- fluidError.addTelemetryProperties({ typeofError: typeof (error) });
132
- }
133
-
134
- const errorTelemetryProps = LoggingError.typeCheck(error)
135
- ? error.getTelemetryProperties()
136
- : { untrustedOrigin: 1 }; // This will let us filter errors that did not originate from our own codebase
137
-
138
- fluidError.addTelemetryProperties({
139
- ...errorTelemetryProps,
140
- ...annotations.props,
141
- });
142
-
143
- return fluidError;
102
+ // Back-compat, while IFluidErrorBase is rolled out
103
+ if (isValidLegacyError(error)) {
104
+ patchLegacyError(error);
105
+ }
106
+
107
+ if (isFluidError(error)) {
108
+ // We can simply add the telemetry props to the error and return it
109
+ error.addTelemetryProperties(annotations.props ?? {});
110
+ return error;
111
+ }
112
+
113
+ // We have to construct a new Fluid Error, copying safe properties over
114
+ const { message, stack } = extractLogSafeErrorProperties(error, false /* sanitizeStack */);
115
+ const fluidError: IFluidErrorBase = new NormalizedLoggingError({
116
+ message,
117
+ stack,
118
+ });
119
+
120
+ // We need to preserve these properties which are used in a non-typesafe way throughout driver code (see #8743)
121
+ // Anywhere they are set should be on a valid Fluid Error that would have been returned above,
122
+ // but we can't prove it with the types, so adding this defensive measure.
123
+ if (typeof error === "object" && error !== null) {
124
+ const { canRetry, retryAfterSeconds } = error as any;
125
+ Object.assign(normalizeError, { canRetry, retryAfterSeconds });
126
+ }
127
+
128
+ if (typeof error !== "object") {
129
+ // This is only interesting for non-objects
130
+ fluidError.addTelemetryProperties({ typeofError: typeof error });
131
+ }
132
+
133
+ const errorTelemetryProps = LoggingError.typeCheck(error)
134
+ ? error.getTelemetryProperties()
135
+ : { untrustedOrigin: 1 }; // This will let us filter errors that did not originate from our own codebase
136
+
137
+ fluidError.addTelemetryProperties({
138
+ ...errorTelemetryProps,
139
+ ...annotations.props,
140
+ });
141
+
142
+ return fluidError;
144
143
  }
145
144
 
146
145
  let stackPopulatedOnCreation: boolean | undefined;
@@ -155,25 +154,25 @@ let stackPopulatedOnCreation: boolean | undefined;
155
154
  * @returns Error object that has stack populated.
156
155
  */
157
156
  export function generateErrorWithStack(): Error {
158
- const err = new Error("<<generated stack>>");
157
+ const err = new Error("<<generated stack>>");
159
158
 
160
- if (stackPopulatedOnCreation === undefined) {
161
- stackPopulatedOnCreation = (err.stack !== undefined);
162
- }
159
+ if (stackPopulatedOnCreation === undefined) {
160
+ stackPopulatedOnCreation = err.stack !== undefined;
161
+ }
163
162
 
164
- if (stackPopulatedOnCreation) {
165
- return err;
166
- }
163
+ if (stackPopulatedOnCreation) {
164
+ return err;
165
+ }
167
166
 
168
- try {
169
- throw err;
170
- } catch (e) {
171
- return e as Error;
172
- }
167
+ try {
168
+ throw err;
169
+ } catch (e) {
170
+ return e as Error;
171
+ }
173
172
  }
174
173
 
175
174
  export function generateStack(): string | undefined {
176
- return generateErrorWithStack().stack;
175
+ return generateErrorWithStack().stack;
177
176
  }
178
177
 
179
178
  /**
@@ -184,72 +183,72 @@ export function generateStack(): string | undefined {
184
183
  * @returns A new error object "wrapping" the given error
185
184
  */
186
185
  export function wrapError<T extends LoggingError>(
187
- innerError: unknown,
188
- newErrorFn: (message: string) => T,
186
+ innerError: unknown,
187
+ newErrorFn: (message: string) => T,
189
188
  ): T {
190
- const {
191
- message,
192
- stack,
193
- } = extractLogSafeErrorProperties(innerError, false /* sanitizeStack */);
189
+ const { message, stack } = extractLogSafeErrorProperties(innerError, false /* sanitizeStack */);
194
190
 
195
- const newError = newErrorFn(message);
191
+ const newError = newErrorFn(message);
196
192
 
197
- if (stack !== undefined) {
198
- overwriteStack(newError, stack);
199
- }
193
+ if (stack !== undefined) {
194
+ overwriteStack(newError, stack);
195
+ }
200
196
 
201
- // Mark external errors with untrustedOrigin flag
202
- if (isExternalError(innerError)) {
203
- newError.addTelemetryProperties({ untrustedOrigin: 1 });
204
- }
197
+ // Mark external errors with untrustedOrigin flag
198
+ if (isExternalError(innerError)) {
199
+ newError.addTelemetryProperties({ untrustedOrigin: 1 });
200
+ }
205
201
 
206
- // Reuse errorInstanceId
207
- if (hasErrorInstanceId(innerError)) {
208
- newError.overwriteErrorInstanceId(innerError.errorInstanceId);
202
+ // Reuse errorInstanceId
203
+ if (hasErrorInstanceId(innerError)) {
204
+ newError.overwriteErrorInstanceId(innerError.errorInstanceId);
209
205
 
210
- // For "back-compat" in the logs
211
- newError.addTelemetryProperties({ innerErrorInstanceId: innerError.errorInstanceId });
212
- }
206
+ // For "back-compat" in the logs
207
+ newError.addTelemetryProperties({ innerErrorInstanceId: innerError.errorInstanceId });
208
+ }
213
209
 
214
- // Lastly, copy over all other telemetry properties. Note these will not overwrite existing properties
215
- // This will include the untrustedOrigin property if the inner error itself was created from an external error
216
- if (isILoggingError(innerError)) {
217
- newError.addTelemetryProperties(innerError.getTelemetryProperties());
218
- }
210
+ // Lastly, copy over all other telemetry properties. Note these will not overwrite existing properties
211
+ // This will include the untrustedOrigin property if the inner error itself was created from an external error
212
+ if (isILoggingError(innerError)) {
213
+ newError.addTelemetryProperties(innerError.getTelemetryProperties());
214
+ }
219
215
 
220
- return newError;
216
+ return newError;
221
217
  }
222
218
 
223
219
  /** The same as wrapError, but also logs the innerError, including the wrapping error's instance id */
224
220
  export function wrapErrorAndLog<T extends LoggingError>(
225
- innerError: unknown,
226
- newErrorFn: (message: string) => T,
227
- logger: ITelemetryLogger,
221
+ innerError: unknown,
222
+ newErrorFn: (message: string) => T,
223
+ logger: ITelemetryLogger,
228
224
  ) {
229
- const newError = wrapError(innerError, newErrorFn);
225
+ const newError = wrapError(innerError, newErrorFn);
230
226
 
231
- // This will match innerError.errorInstanceId if present (see wrapError)
232
- const errorInstanceId = newError.errorInstanceId;
227
+ // This will match innerError.errorInstanceId if present (see wrapError)
228
+ const errorInstanceId = newError.errorInstanceId;
233
229
 
234
- // For "back-compat" in the logs
235
- const wrappedByErrorInstanceId = errorInstanceId;
230
+ // For "back-compat" in the logs
231
+ const wrappedByErrorInstanceId = errorInstanceId;
236
232
 
237
- logger.sendTelemetryEvent({
238
- eventName: "WrapError",
239
- errorInstanceId,
240
- wrappedByErrorInstanceId,
241
- }, innerError);
233
+ logger.sendTelemetryEvent(
234
+ {
235
+ eventName: "WrapError",
236
+ errorInstanceId,
237
+ wrappedByErrorInstanceId,
238
+ },
239
+ innerError,
240
+ );
242
241
 
243
- return newError;
242
+ return newError;
244
243
  }
245
244
 
246
245
  function overwriteStack(error: IFluidErrorBase | LoggingError, stack: string) {
247
- // supposedly setting stack on an Error can throw.
248
- try {
249
- Object.assign(error, { stack });
250
- } catch (errorSettingStack) {
251
- error.addTelemetryProperties({ stack2: stack });
252
- }
246
+ // supposedly setting stack on an Error can throw.
247
+ try {
248
+ Object.assign(error, { stack });
249
+ } catch (errorSettingStack) {
250
+ error.addTelemetryProperties({ stack2: stack });
251
+ }
253
252
  }
254
253
 
255
254
  /**
@@ -258,25 +257,25 @@ function overwriteStack(error: IFluidErrorBase | LoggingError, stack: string) {
258
257
  * or wrapped in a well-known error type
259
258
  */
260
259
  export function isExternalError(e: any): boolean {
261
- // LoggingErrors are an internal FF error type. However, an external error can be converted
262
- // into a LoggingError if it is normalized. In this case we must use the untrustedOrigin flag to
263
- // determine whether the original error was infact external.
264
- if (LoggingError.typeCheck(e)) {
265
- if ((e as NormalizedLoggingError).errorType === NORMALIZED_ERROR_TYPE) {
266
- return e.getTelemetryProperties().untrustedOrigin === 1;
267
- }
268
- return false;
269
- }
270
- return !isValidLegacyError(e);
260
+ // LoggingErrors are an internal FF error type. However, an external error can be converted
261
+ // into a LoggingError if it is normalized. In this case we must use the untrustedOrigin flag to
262
+ // determine whether the original error was infact external.
263
+ if (LoggingError.typeCheck(e)) {
264
+ if ((e as NormalizedLoggingError).errorType === NORMALIZED_ERROR_TYPE) {
265
+ return e.getTelemetryProperties().untrustedOrigin === 1;
266
+ }
267
+ return false;
268
+ }
269
+ return !isValidLegacyError(e);
271
270
  }
272
271
 
273
272
  /**
274
273
  * Type guard to identify if a particular telemetry property appears to be a tagged telemetry property
275
274
  */
276
275
  export function isTaggedTelemetryPropertyValue(
277
- x: ITaggedTelemetryPropertyTypeExt | TelemetryEventPropertyTypeExt,
276
+ x: ITaggedTelemetryPropertyTypeExt | TelemetryEventPropertyTypeExt,
278
277
  ): x is ITaggedTelemetryPropertyType | ITaggedTelemetryPropertyTypeExt {
279
- return typeof ((x as any)?.tag) === "string";
278
+ return typeof (x as any)?.tag === "string";
280
279
  }
281
280
 
282
281
  /**
@@ -286,51 +285,51 @@ export function isTaggedTelemetryPropertyValue(
286
285
  * otherwise returns null since this is what we support at the moment.
287
286
  */
288
287
  function filterValidTelemetryProps(x: any, key: string): TelemetryEventPropertyType {
289
- if (Array.isArray(x) && x.every((val) => isTelemetryEventPropertyValue(val))) {
290
- return JSON.stringify(x);
291
- }
292
- if (isTelemetryEventPropertyValue(x)) {
293
- return x;
294
- }
295
- // We don't support logging arbitrary objects
296
- console.error(`UnSupported Format of Logging Error Property for key ${key}:`, x);
297
- return "REDACTED (arbitrary object)";
288
+ if (Array.isArray(x) && x.every((val) => isTelemetryEventPropertyValue(val))) {
289
+ return JSON.stringify(x);
290
+ }
291
+ if (isTelemetryEventPropertyValue(x)) {
292
+ return x;
293
+ }
294
+ // We don't support logging arbitrary objects
295
+ console.error(`UnSupported Format of Logging Error Property for key ${key}:`, x);
296
+ return "REDACTED (arbitrary object)";
298
297
  }
299
298
 
300
299
  // checking type of x, returns false if x is null
301
300
  function isTelemetryEventPropertyValue(x: any): x is TelemetryEventPropertyType {
302
- switch (typeof x) {
303
- case "string":
304
- case "number":
305
- case "boolean":
306
- case "undefined":
307
- return true;
308
- default:
309
- return false;
310
- }
301
+ switch (typeof x) {
302
+ case "string":
303
+ case "number":
304
+ case "boolean":
305
+ case "undefined":
306
+ return true;
307
+ default:
308
+ return false;
309
+ }
311
310
  }
312
311
  /**
313
312
  * Walk an object's enumerable properties to find those fit for telemetry.
314
313
  */
315
314
  function getValidTelemetryProps(obj: any, keysToOmit: Set<string>): ITelemetryProperties {
316
- const props: ITelemetryProperties = {};
317
- for (const key of Object.keys(obj)) {
318
- if (keysToOmit.has(key)) {
319
- continue;
320
- }
321
- const val = obj[key];
322
-
323
- // ensure only valid props get logged, since props of logging error could be in any shape
324
- if (isTaggedTelemetryPropertyValue(val)) {
325
- props[key] = {
326
- value: filterValidTelemetryProps(val.value, key),
327
- tag: val.tag,
328
- };
329
- } else {
330
- props[key] = filterValidTelemetryProps(val, key);
331
- }
332
- }
333
- return props;
315
+ const props: ITelemetryProperties = {};
316
+ for (const key of Object.keys(obj)) {
317
+ if (keysToOmit.has(key)) {
318
+ continue;
319
+ }
320
+ const val = obj[key];
321
+
322
+ // ensure only valid props get logged, since props of logging error could be in any shape
323
+ if (isTaggedTelemetryPropertyValue(val)) {
324
+ props[key] = {
325
+ value: filterValidTelemetryProps(val.value, key),
326
+ tag: val.tag,
327
+ };
328
+ } else {
329
+ props[key] = filterValidTelemetryProps(val, key);
330
+ }
331
+ }
332
+ return props;
334
333
  }
335
334
 
336
335
  /**
@@ -339,18 +338,18 @@ function getValidTelemetryProps(obj: any, keysToOmit: Set<string>): ITelemetryPr
339
338
  * Avoids runtime errors with circular references.
340
339
  * Not ideal, as will cut values that are not necessarily circular references.
341
340
  * Could be improved by implementing Node's util.inspect() for browser (minus all the coloring code)
342
- */
341
+ */
343
342
  export const getCircularReplacer = () => {
344
- const seen = new WeakSet();
345
- return (key: string, value: any): any => {
346
- if (typeof value === "object" && value !== null) {
347
- if (seen.has(value)) {
348
- return "<removed/circular>";
349
- }
350
- seen.add(value);
351
- }
352
- return value;
353
- };
343
+ const seen = new WeakSet();
344
+ return (key: string, value: any): any => {
345
+ if (typeof value === "object" && value !== null) {
346
+ if (seen.has(value)) {
347
+ return "<removed/circular>";
348
+ }
349
+ seen.add(value);
350
+ }
351
+ return value;
352
+ };
354
353
  };
355
354
 
356
355
  /**
@@ -360,90 +359,94 @@ export const getCircularReplacer = () => {
360
359
  *
361
360
  * PLEASE take care to avoid setting sensitive data on this object without proper tagging!
362
361
  */
363
- export class LoggingError extends Error implements ILoggingError, Omit<IFluidErrorBase, "errorType"> {
364
- private _errorInstanceId = uuid();
365
- get errorInstanceId() { return this._errorInstanceId; }
366
- overwriteErrorInstanceId(id: string) { this._errorInstanceId = id; }
367
-
368
- /** Back-compat to appease isFluidError typeguard in old code that may handle this error */
369
- // @ts-expect-error - This field shouldn't be referenced in the current version, but needs to exist at runtime.
370
- private readonly fluidErrorCode: "-" = "-";
371
-
372
- /**
373
- * Create a new LoggingError
374
- * @param message - Error message to use for Error base class
375
- * @param props - telemetry props to include on the error for when it's logged
376
- * @param omitPropsFromLogging - properties by name to omit from telemetry props
377
- */
378
- constructor(
379
- message: string,
380
- props?: ITelemetryProperties,
381
- private readonly omitPropsFromLogging: Set<string> = new Set(),
382
- ) {
383
- super(message);
384
-
385
- // Don't log this list itself, or the private _errorInstanceId
386
- omitPropsFromLogging.add("omitPropsFromLogging");
387
- omitPropsFromLogging.add("_errorInstanceId");
388
-
389
- if (props) {
390
- this.addTelemetryProperties(props);
391
- }
392
- }
393
-
394
- /**
395
- * Determines if a given object is an instance of a LoggingError
396
- * @param object - any object
397
- * @returns - true if the object is an instance of a LoggingError, false if not.
398
- */
399
- public static typeCheck(object: unknown): object is LoggingError {
400
- if (typeof object === "object" && object !== null) {
401
- return typeof (object as LoggingError).addTelemetryProperties === "function"
402
- && typeof (object as LoggingError).getTelemetryProperties === "function"
403
- && typeof (object as LoggingError).errorInstanceId === "string";
404
- }
405
- return false;
406
- }
407
-
408
- /**
409
- * Add additional properties to be logged
410
- */
411
- public addTelemetryProperties(props: ITelemetryProperties) {
412
- copyProps(this, props);
413
- }
414
-
415
- /**
416
- * Get all properties fit to be logged to telemetry for this error
417
- */
418
- public getTelemetryProperties(): ITelemetryProperties {
419
- const taggableProps = getValidTelemetryProps(this, this.omitPropsFromLogging);
420
- // Include non-enumerable props that are not returned by getValidTelemetryProps
421
- return {
422
- ...taggableProps,
423
- stack: this.stack,
424
- message: this.message,
425
- errorInstanceId: this._errorInstanceId,
426
- };
427
- }
362
+ export class LoggingError
363
+ extends Error
364
+ implements ILoggingError, Omit<IFluidErrorBase, "errorType">
365
+ {
366
+ private _errorInstanceId = uuid();
367
+ get errorInstanceId() {
368
+ return this._errorInstanceId;
369
+ }
370
+ overwriteErrorInstanceId(id: string) {
371
+ this._errorInstanceId = id;
372
+ }
373
+
374
+ /** Back-compat to appease isFluidError typeguard in old code that may handle this error */
375
+ // @ts-expect-error - This field shouldn't be referenced in the current version, but needs to exist at runtime.
376
+ private readonly fluidErrorCode: "-" = "-";
377
+
378
+ /**
379
+ * Create a new LoggingError
380
+ * @param message - Error message to use for Error base class
381
+ * @param props - telemetry props to include on the error for when it's logged
382
+ * @param omitPropsFromLogging - properties by name to omit from telemetry props
383
+ */
384
+ constructor(
385
+ message: string,
386
+ props?: ITelemetryProperties,
387
+ private readonly omitPropsFromLogging: Set<string> = new Set(),
388
+ ) {
389
+ super(message);
390
+
391
+ // Don't log this list itself, or the private _errorInstanceId
392
+ omitPropsFromLogging.add("omitPropsFromLogging");
393
+ omitPropsFromLogging.add("_errorInstanceId");
394
+
395
+ if (props) {
396
+ this.addTelemetryProperties(props);
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Determines if a given object is an instance of a LoggingError
402
+ * @param object - any object
403
+ * @returns - true if the object is an instance of a LoggingError, false if not.
404
+ */
405
+ public static typeCheck(object: unknown): object is LoggingError {
406
+ if (typeof object === "object" && object !== null) {
407
+ return (
408
+ typeof (object as LoggingError).addTelemetryProperties === "function" &&
409
+ typeof (object as LoggingError).getTelemetryProperties === "function" &&
410
+ typeof (object as LoggingError).errorInstanceId === "string"
411
+ );
412
+ }
413
+ return false;
414
+ }
415
+
416
+ /**
417
+ * Add additional properties to be logged
418
+ */
419
+ public addTelemetryProperties(props: ITelemetryProperties) {
420
+ copyProps(this, props);
421
+ }
422
+
423
+ /**
424
+ * Get all properties fit to be logged to telemetry for this error
425
+ */
426
+ public getTelemetryProperties(): ITelemetryProperties {
427
+ const taggableProps = getValidTelemetryProps(this, this.omitPropsFromLogging);
428
+ // Include non-enumerable props that are not returned by getValidTelemetryProps
429
+ return {
430
+ ...taggableProps,
431
+ stack: this.stack,
432
+ message: this.message,
433
+ errorInstanceId: this._errorInstanceId,
434
+ };
435
+ }
428
436
  }
429
437
 
430
438
  /** The Error class used when normalizing an external error */
431
439
  export const NORMALIZED_ERROR_TYPE = "genericError";
432
440
  class NormalizedLoggingError extends LoggingError {
433
- // errorType "genericError" is used as a default value throughout the code.
434
- // Note that this matches ContainerErrorType/DriverErrorType's genericError
435
- errorType = NORMALIZED_ERROR_TYPE;
436
-
437
- constructor(
438
- errorProps: Pick<IFluidErrorBase,
439
- | "message"
440
- | "stack"
441
- >,
442
- ) {
443
- super(errorProps.message);
444
-
445
- if (errorProps.stack !== undefined) {
446
- overwriteStack(this, errorProps.stack);
447
- }
448
- }
441
+ // errorType "genericError" is used as a default value throughout the code.
442
+ // Note that this matches ContainerErrorType/DriverErrorType's genericError
443
+ errorType = NORMALIZED_ERROR_TYPE;
444
+
445
+ constructor(errorProps: Pick<IFluidErrorBase, "message" | "stack">) {
446
+ super(errorProps.message);
447
+
448
+ if (errorProps.stack !== undefined) {
449
+ overwriteStack(this, errorProps.stack);
450
+ }
451
+ }
449
452
  }