@fluidframework/telemetry-utils 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.224419
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-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 +267 -51
- 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 +267 -51
- 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.ts +290 -0
- package/lib/telemetry-utils-beta.d.ts +264 -0
- package/lib/telemetry-utils-public.d.ts +264 -0
- package/lib/telemetry-utils-untrimmed.d.ts +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 +966 -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/dist/errorLogging.d.ts
CHANGED
|
@@ -2,26 +2,43 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { ILoggingError,
|
|
5
|
+
import { ILoggingError, ITelemetryBaseProperties, Tagged } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { IFluidErrorBase } from "./fluidErrorBase";
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { ITelemetryLoggerExt, TelemetryEventPropertyTypeExt } from "./telemetryTypes";
|
|
8
|
+
/**
|
|
9
|
+
* Inspect the given error for common "safe" props and return them.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractLogSafeErrorProperties(error: unknown, sanitizeStack: boolean): {
|
|
9
14
|
message: string;
|
|
10
15
|
errorType?: string | undefined;
|
|
11
16
|
stack?: string | undefined;
|
|
12
17
|
};
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Type-guard for {@link @fluidframework/core-interfaces#ILoggingError}.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare const isILoggingError: (x: unknown) => x is ILoggingError;
|
|
24
|
+
/**
|
|
25
|
+
* Metadata to annotate an error object when annotating or normalizing it
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
16
29
|
export interface IFluidErrorAnnotations {
|
|
17
|
-
/**
|
|
18
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Telemetry props to log with the error
|
|
32
|
+
*/
|
|
33
|
+
props?: ITelemetryBaseProperties;
|
|
19
34
|
}
|
|
20
35
|
/**
|
|
21
36
|
* Normalize the given error yielding a valid Fluid Error
|
|
22
37
|
* @returns A valid Fluid Error with any provided annotations applied
|
|
23
38
|
* @param error - The error to normalize
|
|
24
39
|
* @param annotations - Annotations to apply to the normalized error
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
25
42
|
*/
|
|
26
43
|
export declare function normalizeError(error: unknown, annotations?: IFluidErrorAnnotations): IFluidErrorBase;
|
|
27
44
|
/**
|
|
@@ -32,8 +49,16 @@ export declare function normalizeError(error: unknown, annotations?: IFluidError
|
|
|
32
49
|
* For such cases it's better to not read stack property right away, but rather delay it until / if it's needed
|
|
33
50
|
* Some browsers will populate stack right away, others require throwing Error, so we do auto-detection on the fly.
|
|
34
51
|
* @returns Error object that has stack populated.
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
35
54
|
*/
|
|
36
55
|
export declare function generateErrorWithStack(): Error;
|
|
56
|
+
/**
|
|
57
|
+
* Generate a stack at this callsite as if an error were thrown from here.
|
|
58
|
+
* @returns the callstack (does not throw)
|
|
59
|
+
*
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
37
62
|
export declare function generateStack(): string | undefined;
|
|
38
63
|
/**
|
|
39
64
|
* Create a new error using newErrorFn, wrapping and caused by the given unknown error.
|
|
@@ -41,40 +66,69 @@ export declare function generateStack(): string | undefined;
|
|
|
41
66
|
* @param innerError - An error from untrusted/unknown origins
|
|
42
67
|
* @param newErrorFn - callback that will create a new error given the original error's message
|
|
43
68
|
* @returns A new error object "wrapping" the given error
|
|
69
|
+
*
|
|
70
|
+
* @internal
|
|
44
71
|
*/
|
|
45
72
|
export declare function wrapError<T extends LoggingError>(innerError: unknown, newErrorFn: (message: string) => T): T;
|
|
46
|
-
/**
|
|
47
|
-
|
|
73
|
+
/**
|
|
74
|
+
* The same as wrapError, but also logs the innerError, including the wrapping error's instance ID.
|
|
75
|
+
*
|
|
76
|
+
* @typeParam T - The kind of wrapper error to create.
|
|
77
|
+
*
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
export declare function wrapErrorAndLog<T extends LoggingError>(innerError: unknown, newErrorFn: (message: string) => T, logger: ITelemetryLoggerExt): T;
|
|
81
|
+
/**
|
|
82
|
+
* Attempts to overwrite the error's stack
|
|
83
|
+
*
|
|
84
|
+
* There have been reports of certain JS environments where overwriting stack will throw.
|
|
85
|
+
* If that happens, this adds the given stack as the telemetry property "stack2"
|
|
86
|
+
*
|
|
87
|
+
* @internal
|
|
88
|
+
*/
|
|
89
|
+
export declare function overwriteStack(error: IFluidErrorBase | LoggingError, stack: string): void;
|
|
48
90
|
/**
|
|
49
91
|
* True for any error object that is an (optionally normalized) external error
|
|
50
|
-
* False for any error we created and raised within the FF codebase
|
|
92
|
+
* False for any error we created and raised within the FF codebase via LoggingError base class,
|
|
93
|
+
* or wrapped in a well-known error type
|
|
94
|
+
*
|
|
95
|
+
* @internal
|
|
51
96
|
*/
|
|
52
|
-
export declare function isExternalError(
|
|
97
|
+
export declare function isExternalError(error: unknown): boolean;
|
|
53
98
|
/**
|
|
54
|
-
* Type guard to identify if a particular
|
|
99
|
+
* Type guard to identify if a particular telemetry property appears to be a
|
|
100
|
+
* {@link @fluidframework/core-interfaces#Tagged} telemetry property.
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
55
103
|
*/
|
|
56
|
-
export declare function isTaggedTelemetryPropertyValue(x:
|
|
104
|
+
export declare function isTaggedTelemetryPropertyValue(x: Tagged<TelemetryEventPropertyTypeExt> | TelemetryEventPropertyTypeExt): x is Tagged<TelemetryEventPropertyTypeExt>;
|
|
57
105
|
/**
|
|
58
106
|
* Borrowed from
|
|
59
107
|
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value#examples}
|
|
60
108
|
* Avoids runtime errors with circular references.
|
|
61
109
|
* Not ideal, as will cut values that are not necessarily circular references.
|
|
62
110
|
* Could be improved by implementing Node's util.inspect() for browser (minus all the coloring code)
|
|
63
|
-
|
|
64
|
-
|
|
111
|
+
*
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
export declare const getCircularReplacer: () => (key: string, value: unknown) => any;
|
|
65
115
|
/**
|
|
66
116
|
* Base class for "trusted" errors we create, whose properties can generally be logged to telemetry safely.
|
|
67
117
|
* All properties set on the object, or passed in (via the constructor or addTelemetryProperties),
|
|
68
118
|
* will be logged in accordance with their tag, if present.
|
|
69
119
|
*
|
|
70
120
|
* PLEASE take care to avoid setting sensitive data on this object without proper tagging!
|
|
121
|
+
*
|
|
122
|
+
* @internal
|
|
71
123
|
*/
|
|
72
124
|
export declare class LoggingError extends Error implements ILoggingError, Omit<IFluidErrorBase, "errorType"> {
|
|
73
125
|
private readonly omitPropsFromLogging;
|
|
74
126
|
private _errorInstanceId;
|
|
75
127
|
get errorInstanceId(): string;
|
|
76
128
|
overwriteErrorInstanceId(id: string): void;
|
|
77
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Backwards compatibility to appease {@link isFluidError} in old code that may handle this error.
|
|
131
|
+
*/
|
|
78
132
|
private readonly fluidErrorCode;
|
|
79
133
|
/**
|
|
80
134
|
* Create a new LoggingError
|
|
@@ -82,14 +136,26 @@ export declare class LoggingError extends Error implements ILoggingError, Omit<I
|
|
|
82
136
|
* @param props - telemetry props to include on the error for when it's logged
|
|
83
137
|
* @param omitPropsFromLogging - properties by name to omit from telemetry props
|
|
84
138
|
*/
|
|
85
|
-
constructor(message: string, props?:
|
|
139
|
+
constructor(message: string, props?: ITelemetryBaseProperties, omitPropsFromLogging?: Set<string>);
|
|
140
|
+
/**
|
|
141
|
+
* Determines if a given object is an instance of a LoggingError
|
|
142
|
+
* @param object - any object
|
|
143
|
+
* @returns true if the object is an instance of a LoggingError, false if not.
|
|
144
|
+
*/
|
|
145
|
+
static typeCheck(object: unknown): object is LoggingError;
|
|
86
146
|
/**
|
|
87
147
|
* Add additional properties to be logged
|
|
88
148
|
*/
|
|
89
|
-
addTelemetryProperties(props:
|
|
149
|
+
addTelemetryProperties(props: ITelemetryBaseProperties): void;
|
|
90
150
|
/**
|
|
91
151
|
* Get all properties fit to be logged to telemetry for this error
|
|
92
152
|
*/
|
|
93
|
-
getTelemetryProperties():
|
|
153
|
+
getTelemetryProperties(): ITelemetryBaseProperties;
|
|
94
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* The Error class used when normalizing an external error
|
|
157
|
+
*
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
export declare const NORMALIZED_ERROR_TYPE = "genericError";
|
|
95
161
|
//# sourceMappingURL=errorLogging.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorLogging.d.ts","sourceRoot":"","sources":["../src/errorLogging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"errorLogging.d.ts","sourceRoot":"","sources":["../src/errorLogging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,aAAa,EACb,wBAAwB,EAExB,MAAM,EACN,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAEN,eAAe,EAGf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAStF;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC5C,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,OAAO,GACpB;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,CAoCA;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,MAAO,OAAO,uBACkC,CAAC;AAgB7E;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC;;OAEG;IACH,KAAK,CAAC,EAAE,wBAAwB,CAAC;CACjC;AAeD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,OAAO,EACd,WAAW,GAAE,sBAA2B,GACtC,eAAe,CAqDjB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,IAAI,KAAK,CAgB9C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,YAAY,EAC/C,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,GAChC,CAAC,CA6BH;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EACrD,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,EAClC,MAAM,EAAE,mBAAmB,GACzB,CAAC,CAmBH;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAMzF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWvD;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC7C,CAAC,EAAE,MAAM,CAAC,6BAA6B,CAAC,GAAG,6BAA6B,GACtE,CAAC,IAAI,MAAM,CAAC,6BAA6B,CAAC,CAE5C;AA2DD;;;;;;;;GAQG;AAGH,eAAO,MAAM,mBAAmB,cAAc,MAAM,SAAS,OAAO,KAAK,GAWxE,CAAC;AAGF;;;;;;;;GAQG;AACH,qBAAa,YACZ,SAAQ,KACR,YAAW,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC;IA0B3D,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAxBtC,OAAO,CAAC,gBAAgB,CAAU;IAClC,IAAI,eAAe,IAAI,MAAM,CAE5B;IACD,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI1C;;OAEG;IAGH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAY;IAE3C;;;;;OAKG;gBAEF,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,wBAAwB,EACf,oBAAoB,GAAE,GAAG,CAAC,MAAM,CAAa;IAa/D;;;;OAIG;WACW,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,YAAY;IAWhE;;OAEG;IACI,sBAAsB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAIpE;;OAEG;IACI,sBAAsB,IAAI,wBAAwB;CAUzD;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,iBAAiB,CAAC"}
|
package/dist/errorLogging.js
CHANGED
|
@@ -4,14 +4,20 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.LoggingError = exports.getCircularReplacer = exports.isTaggedTelemetryPropertyValue = exports.isExternalError = exports.wrapErrorAndLog = exports.wrapError = exports.generateStack = exports.generateErrorWithStack = exports.normalizeError = exports.isILoggingError = exports.extractLogSafeErrorProperties = void 0;
|
|
7
|
+
exports.NORMALIZED_ERROR_TYPE = exports.LoggingError = exports.getCircularReplacer = exports.isTaggedTelemetryPropertyValue = exports.isExternalError = exports.overwriteStack = exports.wrapErrorAndLog = exports.wrapError = exports.generateStack = exports.generateErrorWithStack = exports.normalizeError = exports.isILoggingError = exports.extractLogSafeErrorProperties = void 0;
|
|
8
8
|
const uuid_1 = require("uuid");
|
|
9
9
|
const fluidErrorBase_1 = require("./fluidErrorBase");
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Determines if the provided value is an object but neither null nor an array.
|
|
12
|
+
*/
|
|
11
13
|
const isRegularObject = (value) => {
|
|
12
14
|
return value !== null && !Array.isArray(value) && typeof value === "object";
|
|
13
15
|
};
|
|
14
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Inspect the given error for common "safe" props and return them.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
15
21
|
function extractLogSafeErrorProperties(error, sanitizeStack) {
|
|
16
22
|
const removeMessageFromStack = (stack, errorName) => {
|
|
17
23
|
if (!sanitizeStack) {
|
|
@@ -24,7 +30,7 @@ function extractLogSafeErrorProperties(error, sanitizeStack) {
|
|
|
24
30
|
}
|
|
25
31
|
return stackFrames.join("\n");
|
|
26
32
|
};
|
|
27
|
-
const message =
|
|
33
|
+
const message = typeof error?.message === "string"
|
|
28
34
|
? error.message
|
|
29
35
|
: String(error);
|
|
30
36
|
const safeProps = {
|
|
@@ -36,17 +42,23 @@ function extractLogSafeErrorProperties(error, sanitizeStack) {
|
|
|
36
42
|
safeProps.errorType = errorType;
|
|
37
43
|
}
|
|
38
44
|
if (typeof stack === "string") {
|
|
39
|
-
const errorName =
|
|
45
|
+
const errorName = typeof name === "string" ? name : undefined;
|
|
40
46
|
safeProps.stack = removeMessageFromStack(stack, errorName);
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
return safeProps;
|
|
44
50
|
}
|
|
45
51
|
exports.extractLogSafeErrorProperties = extractLogSafeErrorProperties;
|
|
46
|
-
/**
|
|
47
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Type-guard for {@link @fluidframework/core-interfaces#ILoggingError}.
|
|
54
|
+
*
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
const isILoggingError = (x) => typeof x?.getTelemetryProperties === "function";
|
|
48
58
|
exports.isILoggingError = isILoggingError;
|
|
49
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Copy props from source onto target, but do not overwrite an existing prop that matches
|
|
61
|
+
*/
|
|
50
62
|
function copyProps(target, source) {
|
|
51
63
|
for (const key of Object.keys(source)) {
|
|
52
64
|
if (target[key] === undefined) {
|
|
@@ -54,8 +66,11 @@ function copyProps(target, source) {
|
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
68
|
}
|
|
57
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* For backwards compatibility with pre-errorInstanceId valid errors
|
|
71
|
+
*/
|
|
58
72
|
function patchLegacyError(legacyError) {
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
|
59
74
|
const patchMe = legacyError;
|
|
60
75
|
if (patchMe.errorInstanceId === undefined) {
|
|
61
76
|
patchMe.errorInstanceId = (0, uuid_1.v4)();
|
|
@@ -66,21 +81,22 @@ function patchLegacyError(legacyError) {
|
|
|
66
81
|
* @returns A valid Fluid Error with any provided annotations applied
|
|
67
82
|
* @param error - The error to normalize
|
|
68
83
|
* @param annotations - Annotations to apply to the normalized error
|
|
84
|
+
*
|
|
85
|
+
* @internal
|
|
69
86
|
*/
|
|
70
87
|
function normalizeError(error, annotations = {}) {
|
|
71
|
-
var _a;
|
|
72
88
|
// Back-compat, while IFluidErrorBase is rolled out
|
|
73
89
|
if ((0, fluidErrorBase_1.isValidLegacyError)(error)) {
|
|
74
90
|
patchLegacyError(error);
|
|
75
91
|
}
|
|
76
92
|
if ((0, fluidErrorBase_1.isFluidError)(error)) {
|
|
77
93
|
// We can simply add the telemetry props to the error and return it
|
|
78
|
-
error.addTelemetryProperties(
|
|
94
|
+
error.addTelemetryProperties(annotations.props ?? {});
|
|
79
95
|
return error;
|
|
80
96
|
}
|
|
81
97
|
// We have to construct a new Fluid Error, copying safe properties over
|
|
82
98
|
const { message, stack } = extractLogSafeErrorProperties(error, false /* sanitizeStack */);
|
|
83
|
-
const fluidError = new
|
|
99
|
+
const fluidError = new NormalizedLoggingError({
|
|
84
100
|
message,
|
|
85
101
|
stack,
|
|
86
102
|
});
|
|
@@ -88,15 +104,31 @@ function normalizeError(error, annotations = {}) {
|
|
|
88
104
|
// Anywhere they are set should be on a valid Fluid Error that would have been returned above,
|
|
89
105
|
// but we can't prove it with the types, so adding this defensive measure.
|
|
90
106
|
if (typeof error === "object" && error !== null) {
|
|
91
|
-
const
|
|
92
|
-
|
|
107
|
+
const maybeHasRetry = error;
|
|
108
|
+
let retryProps;
|
|
109
|
+
if ("canRetry" in error) {
|
|
110
|
+
retryProps ?? (retryProps = {});
|
|
111
|
+
retryProps.canRetry = maybeHasRetry.canRetry;
|
|
112
|
+
}
|
|
113
|
+
if ("retryAfterSeconds" in error) {
|
|
114
|
+
retryProps ?? (retryProps = {});
|
|
115
|
+
retryProps.retryAfterSeconds = maybeHasRetry.retryAfterSeconds;
|
|
116
|
+
}
|
|
117
|
+
if (retryProps !== undefined) {
|
|
118
|
+
Object.assign(fluidError, retryProps);
|
|
119
|
+
}
|
|
93
120
|
}
|
|
94
|
-
if (typeof
|
|
121
|
+
if (typeof error !== "object") {
|
|
95
122
|
// This is only interesting for non-objects
|
|
96
|
-
fluidError.addTelemetryProperties({ typeofError: typeof
|
|
123
|
+
fluidError.addTelemetryProperties({ typeofError: typeof error });
|
|
97
124
|
}
|
|
98
|
-
const
|
|
99
|
-
|
|
125
|
+
const errorTelemetryProps = LoggingError.typeCheck(error)
|
|
126
|
+
? error.getTelemetryProperties()
|
|
127
|
+
: { untrustedOrigin: 1 }; // This will let us filter errors that did not originate from our own codebase
|
|
128
|
+
fluidError.addTelemetryProperties({
|
|
129
|
+
...errorTelemetryProps,
|
|
130
|
+
...annotations.props,
|
|
131
|
+
});
|
|
100
132
|
return fluidError;
|
|
101
133
|
}
|
|
102
134
|
exports.normalizeError = normalizeError;
|
|
@@ -109,11 +141,13 @@ let stackPopulatedOnCreation;
|
|
|
109
141
|
* For such cases it's better to not read stack property right away, but rather delay it until / if it's needed
|
|
110
142
|
* Some browsers will populate stack right away, others require throwing Error, so we do auto-detection on the fly.
|
|
111
143
|
* @returns Error object that has stack populated.
|
|
144
|
+
*
|
|
145
|
+
* @internal
|
|
112
146
|
*/
|
|
113
147
|
function generateErrorWithStack() {
|
|
114
148
|
const err = new Error("<<generated stack>>");
|
|
115
149
|
if (stackPopulatedOnCreation === undefined) {
|
|
116
|
-
stackPopulatedOnCreation =
|
|
150
|
+
stackPopulatedOnCreation = err.stack !== undefined;
|
|
117
151
|
}
|
|
118
152
|
if (stackPopulatedOnCreation) {
|
|
119
153
|
return err;
|
|
@@ -121,11 +155,17 @@ function generateErrorWithStack() {
|
|
|
121
155
|
try {
|
|
122
156
|
throw err;
|
|
123
157
|
}
|
|
124
|
-
catch (
|
|
125
|
-
return
|
|
158
|
+
catch (error) {
|
|
159
|
+
return error;
|
|
126
160
|
}
|
|
127
161
|
}
|
|
128
162
|
exports.generateErrorWithStack = generateErrorWithStack;
|
|
163
|
+
/**
|
|
164
|
+
* Generate a stack at this callsite as if an error were thrown from here.
|
|
165
|
+
* @returns the callstack (does not throw)
|
|
166
|
+
*
|
|
167
|
+
* @internal
|
|
168
|
+
*/
|
|
129
169
|
function generateStack() {
|
|
130
170
|
return generateErrorWithStack().stack;
|
|
131
171
|
}
|
|
@@ -136,9 +176,11 @@ exports.generateStack = generateStack;
|
|
|
136
176
|
* @param innerError - An error from untrusted/unknown origins
|
|
137
177
|
* @param newErrorFn - callback that will create a new error given the original error's message
|
|
138
178
|
* @returns A new error object "wrapping" the given error
|
|
179
|
+
*
|
|
180
|
+
* @internal
|
|
139
181
|
*/
|
|
140
182
|
function wrapError(innerError, newErrorFn) {
|
|
141
|
-
const { message, stack
|
|
183
|
+
const { message, stack } = extractLogSafeErrorProperties(innerError, false /* sanitizeStack */);
|
|
142
184
|
const newError = newErrorFn(message);
|
|
143
185
|
if (stack !== undefined) {
|
|
144
186
|
overwriteStack(newError, stack);
|
|
@@ -161,7 +203,13 @@ function wrapError(innerError, newErrorFn) {
|
|
|
161
203
|
return newError;
|
|
162
204
|
}
|
|
163
205
|
exports.wrapError = wrapError;
|
|
164
|
-
/**
|
|
206
|
+
/**
|
|
207
|
+
* The same as wrapError, but also logs the innerError, including the wrapping error's instance ID.
|
|
208
|
+
*
|
|
209
|
+
* @typeParam T - The kind of wrapper error to create.
|
|
210
|
+
*
|
|
211
|
+
* @internal
|
|
212
|
+
*/
|
|
165
213
|
function wrapErrorAndLog(innerError, newErrorFn, logger) {
|
|
166
214
|
const newError = wrapError(innerError, newErrorFn);
|
|
167
215
|
// This will match innerError.errorInstanceId if present (see wrapError)
|
|
@@ -176,32 +224,84 @@ function wrapErrorAndLog(innerError, newErrorFn, logger) {
|
|
|
176
224
|
return newError;
|
|
177
225
|
}
|
|
178
226
|
exports.wrapErrorAndLog = wrapErrorAndLog;
|
|
227
|
+
/**
|
|
228
|
+
* Attempts to overwrite the error's stack
|
|
229
|
+
*
|
|
230
|
+
* There have been reports of certain JS environments where overwriting stack will throw.
|
|
231
|
+
* If that happens, this adds the given stack as the telemetry property "stack2"
|
|
232
|
+
*
|
|
233
|
+
* @internal
|
|
234
|
+
*/
|
|
179
235
|
function overwriteStack(error, stack) {
|
|
180
|
-
// supposedly setting stack on an Error can throw.
|
|
181
236
|
try {
|
|
182
237
|
Object.assign(error, { stack });
|
|
183
238
|
}
|
|
184
|
-
catch
|
|
239
|
+
catch {
|
|
185
240
|
error.addTelemetryProperties({ stack2: stack });
|
|
186
241
|
}
|
|
187
242
|
}
|
|
243
|
+
exports.overwriteStack = overwriteStack;
|
|
188
244
|
/**
|
|
189
245
|
* True for any error object that is an (optionally normalized) external error
|
|
190
|
-
* False for any error we created and raised within the FF codebase
|
|
246
|
+
* False for any error we created and raised within the FF codebase via LoggingError base class,
|
|
247
|
+
* or wrapped in a well-known error type
|
|
248
|
+
*
|
|
249
|
+
* @internal
|
|
191
250
|
*/
|
|
192
|
-
function isExternalError(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
251
|
+
function isExternalError(error) {
|
|
252
|
+
// LoggingErrors are an internal FF error type. However, an external error can be converted
|
|
253
|
+
// into a LoggingError if it is normalized. In this case we must use the untrustedOrigin flag to
|
|
254
|
+
// determine whether the original error was infact external.
|
|
255
|
+
if (LoggingError.typeCheck(error)) {
|
|
256
|
+
if (error.errorType === exports.NORMALIZED_ERROR_TYPE) {
|
|
257
|
+
return error.getTelemetryProperties().untrustedOrigin === 1;
|
|
258
|
+
}
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
return !(0, fluidErrorBase_1.isValidLegacyError)(error);
|
|
196
262
|
}
|
|
197
263
|
exports.isExternalError = isExternalError;
|
|
198
264
|
/**
|
|
199
|
-
* Type guard to identify if a particular
|
|
265
|
+
* Type guard to identify if a particular telemetry property appears to be a
|
|
266
|
+
* {@link @fluidframework/core-interfaces#Tagged} telemetry property.
|
|
267
|
+
*
|
|
268
|
+
* @internal
|
|
200
269
|
*/
|
|
201
270
|
function isTaggedTelemetryPropertyValue(x) {
|
|
202
|
-
return
|
|
271
|
+
return typeof x?.tag === "string";
|
|
203
272
|
}
|
|
204
273
|
exports.isTaggedTelemetryPropertyValue = isTaggedTelemetryPropertyValue;
|
|
274
|
+
/**
|
|
275
|
+
* Filter serializable telemetry properties
|
|
276
|
+
* @param x - Any telemetry prop
|
|
277
|
+
* @returns As-is if x is primitive. returns stringified if x is an array of primitive.
|
|
278
|
+
* otherwise returns null since this is what we support at the moment.
|
|
279
|
+
*/
|
|
280
|
+
function filterValidTelemetryProps(x, key) {
|
|
281
|
+
if (Array.isArray(x) && x.every((val) => isTelemetryEventPropertyValue(val))) {
|
|
282
|
+
return JSON.stringify(x);
|
|
283
|
+
}
|
|
284
|
+
if (isTelemetryEventPropertyValue(x)) {
|
|
285
|
+
return x;
|
|
286
|
+
}
|
|
287
|
+
// We don't support logging arbitrary objects
|
|
288
|
+
console.error(`UnSupported Format of Logging Error Property for key ${key}:`, x);
|
|
289
|
+
return "REDACTED (arbitrary object)";
|
|
290
|
+
}
|
|
291
|
+
// checking type of x, returns false if x is null
|
|
292
|
+
function isTelemetryEventPropertyValue(x) {
|
|
293
|
+
switch (typeof x) {
|
|
294
|
+
case "string":
|
|
295
|
+
case "number":
|
|
296
|
+
case "boolean":
|
|
297
|
+
case "undefined": {
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
default: {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
205
305
|
/**
|
|
206
306
|
* Walk an object's enumerable properties to find those fit for telemetry.
|
|
207
307
|
*/
|
|
@@ -212,24 +312,13 @@ function getValidTelemetryProps(obj, keysToOmit) {
|
|
|
212
312
|
continue;
|
|
213
313
|
}
|
|
214
314
|
const val = obj[key];
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
props[key] = val;
|
|
221
|
-
break;
|
|
222
|
-
default: {
|
|
223
|
-
if (isTaggedTelemetryPropertyValue(val)) {
|
|
224
|
-
props[key] = val;
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
// We don't support logging arbitrary objects
|
|
228
|
-
props[key] = "REDACTED (arbitrary object)";
|
|
229
|
-
}
|
|
230
|
-
break;
|
|
315
|
+
// ensure only valid props get logged, since props of logging error could be in any shape
|
|
316
|
+
props[key] = isTaggedTelemetryPropertyValue(val)
|
|
317
|
+
? {
|
|
318
|
+
value: filterValidTelemetryProps(val.value, key),
|
|
319
|
+
tag: val.tag,
|
|
231
320
|
}
|
|
232
|
-
|
|
321
|
+
: filterValidTelemetryProps(val, key);
|
|
233
322
|
}
|
|
234
323
|
return props;
|
|
235
324
|
}
|
|
@@ -239,7 +328,11 @@ function getValidTelemetryProps(obj, keysToOmit) {
|
|
|
239
328
|
* Avoids runtime errors with circular references.
|
|
240
329
|
* Not ideal, as will cut values that are not necessarily circular references.
|
|
241
330
|
* Could be improved by implementing Node's util.inspect() for browser (minus all the coloring code)
|
|
242
|
-
|
|
331
|
+
*
|
|
332
|
+
* @internal
|
|
333
|
+
*/
|
|
334
|
+
// TODO: Use `unknown` instead (API breaking change)
|
|
335
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
243
336
|
const getCircularReplacer = () => {
|
|
244
337
|
const seen = new WeakSet();
|
|
245
338
|
return (key, value) => {
|
|
@@ -253,14 +346,23 @@ const getCircularReplacer = () => {
|
|
|
253
346
|
};
|
|
254
347
|
};
|
|
255
348
|
exports.getCircularReplacer = getCircularReplacer;
|
|
349
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
256
350
|
/**
|
|
257
351
|
* Base class for "trusted" errors we create, whose properties can generally be logged to telemetry safely.
|
|
258
352
|
* All properties set on the object, or passed in (via the constructor or addTelemetryProperties),
|
|
259
353
|
* will be logged in accordance with their tag, if present.
|
|
260
354
|
*
|
|
261
355
|
* PLEASE take care to avoid setting sensitive data on this object without proper tagging!
|
|
356
|
+
*
|
|
357
|
+
* @internal
|
|
262
358
|
*/
|
|
263
359
|
class LoggingError extends Error {
|
|
360
|
+
get errorInstanceId() {
|
|
361
|
+
return this._errorInstanceId;
|
|
362
|
+
}
|
|
363
|
+
overwriteErrorInstanceId(id) {
|
|
364
|
+
this._errorInstanceId = id;
|
|
365
|
+
}
|
|
264
366
|
/**
|
|
265
367
|
* Create a new LoggingError
|
|
266
368
|
* @param message - Error message to use for Error base class
|
|
@@ -271,8 +373,11 @@ class LoggingError extends Error {
|
|
|
271
373
|
super(message);
|
|
272
374
|
this.omitPropsFromLogging = omitPropsFromLogging;
|
|
273
375
|
this._errorInstanceId = (0, uuid_1.v4)();
|
|
274
|
-
/**
|
|
376
|
+
/**
|
|
377
|
+
* Backwards compatibility to appease {@link isFluidError} in old code that may handle this error.
|
|
378
|
+
*/
|
|
275
379
|
// @ts-expect-error - This field shouldn't be referenced in the current version, but needs to exist at runtime.
|
|
380
|
+
// eslint-disable-next-line @typescript-eslint/prefer-as-const
|
|
276
381
|
this.fluidErrorCode = "-";
|
|
277
382
|
// Don't log this list itself, or the private _errorInstanceId
|
|
278
383
|
omitPropsFromLogging.add("omitPropsFromLogging");
|
|
@@ -281,8 +386,19 @@ class LoggingError extends Error {
|
|
|
281
386
|
this.addTelemetryProperties(props);
|
|
282
387
|
}
|
|
283
388
|
}
|
|
284
|
-
|
|
285
|
-
|
|
389
|
+
/**
|
|
390
|
+
* Determines if a given object is an instance of a LoggingError
|
|
391
|
+
* @param object - any object
|
|
392
|
+
* @returns true if the object is an instance of a LoggingError, false if not.
|
|
393
|
+
*/
|
|
394
|
+
static typeCheck(object) {
|
|
395
|
+
if (typeof object === "object" && object !== null) {
|
|
396
|
+
return (typeof object.addTelemetryProperties === "function" &&
|
|
397
|
+
typeof object.getTelemetryProperties === "function" &&
|
|
398
|
+
typeof object.errorInstanceId === "string");
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
286
402
|
/**
|
|
287
403
|
* Add additional properties to be logged
|
|
288
404
|
*/
|
|
@@ -295,21 +411,35 @@ class LoggingError extends Error {
|
|
|
295
411
|
getTelemetryProperties() {
|
|
296
412
|
const taggableProps = getValidTelemetryProps(this, this.omitPropsFromLogging);
|
|
297
413
|
// Include non-enumerable props that are not returned by getValidTelemetryProps
|
|
298
|
-
return
|
|
414
|
+
return {
|
|
415
|
+
...taggableProps,
|
|
416
|
+
stack: this.stack,
|
|
417
|
+
message: this.message,
|
|
418
|
+
errorInstanceId: this._errorInstanceId,
|
|
419
|
+
};
|
|
299
420
|
}
|
|
300
421
|
}
|
|
301
422
|
exports.LoggingError = LoggingError;
|
|
302
|
-
/**
|
|
303
|
-
class
|
|
423
|
+
/**
|
|
424
|
+
* The Error class used when normalizing an external error
|
|
425
|
+
*
|
|
426
|
+
* @internal
|
|
427
|
+
*/
|
|
428
|
+
exports.NORMALIZED_ERROR_TYPE = "genericError";
|
|
429
|
+
/**
|
|
430
|
+
* Subclass of LoggingError returned by normalizeError
|
|
431
|
+
*
|
|
432
|
+
* @internal
|
|
433
|
+
*/
|
|
434
|
+
class NormalizedLoggingError extends LoggingError {
|
|
304
435
|
constructor(errorProps) {
|
|
305
436
|
super(errorProps.message);
|
|
306
|
-
|
|
437
|
+
// errorType "genericError" is used as a default value throughout the code.
|
|
438
|
+
// Note that this matches ContainerErrorType/DriverErrorType's genericError
|
|
439
|
+
this.errorType = exports.NORMALIZED_ERROR_TYPE;
|
|
307
440
|
if (errorProps.stack !== undefined) {
|
|
308
441
|
overwriteStack(this, errorProps.stack);
|
|
309
442
|
}
|
|
310
443
|
}
|
|
311
444
|
}
|
|
312
|
-
// errorType "genericError" is used as a default value throughout the code.
|
|
313
|
-
// Note that this matches ContainerErrorType/DriverErrorType's genericError
|
|
314
|
-
NormalizedExternalError.normalizedErrorType = "genericError";
|
|
315
445
|
//# sourceMappingURL=errorLogging.js.map
|