@fluidframework/telemetry-utils 2.81.1 → 2.82.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.
- package/CHANGELOG.md +4 -0
- package/dist/error.d.ts +13 -8
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +85 -40
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/lib/error.d.ts +13 -8
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +85 -40
- package/lib/error.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +8 -8
- package/src/error.ts +155 -85
- package/src/index.ts +1 -0
- package/biome.jsonc +0 -4
package/CHANGELOG.md
CHANGED
package/dist/error.d.ts
CHANGED
|
@@ -8,6 +8,11 @@ import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitio
|
|
|
8
8
|
import { LoggingError } from "./errorLogging.js";
|
|
9
9
|
import type { IFluidErrorBase } from "./fluidErrorBase.js";
|
|
10
10
|
import type { ITelemetryPropertiesExt } from "./telemetryTypes.js";
|
|
11
|
+
/**
|
|
12
|
+
* A subset of `ISequencedDocumentMessage` properties that are safe to log for telemetry.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export type MessageLike = Partial<Pick<ISequencedDocumentMessage, "clientId" | "sequenceNumber" | "clientSequenceNumber" | "referenceSequenceNumber" | "minimumSequenceNumber" | "timestamp">>;
|
|
11
16
|
/**
|
|
12
17
|
* Throws a UsageError with the given message if the condition is not met.
|
|
13
18
|
* Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).
|
|
@@ -53,6 +58,10 @@ export declare class DataCorruptionError extends LoggingError implements IErrorB
|
|
|
53
58
|
readonly errorType: "dataCorruptionError";
|
|
54
59
|
readonly canRetry = false;
|
|
55
60
|
constructor(message: string, props: ITelemetryBaseProperties);
|
|
61
|
+
/**
|
|
62
|
+
* Create a new `DataCorruptionError` detected and raised within the Fluid Framework.
|
|
63
|
+
*/
|
|
64
|
+
static create(errorMessage: string, dataCorruptionCodepath: string, messageLike?: MessageLike, props?: ITelemetryPropertiesExt, stackTraceLimit?: number): IFluidErrorBase;
|
|
56
65
|
}
|
|
57
66
|
/**
|
|
58
67
|
* Indicates we hit a fatal error while processing incoming data from the Fluid Service.
|
|
@@ -75,18 +84,14 @@ export declare class DataProcessingError extends LoggingError implements IErrorB
|
|
|
75
84
|
/**
|
|
76
85
|
* Create a new `DataProcessingError` detected and raised within the Fluid Framework.
|
|
77
86
|
*/
|
|
78
|
-
static create(errorMessage: string, dataProcessingCodepath: string, messageLike?:
|
|
87
|
+
static create(errorMessage: string, dataProcessingCodepath: string, messageLike?: MessageLike, props?: ITelemetryPropertiesExt, stackTraceLimit?: number): IFluidErrorBase;
|
|
79
88
|
/**
|
|
80
89
|
* Wrap the given error in a `DataProcessingError`, unless the error is already of a known type
|
|
81
90
|
* with the exception of a normalized {@link LoggingError}, which will still be wrapped.
|
|
82
91
|
*
|
|
83
92
|
* In either case, the error will have some relevant properties added for telemetry.
|
|
84
93
|
*
|
|
85
|
-
* @remarks
|
|
86
|
-
*
|
|
87
|
-
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
88
|
-
* one day we will move away from throwing these errors but rather we'll return them.
|
|
89
|
-
* But an unrecognized error needs to be classified as `DataProcessingError`.
|
|
94
|
+
* @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.
|
|
90
95
|
*
|
|
91
96
|
* @param originalError - The error to be converted.
|
|
92
97
|
* @param dataProcessingCodepath - Which code-path failed while processing data.
|
|
@@ -94,7 +99,7 @@ export declare class DataProcessingError extends LoggingError implements IErrorB
|
|
|
94
99
|
*
|
|
95
100
|
* @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.
|
|
96
101
|
*/
|
|
97
|
-
static wrapIfUnrecognized(originalError: unknown, dataProcessingCodepath: string, messageLike?:
|
|
102
|
+
static wrapIfUnrecognized(originalError: unknown, dataProcessingCodepath: string, messageLike?: MessageLike): IFluidErrorBase;
|
|
98
103
|
}
|
|
99
104
|
/**
|
|
100
105
|
* Error indicating that two Fluid layers are incompatible.
|
|
@@ -128,7 +133,7 @@ export declare class LayerIncompatibilityError extends LoggingError implements I
|
|
|
128
133
|
*
|
|
129
134
|
* @internal
|
|
130
135
|
*/
|
|
131
|
-
export declare const extractSafePropertiesFromMessage: (messageLike:
|
|
136
|
+
export declare const extractSafePropertiesFromMessage: (messageLike: MessageLike) => {
|
|
132
137
|
messageClientId: string | undefined;
|
|
133
138
|
messageSequenceNumber: number | undefined;
|
|
134
139
|
messageClientSequenceNumber: number | undefined;
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC5F,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,EAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAE7F,OAAO,EACN,YAAY,EAKZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,wBAAwB,GAC9B,OAAO,CAAC,SAAS,CAInB;
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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"}
|
package/dist/error.js
CHANGED
|
@@ -22,6 +22,82 @@ function validatePrecondition(condition, message, props) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
exports.validatePrecondition = validatePrecondition;
|
|
25
|
+
/**
|
|
26
|
+
* Creates an error during data processing (DataProcessingError or DataCorruptionError) with telemetry properties.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* This helper allows customizing the stack trace limit during error creation, which is useful
|
|
30
|
+
* for capturing more context in error scenarios. It delegates to {@link wrapOrAnnotateError}
|
|
31
|
+
* for the actual error wrapping/annotation logic.
|
|
32
|
+
*
|
|
33
|
+
* @param factory - Factory function that creates the specific error type.
|
|
34
|
+
* @param errorMessage - The error message to use.
|
|
35
|
+
* @param codepath - Identifier for the code path where the error was detected.
|
|
36
|
+
* @param messageLike - Optional message properties to include in telemetry.
|
|
37
|
+
* @param props - Additional telemetry properties to attach to the error.
|
|
38
|
+
* @param stackTraceLimit - Optional limit for the stack trace depth.
|
|
39
|
+
* @returns The created error with telemetry properties attached.
|
|
40
|
+
*/
|
|
41
|
+
function buildDataProcessingError(factory, errorMessage, codepath, messageLike, props = {}, stackTraceLimit) {
|
|
42
|
+
const ErrorConfig = Error;
|
|
43
|
+
const originalStackTraceLimit = ErrorConfig.stackTraceLimit;
|
|
44
|
+
try {
|
|
45
|
+
if (stackTraceLimit !== undefined) {
|
|
46
|
+
ErrorConfig.stackTraceLimit = stackTraceLimit;
|
|
47
|
+
}
|
|
48
|
+
const error = wrapDataProcessingErrorIfUnrecognized(factory, errorMessage, codepath, messageLike);
|
|
49
|
+
error.addTelemetryProperties(props);
|
|
50
|
+
return error;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
// Reset the stack trace limit to the original value
|
|
54
|
+
if (stackTraceLimit !== undefined) {
|
|
55
|
+
ErrorConfig.stackTraceLimit = originalStackTraceLimit;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Wraps an unrecognized error into a data processing error (DataProcessingError or DataCorruptionError)
|
|
61
|
+
* using the provided factory.
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* This function handles two cases:
|
|
65
|
+
* - **Unrecognized/external errors**: Wrapped using the provided factory function to create a proper
|
|
66
|
+
* Fluid error type (DataProcessingError or DataCorruptionError).
|
|
67
|
+
* - **Recognized Fluid errors**: Not wrapped, but annotated with data processing telemetry properties.
|
|
68
|
+
*
|
|
69
|
+
* An error is considered "unrecognized" if it's external (from outside Fluid) or has the
|
|
70
|
+
* {@link NORMALIZED_ERROR_TYPE} error type (indicating it was normalized but not classified).
|
|
71
|
+
*
|
|
72
|
+
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
73
|
+
* one day we will move away from throwing these errors but rather we'll return them.
|
|
74
|
+
* But an unrecognized error needs to be classified appropriately (e.g., as DataProcessingError).
|
|
75
|
+
*
|
|
76
|
+
* @param factory - Factory function that creates the specific error type for wrapping unrecognized errors.
|
|
77
|
+
* @param originalError - The error to be wrapped or annotated.
|
|
78
|
+
* @param codepath - Identifier for the code path where the error was detected.
|
|
79
|
+
* @param messageLike - Optional message properties to include in telemetry.
|
|
80
|
+
* @returns The wrapped or annotated error as an {@link IFluidErrorBase}.
|
|
81
|
+
*/
|
|
82
|
+
function wrapDataProcessingErrorIfUnrecognized(factory, originalError, codepath, messageLike) {
|
|
83
|
+
const props = {
|
|
84
|
+
dataProcessingError: 1,
|
|
85
|
+
dataProcessingCodepath: codepath,
|
|
86
|
+
...(messageLike === undefined ? undefined : (0, exports.extractSafePropertiesFromMessage)(messageLike)),
|
|
87
|
+
};
|
|
88
|
+
const normalizedError = (0, errorLogging_js_1.normalizeError)(originalError, { props });
|
|
89
|
+
// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,
|
|
90
|
+
// but if so they are still suitable to be wrapped as DataProcessingError.
|
|
91
|
+
if ((0, errorLogging_js_1.isExternalError)(normalizedError) ||
|
|
92
|
+
normalizedError.errorType === errorLogging_js_1.NORMALIZED_ERROR_TYPE) {
|
|
93
|
+
// Create a new DataProcessingError to wrap this external error
|
|
94
|
+
const error = (0, errorLogging_js_1.wrapError)(normalizedError, (message) => factory(message));
|
|
95
|
+
// Copy over the props above and any others added to this error since first being normalized
|
|
96
|
+
error.addTelemetryProperties(normalizedError.getTelemetryProperties());
|
|
97
|
+
return error;
|
|
98
|
+
}
|
|
99
|
+
return normalizedError;
|
|
100
|
+
}
|
|
25
101
|
/**
|
|
26
102
|
* Generic wrapper for an unrecognized/uncategorized error object
|
|
27
103
|
*
|
|
@@ -69,6 +145,12 @@ class DataCorruptionError extends errorLogging_js_1.LoggingError {
|
|
|
69
145
|
this.errorType = internal_1.FluidErrorTypes.dataCorruptionError;
|
|
70
146
|
this.canRetry = false;
|
|
71
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Create a new `DataCorruptionError` detected and raised within the Fluid Framework.
|
|
150
|
+
*/
|
|
151
|
+
static create(errorMessage, dataCorruptionCodepath, messageLike, props = {}, stackTraceLimit) {
|
|
152
|
+
return buildDataProcessingError((message) => new DataCorruptionError(message, {}), errorMessage, dataCorruptionCodepath, messageLike, props, stackTraceLimit);
|
|
153
|
+
}
|
|
72
154
|
}
|
|
73
155
|
exports.DataCorruptionError = DataCorruptionError;
|
|
74
156
|
/**
|
|
@@ -95,22 +177,7 @@ class DataProcessingError extends errorLogging_js_1.LoggingError {
|
|
|
95
177
|
* Create a new `DataProcessingError` detected and raised within the Fluid Framework.
|
|
96
178
|
*/
|
|
97
179
|
static create(errorMessage, dataProcessingCodepath, messageLike, props = {}, stackTraceLimit) {
|
|
98
|
-
|
|
99
|
-
const originalStackTraceLimit = ErrorConfig.stackTraceLimit;
|
|
100
|
-
try {
|
|
101
|
-
if (stackTraceLimit !== undefined) {
|
|
102
|
-
ErrorConfig.stackTraceLimit = stackTraceLimit;
|
|
103
|
-
}
|
|
104
|
-
const dataProcessingError = DataProcessingError.wrapIfUnrecognized(errorMessage, dataProcessingCodepath, messageLike);
|
|
105
|
-
dataProcessingError.addTelemetryProperties(props);
|
|
106
|
-
return dataProcessingError;
|
|
107
|
-
}
|
|
108
|
-
finally {
|
|
109
|
-
// Reset the stack trace limit to the original value
|
|
110
|
-
if (stackTraceLimit !== undefined) {
|
|
111
|
-
ErrorConfig.stackTraceLimit = originalStackTraceLimit;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
180
|
+
return buildDataProcessingError((message) => new DataProcessingError(message), errorMessage, dataProcessingCodepath, messageLike, props, stackTraceLimit);
|
|
114
181
|
}
|
|
115
182
|
/**
|
|
116
183
|
* Wrap the given error in a `DataProcessingError`, unless the error is already of a known type
|
|
@@ -118,11 +185,7 @@ class DataProcessingError extends errorLogging_js_1.LoggingError {
|
|
|
118
185
|
*
|
|
119
186
|
* In either case, the error will have some relevant properties added for telemetry.
|
|
120
187
|
*
|
|
121
|
-
* @remarks
|
|
122
|
-
*
|
|
123
|
-
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
124
|
-
* one day we will move away from throwing these errors but rather we'll return them.
|
|
125
|
-
* But an unrecognized error needs to be classified as `DataProcessingError`.
|
|
188
|
+
* @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.
|
|
126
189
|
*
|
|
127
190
|
* @param originalError - The error to be converted.
|
|
128
191
|
* @param dataProcessingCodepath - Which code-path failed while processing data.
|
|
@@ -131,25 +194,7 @@ class DataProcessingError extends errorLogging_js_1.LoggingError {
|
|
|
131
194
|
* @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.
|
|
132
195
|
*/
|
|
133
196
|
static wrapIfUnrecognized(originalError, dataProcessingCodepath, messageLike) {
|
|
134
|
-
|
|
135
|
-
dataProcessingError: 1,
|
|
136
|
-
dataProcessingCodepath,
|
|
137
|
-
...(messageLike === undefined
|
|
138
|
-
? undefined
|
|
139
|
-
: (0, exports.extractSafePropertiesFromMessage)(messageLike)),
|
|
140
|
-
};
|
|
141
|
-
const normalizedError = (0, errorLogging_js_1.normalizeError)(originalError, { props });
|
|
142
|
-
// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,
|
|
143
|
-
// but if so they are still suitable to be wrapped as DataProcessingError.
|
|
144
|
-
if ((0, errorLogging_js_1.isExternalError)(normalizedError) ||
|
|
145
|
-
normalizedError.errorType === errorLogging_js_1.NORMALIZED_ERROR_TYPE) {
|
|
146
|
-
// Create a new DataProcessingError to wrap this external error
|
|
147
|
-
const dataProcessingError = (0, errorLogging_js_1.wrapError)(normalizedError, (message) => new DataProcessingError(message));
|
|
148
|
-
// Copy over the props above and any others added to this error since first being normalized
|
|
149
|
-
dataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());
|
|
150
|
-
return dataProcessingError;
|
|
151
|
-
}
|
|
152
|
-
return normalizedError;
|
|
197
|
+
return wrapDataProcessingErrorIfUnrecognized((errorMessage, props) => new DataProcessingError(errorMessage, props), originalError, dataProcessingCodepath, messageLike);
|
|
153
198
|
}
|
|
154
199
|
}
|
|
155
200
|
exports.DataProcessingError = DataProcessingError;
|
package/dist/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IErrorBase, ITelemetryBaseProperties } from \"@fluidframework/core-interfaces\";\nimport {\n\tFluidErrorTypes,\n\ttype IGenericError,\n\ttype ILayerIncompatibilityError,\n\ttype IUsageError,\n} from \"@fluidframework/core-interfaces/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tisExternalError,\n\tnormalizeError,\n\twrapError,\n} from \"./errorLogging.js\";\nimport type { IFluidErrorBase } from \"./fluidErrorBase.js\";\nimport type { ITelemetryPropertiesExt } from \"./telemetryTypes.js\";\n\n/**\n * Throws a UsageError with the given message if the condition is not met.\n * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).\n *\n * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.\n * @param message - The message to include in the error when the condition does not hold.\n * @param props - Telemetry props to include on the error when the condition does not hold.\n * @internal\n */\nexport function validatePrecondition(\n\tcondition: boolean,\n\tmessage: string,\n\tprops?: ITelemetryBaseProperties,\n): asserts condition {\n\tif (!condition) {\n\t\tthrow new UsageError(message, props);\n\t}\n}\n\n/**\n * Generic wrapper for an unrecognized/uncategorized error object\n *\n * @internal\n */\nexport class GenericError extends LoggingError implements IGenericError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.genericError;\n\n\t/**\n\t * Create a new GenericError\n\t * @param message - Error message\n\t * @param error - inner error object\n\t * @param props - Telemetry props to include when the error is logged\n\t */\n\tpublic constructor(\n\t\tmessage: string,\n\t\t// TODO: Use `unknown` instead (API breaking change because error is not just an input parameter, but a public member of the class)\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\tpublic readonly error?: any,\n\t\tprops?: ITelemetryBaseProperties,\n\t) {\n\t\t// Don't try to log the inner error\n\t\tsuper(message, props, new Set([\"error\"]));\n\t}\n}\n\n/**\n * Error indicating an API is being used improperly resulting in an invalid operation.\n *\n * @internal\n */\nexport class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.usageError;\n\n\tpublic constructor(message: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, usageError: true });\n\t}\n}\n\n/**\n * DataCorruptionError indicates that we encountered definitive evidence that the data at rest\n * backing this container is corrupted, and this container would never be expected to load properly again\n *\n * @internal\n */\nexport class DataCorruptionError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.dataCorruptionError;\n\tpublic readonly canRetry = false;\n\n\tpublic constructor(message: string, props: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, dataProcessingError: 1 });\n\t}\n}\n\n/**\n * Indicates we hit a fatal error while processing incoming data from the Fluid Service.\n *\n * @remarks\n *\n * The error will often originate in the dataStore or DDS implementation that is responding to incoming changes.\n * This differs from {@link DataCorruptionError} in that this may be a transient error that will not repro in another\n * client or session.\n *\n * @internal\n */\nexport class DataProcessingError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\t/**\n\t * {@inheritDoc IFluidErrorBase.errorType}\n\t */\n\tpublic readonly errorType = FluidErrorTypes.dataProcessingError;\n\n\tpublic readonly canRetry = false;\n\n\tprivate constructor(errorMessage: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(errorMessage, props);\n\t}\n\n\t/**\n\t * Create a new `DataProcessingError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: Partial<\n\t\t\tPick<\n\t\t\t\tISequencedDocumentMessage,\n\t\t\t\t| \"clientId\"\n\t\t\t\t| \"sequenceNumber\"\n\t\t\t\t| \"clientSequenceNumber\"\n\t\t\t\t| \"referenceSequenceNumber\"\n\t\t\t\t| \"minimumSequenceNumber\"\n\t\t\t\t| \"timestamp\"\n\t\t\t>\n\t\t>,\n\t\tprops: ITelemetryPropertiesExt = {},\n\t\tstackTraceLimit?: number,\n\t): IFluidErrorBase {\n\t\tconst ErrorConfig = Error as unknown as { stackTraceLimit: number };\n\t\tconst originalStackTraceLimit = ErrorConfig.stackTraceLimit;\n\t\ttry {\n\t\t\tif (stackTraceLimit !== undefined) {\n\t\t\t\tErrorConfig.stackTraceLimit = stackTraceLimit;\n\t\t\t}\n\n\t\t\tconst dataProcessingError = DataProcessingError.wrapIfUnrecognized(\n\t\t\t\terrorMessage,\n\t\t\t\tdataProcessingCodepath,\n\t\t\t\tmessageLike,\n\t\t\t);\n\t\t\tdataProcessingError.addTelemetryProperties(props);\n\n\t\t\treturn dataProcessingError;\n\t\t} finally {\n\t\t\t// Reset the stack trace limit to the original value\n\t\t\tif (stackTraceLimit !== undefined) {\n\t\t\t\tErrorConfig.stackTraceLimit = originalStackTraceLimit;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Wrap the given error in a `DataProcessingError`, unless the error is already of a known type\n\t * with the exception of a normalized {@link LoggingError}, which will still be wrapped.\n\t *\n\t * In either case, the error will have some relevant properties added for telemetry.\n\t *\n\t * @remarks\n\t *\n\t * We wrap conditionally since known error types represent well-understood failure modes, and ideally\n\t * one day we will move away from throwing these errors but rather we'll return them.\n\t * But an unrecognized error needs to be classified as `DataProcessingError`.\n\t *\n\t * @param originalError - The error to be converted.\n\t * @param dataProcessingCodepath - Which code-path failed while processing data.\n\t * @param messageLike - Message to include info about via telemetry props.\n\t *\n\t * @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.\n\t */\n\tpublic static wrapIfUnrecognized(\n\t\toriginalError: unknown,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: Partial<\n\t\t\tPick<\n\t\t\t\tISequencedDocumentMessage,\n\t\t\t\t| \"clientId\"\n\t\t\t\t| \"sequenceNumber\"\n\t\t\t\t| \"clientSequenceNumber\"\n\t\t\t\t| \"referenceSequenceNumber\"\n\t\t\t\t| \"minimumSequenceNumber\"\n\t\t\t\t| \"timestamp\"\n\t\t\t>\n\t\t>,\n\t): IFluidErrorBase {\n\t\tconst props = {\n\t\t\tdataProcessingError: 1,\n\t\t\tdataProcessingCodepath,\n\t\t\t...(messageLike === undefined\n\t\t\t\t? undefined\n\t\t\t\t: extractSafePropertiesFromMessage(messageLike)),\n\t\t};\n\n\t\tconst normalizedError = normalizeError(originalError, { props });\n\t\t// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,\n\t\t// but if so they are still suitable to be wrapped as DataProcessingError.\n\t\tif (\n\t\t\tisExternalError(normalizedError) ||\n\t\t\tnormalizedError.errorType === NORMALIZED_ERROR_TYPE\n\t\t) {\n\t\t\t// Create a new DataProcessingError to wrap this external error\n\t\t\tconst dataProcessingError = wrapError(\n\t\t\t\tnormalizedError,\n\t\t\t\t(message: string) => new DataProcessingError(message),\n\t\t\t);\n\n\t\t\t// Copy over the props above and any others added to this error since first being normalized\n\t\t\tdataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());\n\n\t\t\treturn dataProcessingError;\n\t\t}\n\t\treturn normalizedError;\n\t}\n}\n\n/**\n * Error indicating that two Fluid layers are incompatible.\n * See {@link @fluidframework/core-interfaces#ILayerIncompatibilityError} for more details.\n *\n * @internal\n */\nexport class LayerIncompatibilityError\n\textends LoggingError\n\timplements ILayerIncompatibilityError\n{\n\tpublic readonly errorType = FluidErrorTypes.layerIncompatibilityError;\n\tpublic readonly layer: string;\n\tpublic readonly layerVersion: string;\n\tpublic readonly incompatibleLayer: string;\n\tpublic readonly incompatibleLayerVersion: string;\n\tpublic readonly compatibilityRequirementsInMonths: number;\n\tpublic readonly actualDifferenceInMonths: number;\n\tpublic readonly details: string;\n\n\tpublic constructor(\n\t\tmessage: string,\n\t\tincompatibilityProps: {\n\t\t\tlayer: string;\n\t\t\tlayerVersion: string;\n\t\t\tincompatibleLayer: string;\n\t\t\tincompatibleLayerVersion: string;\n\t\t\tcompatibilityRequirementsInMonths: number;\n\t\t\tactualDifferenceInMonths: number;\n\t\t\tdetails: string;\n\t\t},\n\t\ttelemetryProps?: ITelemetryBaseProperties,\n\t) {\n\t\tsuper(message, {\n\t\t\t...incompatibilityProps,\n\t\t\t...telemetryProps,\n\t\t\tlayerIncompatibilityError: true,\n\t\t});\n\t\tthis.layer = incompatibilityProps.layer;\n\t\tthis.layerVersion = incompatibilityProps.layerVersion;\n\t\tthis.incompatibleLayer = incompatibilityProps.incompatibleLayer;\n\t\tthis.incompatibleLayerVersion = incompatibilityProps.incompatibleLayerVersion;\n\t\tthis.compatibilityRequirementsInMonths =\n\t\t\tincompatibilityProps.compatibilityRequirementsInMonths;\n\t\tthis.actualDifferenceInMonths = incompatibilityProps.actualDifferenceInMonths;\n\t\tthis.details = incompatibilityProps.details;\n\t}\n}\n\n/**\n * Extracts specific properties from the provided message that we know are safe to log.\n *\n * @param messageLike - Message to include info about via telemetry props.\n *\n * @internal\n */\nexport const extractSafePropertiesFromMessage = (\n\tmessageLike: Partial<\n\t\tPick<\n\t\t\tISequencedDocumentMessage,\n\t\t\t| \"clientId\"\n\t\t\t| \"sequenceNumber\"\n\t\t\t| \"clientSequenceNumber\"\n\t\t\t| \"referenceSequenceNumber\"\n\t\t\t| \"minimumSequenceNumber\"\n\t\t\t| \"timestamp\"\n\t\t>\n\t>,\n): {\n\tmessageClientId: string | undefined;\n\tmessageSequenceNumber: number | undefined;\n\tmessageClientSequenceNumber: number | undefined;\n\tmessageReferenceSequenceNumber: number | undefined;\n\tmessageMinimumSequenceNumber: number | undefined;\n\tmessageTimestamp: number | undefined;\n} => ({\n\tmessageClientId: messageLike.clientId === null ? \"null\" : messageLike.clientId,\n\tmessageSequenceNumber: messageLike.sequenceNumber,\n\tmessageClientSequenceNumber: messageLike.clientSequenceNumber,\n\tmessageReferenceSequenceNumber: messageLike.referenceSequenceNumber,\n\tmessageMinimumSequenceNumber: messageLike.minimumSequenceNumber,\n\tmessageTimestamp: messageLike.timestamp,\n});\n"]}
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IErrorBase, ITelemetryBaseProperties } from \"@fluidframework/core-interfaces\";\nimport {\n\tFluidErrorTypes,\n\ttype IGenericError,\n\ttype ILayerIncompatibilityError,\n\ttype IUsageError,\n} from \"@fluidframework/core-interfaces/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tisExternalError,\n\tnormalizeError,\n\twrapError,\n} from \"./errorLogging.js\";\nimport type { IFluidErrorBase } from \"./fluidErrorBase.js\";\nimport type { ITelemetryPropertiesExt } from \"./telemetryTypes.js\";\n\n/**\n * A subset of `ISequencedDocumentMessage` properties that are safe to log for telemetry.\n * @internal\n */\nexport type MessageLike = Partial<\n\tPick<\n\t\tISequencedDocumentMessage,\n\t\t| \"clientId\"\n\t\t| \"sequenceNumber\"\n\t\t| \"clientSequenceNumber\"\n\t\t| \"referenceSequenceNumber\"\n\t\t| \"minimumSequenceNumber\"\n\t\t| \"timestamp\"\n\t>\n>;\n\n/**\n * Throws a UsageError with the given message if the condition is not met.\n * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).\n *\n * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.\n * @param message - The message to include in the error when the condition does not hold.\n * @param props - Telemetry props to include on the error when the condition does not hold.\n * @internal\n */\nexport function validatePrecondition(\n\tcondition: boolean,\n\tmessage: string,\n\tprops?: ITelemetryBaseProperties,\n): asserts condition {\n\tif (!condition) {\n\t\tthrow new UsageError(message, props);\n\t}\n}\n\n/**\n * Creates an error during data processing (DataProcessingError or DataCorruptionError) with telemetry properties.\n *\n * @remarks\n * This helper allows customizing the stack trace limit during error creation, which is useful\n * for capturing more context in error scenarios. It delegates to {@link wrapOrAnnotateError}\n * for the actual error wrapping/annotation logic.\n *\n * @param factory - Factory function that creates the specific error type.\n * @param errorMessage - The error message to use.\n * @param codepath - Identifier for the code path where the error was detected.\n * @param messageLike - Optional message properties to include in telemetry.\n * @param props - Additional telemetry properties to attach to the error.\n * @param stackTraceLimit - Optional limit for the stack trace depth.\n * @returns The created error with telemetry properties attached.\n */\nfunction buildDataProcessingError(\n\tfactory: (message: string) => LoggingError & IFluidErrorBase,\n\terrorMessage: string,\n\tcodepath: string,\n\tmessageLike?: MessageLike,\n\tprops: ITelemetryPropertiesExt = {},\n\tstackTraceLimit?: number,\n): IFluidErrorBase {\n\tconst ErrorConfig = Error as unknown as { stackTraceLimit: number };\n\tconst originalStackTraceLimit = ErrorConfig.stackTraceLimit;\n\ttry {\n\t\tif (stackTraceLimit !== undefined) {\n\t\t\tErrorConfig.stackTraceLimit = stackTraceLimit;\n\t\t}\n\n\t\tconst error = wrapDataProcessingErrorIfUnrecognized(\n\t\t\tfactory,\n\t\t\terrorMessage,\n\t\t\tcodepath,\n\t\t\tmessageLike,\n\t\t);\n\t\terror.addTelemetryProperties(props);\n\n\t\treturn error;\n\t} finally {\n\t\t// Reset the stack trace limit to the original value\n\t\tif (stackTraceLimit !== undefined) {\n\t\t\tErrorConfig.stackTraceLimit = originalStackTraceLimit;\n\t\t}\n\t}\n}\n\n/**\n * Wraps an unrecognized error into a data processing error (DataProcessingError or DataCorruptionError)\n * using the provided factory.\n *\n * @remarks\n * This function handles two cases:\n * - **Unrecognized/external errors**: Wrapped using the provided factory function to create a proper\n * Fluid error type (DataProcessingError or DataCorruptionError).\n * - **Recognized Fluid errors**: Not wrapped, but annotated with data processing telemetry properties.\n *\n * An error is considered \"unrecognized\" if it's external (from outside Fluid) or has the\n * {@link NORMALIZED_ERROR_TYPE} error type (indicating it was normalized but not classified).\n *\n * We wrap conditionally since known error types represent well-understood failure modes, and ideally\n * one day we will move away from throwing these errors but rather we'll return them.\n * But an unrecognized error needs to be classified appropriately (e.g., as DataProcessingError).\n *\n * @param factory - Factory function that creates the specific error type for wrapping unrecognized errors.\n * @param originalError - The error to be wrapped or annotated.\n * @param codepath - Identifier for the code path where the error was detected.\n * @param messageLike - Optional message properties to include in telemetry.\n * @returns The wrapped or annotated error as an {@link IFluidErrorBase}.\n */\nfunction wrapDataProcessingErrorIfUnrecognized(\n\tfactory: (message: string) => LoggingError & IFluidErrorBase,\n\toriginalError: unknown,\n\tcodepath: string,\n\tmessageLike?: MessageLike,\n): IFluidErrorBase {\n\tconst props = {\n\t\tdataProcessingError: 1,\n\t\tdataProcessingCodepath: codepath,\n\t\t...(messageLike === undefined ? undefined : extractSafePropertiesFromMessage(messageLike)),\n\t};\n\n\tconst normalizedError = normalizeError(originalError, { props });\n\t// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,\n\t// but if so they are still suitable to be wrapped as DataProcessingError.\n\tif (\n\t\tisExternalError(normalizedError) ||\n\t\tnormalizedError.errorType === NORMALIZED_ERROR_TYPE\n\t) {\n\t\t// Create a new DataProcessingError to wrap this external error\n\t\tconst error = wrapError(normalizedError, (message: string) => factory(message));\n\n\t\t// Copy over the props above and any others added to this error since first being normalized\n\t\terror.addTelemetryProperties(normalizedError.getTelemetryProperties());\n\n\t\treturn error;\n\t}\n\treturn normalizedError;\n}\n\n/**\n * Generic wrapper for an unrecognized/uncategorized error object\n *\n * @internal\n */\nexport class GenericError extends LoggingError implements IGenericError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.genericError;\n\n\t/**\n\t * Create a new GenericError\n\t * @param message - Error message\n\t * @param error - inner error object\n\t * @param props - Telemetry props to include when the error is logged\n\t */\n\tpublic constructor(\n\t\tmessage: string,\n\t\t// TODO: Use `unknown` instead (API breaking change because error is not just an input parameter, but a public member of the class)\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\tpublic readonly error?: any,\n\t\tprops?: ITelemetryBaseProperties,\n\t) {\n\t\t// Don't try to log the inner error\n\t\tsuper(message, props, new Set([\"error\"]));\n\t}\n}\n\n/**\n * Error indicating an API is being used improperly resulting in an invalid operation.\n *\n * @internal\n */\nexport class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.usageError;\n\n\tpublic constructor(message: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, usageError: true });\n\t}\n}\n\n/**\n * DataCorruptionError indicates that we encountered definitive evidence that the data at rest\n * backing this container is corrupted, and this container would never be expected to load properly again\n *\n * @internal\n */\nexport class DataCorruptionError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.dataCorruptionError;\n\tpublic readonly canRetry = false;\n\n\tpublic constructor(message: string, props: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, dataProcessingError: 1 });\n\t}\n\n\t/**\n\t * Create a new `DataCorruptionError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataCorruptionCodepath: string,\n\t\tmessageLike?: MessageLike,\n\t\tprops: ITelemetryPropertiesExt = {},\n\t\tstackTraceLimit?: number,\n\t): IFluidErrorBase {\n\t\treturn buildDataProcessingError(\n\t\t\t(message: string) => new DataCorruptionError(message, {}),\n\t\t\terrorMessage,\n\t\t\tdataCorruptionCodepath,\n\t\t\tmessageLike,\n\t\t\tprops,\n\t\t\tstackTraceLimit,\n\t\t);\n\t}\n}\n\n/**\n * Indicates we hit a fatal error while processing incoming data from the Fluid Service.\n *\n * @remarks\n *\n * The error will often originate in the dataStore or DDS implementation that is responding to incoming changes.\n * This differs from {@link DataCorruptionError} in that this may be a transient error that will not repro in another\n * client or session.\n *\n * @internal\n */\nexport class DataProcessingError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\t/**\n\t * {@inheritDoc IFluidErrorBase.errorType}\n\t */\n\tpublic readonly errorType = FluidErrorTypes.dataProcessingError;\n\n\tpublic readonly canRetry = false;\n\n\tprivate constructor(errorMessage: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(errorMessage, props);\n\t}\n\n\t/**\n\t * Create a new `DataProcessingError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: MessageLike,\n\t\tprops: ITelemetryPropertiesExt = {},\n\t\tstackTraceLimit?: number,\n\t): IFluidErrorBase {\n\t\treturn buildDataProcessingError(\n\t\t\t(message: string) => new DataProcessingError(message),\n\t\t\terrorMessage,\n\t\t\tdataProcessingCodepath,\n\t\t\tmessageLike,\n\t\t\tprops,\n\t\t\tstackTraceLimit,\n\t\t);\n\t}\n\n\t/**\n\t * Wrap the given error in a `DataProcessingError`, unless the error is already of a known type\n\t * with the exception of a normalized {@link LoggingError}, which will still be wrapped.\n\t *\n\t * In either case, the error will have some relevant properties added for telemetry.\n\t *\n\t * @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.\n\t *\n\t * @param originalError - The error to be converted.\n\t * @param dataProcessingCodepath - Which code-path failed while processing data.\n\t * @param messageLike - Message to include info about via telemetry props.\n\t *\n\t * @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.\n\t */\n\tpublic static wrapIfUnrecognized(\n\t\toriginalError: unknown,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: MessageLike,\n\t): IFluidErrorBase {\n\t\treturn wrapDataProcessingErrorIfUnrecognized(\n\t\t\t(errorMessage: string, props?: ITelemetryBaseProperties) =>\n\t\t\t\tnew DataProcessingError(errorMessage, props),\n\t\t\toriginalError,\n\t\t\tdataProcessingCodepath,\n\t\t\tmessageLike,\n\t\t);\n\t}\n}\n\n/**\n * Error indicating that two Fluid layers are incompatible.\n * See {@link @fluidframework/core-interfaces#ILayerIncompatibilityError} for more details.\n *\n * @internal\n */\nexport class LayerIncompatibilityError\n\textends LoggingError\n\timplements ILayerIncompatibilityError\n{\n\tpublic readonly errorType = FluidErrorTypes.layerIncompatibilityError;\n\tpublic readonly layer: string;\n\tpublic readonly layerVersion: string;\n\tpublic readonly incompatibleLayer: string;\n\tpublic readonly incompatibleLayerVersion: string;\n\tpublic readonly compatibilityRequirementsInMonths: number;\n\tpublic readonly actualDifferenceInMonths: number;\n\tpublic readonly details: string;\n\n\tpublic constructor(\n\t\tmessage: string,\n\t\tincompatibilityProps: {\n\t\t\tlayer: string;\n\t\t\tlayerVersion: string;\n\t\t\tincompatibleLayer: string;\n\t\t\tincompatibleLayerVersion: string;\n\t\t\tcompatibilityRequirementsInMonths: number;\n\t\t\tactualDifferenceInMonths: number;\n\t\t\tdetails: string;\n\t\t},\n\t\ttelemetryProps?: ITelemetryBaseProperties,\n\t) {\n\t\tsuper(message, {\n\t\t\t...incompatibilityProps,\n\t\t\t...telemetryProps,\n\t\t\tlayerIncompatibilityError: true,\n\t\t});\n\t\tthis.layer = incompatibilityProps.layer;\n\t\tthis.layerVersion = incompatibilityProps.layerVersion;\n\t\tthis.incompatibleLayer = incompatibilityProps.incompatibleLayer;\n\t\tthis.incompatibleLayerVersion = incompatibilityProps.incompatibleLayerVersion;\n\t\tthis.compatibilityRequirementsInMonths =\n\t\t\tincompatibilityProps.compatibilityRequirementsInMonths;\n\t\tthis.actualDifferenceInMonths = incompatibilityProps.actualDifferenceInMonths;\n\t\tthis.details = incompatibilityProps.details;\n\t}\n}\n\n/**\n * Extracts specific properties from the provided message that we know are safe to log.\n *\n * @param messageLike - Message to include info about via telemetry props.\n *\n * @internal\n */\nexport const extractSafePropertiesFromMessage = (\n\tmessageLike: MessageLike,\n): {\n\tmessageClientId: string | undefined;\n\tmessageSequenceNumber: number | undefined;\n\tmessageClientSequenceNumber: number | undefined;\n\tmessageReferenceSequenceNumber: number | undefined;\n\tmessageMinimumSequenceNumber: number | undefined;\n\tmessageTimestamp: number | undefined;\n} => ({\n\tmessageClientId: messageLike.clientId === null ? \"null\" : messageLike.clientId,\n\tmessageSequenceNumber: messageLike.sequenceNumber,\n\tmessageClientSequenceNumber: messageLike.clientSequenceNumber,\n\tmessageReferenceSequenceNumber: messageLike.referenceSequenceNumber,\n\tmessageMinimumSequenceNumber: messageLike.minimumSequenceNumber,\n\tmessageTimestamp: messageLike.timestamp,\n});\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
export { createChildMonitoringContext, type MonitoringContext, sessionStorageConfigProvider, mixinMonitoringContext, type IConfigProvider, loggerToMonitoringContext, wrapConfigProviderWithDefaults, createConfigBasedOptionsProxy, type OptionConfigReaders, } from "./config.js";
|
|
6
|
-
export { DataCorruptionError, DataProcessingError, extractSafePropertiesFromMessage, GenericError, UsageError, validatePrecondition, LayerIncompatibilityError, } from "./error.js";
|
|
6
|
+
export { DataCorruptionError, DataProcessingError, extractSafePropertiesFromMessage, GenericError, UsageError, validatePrecondition, LayerIncompatibilityError, type MessageLike, } from "./error.js";
|
|
7
7
|
export { extractLogSafeErrorProperties, generateErrorWithStack, generateStack, getCircularReplacer, type IFluidErrorAnnotations, isExternalError, isILoggingError, isTaggedTelemetryPropertyValue, LoggingError, NORMALIZED_ERROR_TYPE, normalizeError, overwriteStack, wrapError, wrapErrorAndLog, } from "./errorLogging.js";
|
|
8
8
|
export { EventEmitterWithErrorHandling } from "./eventEmitterWithErrorHandling.js";
|
|
9
9
|
export { connectedEventName, disconnectedEventName, raiseConnectedEvent, safeRaiseEvent, } from "./events.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,eAAe,EACpB,yBAAyB,EACzB,8BAA8B,EAC9B,6BAA6B,EAC7B,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,eAAe,EACpB,yBAAyB,EACzB,8BAA8B,EAC9B,6BAA6B,EAC7B,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,WAAW,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,6BAA6B,EAC7B,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,eAAe,EACf,eAAe,EACf,8BAA8B,EAC9B,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,SAAS,EACT,eAAe,GACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EACN,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kBAAkB,EAClB,KAAK,eAAe,EACpB,YAAY,EACZ,2BAA2B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAC9B,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,2BAA2B,GAChC,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,KAAK,cAAc,EACnB,UAAU,GACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACN,sBAAsB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,OAAO,GACP,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,6BAA6B,EAC7B,kBAAkB,EAClB,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;AAEH,yCAUqB;AATpB,yHAAA,4BAA4B,OAAA;AAE5B,yHAAA,4BAA4B,OAAA;AAC5B,mHAAA,sBAAsB,OAAA;AAEtB,sHAAA,yBAAyB,OAAA;AACzB,2HAAA,8BAA8B,OAAA;AAC9B,0HAAA,6BAA6B,OAAA;AAG9B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;AAEH,yCAUqB;AATpB,yHAAA,4BAA4B,OAAA;AAE5B,yHAAA,4BAA4B,OAAA;AAC5B,mHAAA,sBAAsB,OAAA;AAEtB,sHAAA,yBAAyB,OAAA;AACzB,2HAAA,8BAA8B,OAAA;AAC9B,0HAAA,6BAA6B,OAAA;AAG9B,uCASoB;AARnB,+GAAA,mBAAmB,OAAA;AACnB,+GAAA,mBAAmB,OAAA;AACnB,4HAAA,gCAAgC,OAAA;AAChC,wGAAA,YAAY,OAAA;AACZ,sGAAA,UAAU,OAAA;AACV,gHAAA,oBAAoB,OAAA;AACpB,qHAAA,yBAAyB,OAAA;AAG1B,qDAe2B;AAd1B,gIAAA,6BAA6B,OAAA;AAC7B,yHAAA,sBAAsB,OAAA;AACtB,gHAAA,aAAa,OAAA;AACb,sHAAA,mBAAmB,OAAA;AAEnB,kHAAA,eAAe,OAAA;AACf,kHAAA,eAAe,OAAA;AACf,iIAAA,8BAA8B,OAAA;AAC9B,+GAAA,YAAY,OAAA;AACZ,wHAAA,qBAAqB,OAAA;AACrB,iHAAA,cAAc,OAAA;AACd,iHAAA,cAAc,OAAA;AACd,4GAAA,SAAS,OAAA;AACT,kHAAA,eAAe,OAAA;AAEhB,uFAAmF;AAA1E,iJAAA,6BAA6B,OAAA;AACtC,yCAKqB;AAJpB,+GAAA,kBAAkB,OAAA;AAClB,kHAAA,qBAAqB,OAAA;AACrB,gHAAA,mBAAmB,OAAA;AACnB,2GAAA,cAAc,OAAA;AAEf,yDAK6B;AAJ5B,uHAAA,kBAAkB,OAAA;AAElB,iHAAA,YAAY,OAAA;AACZ,gIAAA,2BAA2B,OAAA;AAE5B,yCAgBqB;AAfpB,oHAAA,uBAAuB,OAAA;AACvB,8GAAA,iBAAiB,OAAA;AACjB,kHAAA,qBAAqB,OAAA;AACrB,uGAAA,UAAU,OAAA;AAKV,6GAAA,gBAAgB,OAAA;AAChB,6GAAA,gBAAgB,OAAA;AAChB,gHAAA,mBAAmB,OAAA;AACnB,oGAAA,OAAO,OAAA;AACP,6GAAA,gBAAgB,OAAA;AAChB,6GAAA,gBAAgB,OAAA;AAGjB,iDAIyB;AAHxB,oHAAA,mBAAmB,OAAA;AAEnB,2GAAA,UAAU,OAAA;AAEX,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AACzB,yEAKqC;AAJpC,mIAAA,sBAAsB,OAAA;AAKvB,uCAKoB;AAJnB,+GAAA,mBAAmB,OAAA;AAGnB,mGAAA,OAAO,OAAA;AAYR,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAC9B,6DAA+F;AAAtF,iIAAA,0BAA0B,OAAA;AAAE,iIAAA,0BAA0B,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tcreateChildMonitoringContext,\n\ttype MonitoringContext,\n\tsessionStorageConfigProvider,\n\tmixinMonitoringContext,\n\ttype IConfigProvider,\n\tloggerToMonitoringContext,\n\twrapConfigProviderWithDefaults,\n\tcreateConfigBasedOptionsProxy,\n\ttype OptionConfigReaders,\n} from \"./config.js\";\nexport {\n\tDataCorruptionError,\n\tDataProcessingError,\n\textractSafePropertiesFromMessage,\n\tGenericError,\n\tUsageError,\n\tvalidatePrecondition,\n\tLayerIncompatibilityError,\n\ttype MessageLike,\n} from \"./error.js\";\nexport {\n\textractLogSafeErrorProperties,\n\tgenerateErrorWithStack,\n\tgenerateStack,\n\tgetCircularReplacer,\n\ttype IFluidErrorAnnotations,\n\tisExternalError,\n\tisILoggingError,\n\tisTaggedTelemetryPropertyValue,\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tnormalizeError,\n\toverwriteStack,\n\twrapError,\n\twrapErrorAndLog,\n} from \"./errorLogging.js\";\nexport { EventEmitterWithErrorHandling } from \"./eventEmitterWithErrorHandling.js\";\nexport {\n\tconnectedEventName,\n\tdisconnectedEventName,\n\traiseConnectedEvent,\n\tsafeRaiseEvent,\n} from \"./events.js\";\nexport {\n\thasErrorInstanceId,\n\ttype IFluidErrorBase,\n\tisFluidError,\n\tisLayerIncompatibilityError,\n} from \"./fluidErrorBase.js\";\nexport {\n\teventNamespaceSeparator,\n\tcreateChildLogger,\n\tcreateMultiSinkLogger,\n\tformatTick,\n\ttype IPerformanceEventMarkers,\n\ttype ITelemetryLoggerPropertyBag,\n\ttype ITelemetryLoggerPropertyBags,\n\ttype MultiSinkLoggerProperties,\n\tnumberFromString,\n\tPerformanceEvent,\n\tTaggedLoggerAdapter,\n\ttagData,\n\ttagCodeArtifacts,\n\tTelemetryDataTag,\n\ttype TelemetryEventPropertyTypes,\n} from \"./logger.js\";\nexport {\n\tcreateMockLoggerExt,\n\ttype IMockLoggerExt,\n\tMockLogger,\n} from \"./mockLogger.js\";\nexport { ThresholdCounter } from \"./thresholdCounter.js\";\nexport {\n\tSampledTelemetryHelper,\n\ttype CustomMetrics,\n\ttype ICustomData,\n\ttype MeasureReturnType,\n} from \"./sampledTelemetryHelper.js\";\nexport {\n\tcreateSampledLogger,\n\ttype IEventSampler,\n\ttype ISampledTelemetryLogger,\n\tmeasure,\n} from \"./utils.js\";\nexport type {\n\tTelemetryEventPropertyTypeExt,\n\tITelemetryEventExt,\n\tITelemetryGenericEventExt,\n\tITelemetryErrorEventExt,\n\tITelemetryPerformanceEventExt,\n\tITelemetryLoggerExt,\n\tITelemetryPropertiesExt,\n\tTelemetryEventCategory,\n} from \"./telemetryTypes.js\";\nexport { TelemetryEventBatcher } from \"./telemetryEventBatcher.js\";\nexport { allowIncompatibleLayersKey, validateLayerCompatibility } from \"./layerCompatError.js\";\n"]}
|
package/lib/error.d.ts
CHANGED
|
@@ -8,6 +8,11 @@ import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitio
|
|
|
8
8
|
import { LoggingError } from "./errorLogging.js";
|
|
9
9
|
import type { IFluidErrorBase } from "./fluidErrorBase.js";
|
|
10
10
|
import type { ITelemetryPropertiesExt } from "./telemetryTypes.js";
|
|
11
|
+
/**
|
|
12
|
+
* A subset of `ISequencedDocumentMessage` properties that are safe to log for telemetry.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export type MessageLike = Partial<Pick<ISequencedDocumentMessage, "clientId" | "sequenceNumber" | "clientSequenceNumber" | "referenceSequenceNumber" | "minimumSequenceNumber" | "timestamp">>;
|
|
11
16
|
/**
|
|
12
17
|
* Throws a UsageError with the given message if the condition is not met.
|
|
13
18
|
* Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).
|
|
@@ -53,6 +58,10 @@ export declare class DataCorruptionError extends LoggingError implements IErrorB
|
|
|
53
58
|
readonly errorType: "dataCorruptionError";
|
|
54
59
|
readonly canRetry = false;
|
|
55
60
|
constructor(message: string, props: ITelemetryBaseProperties);
|
|
61
|
+
/**
|
|
62
|
+
* Create a new `DataCorruptionError` detected and raised within the Fluid Framework.
|
|
63
|
+
*/
|
|
64
|
+
static create(errorMessage: string, dataCorruptionCodepath: string, messageLike?: MessageLike, props?: ITelemetryPropertiesExt, stackTraceLimit?: number): IFluidErrorBase;
|
|
56
65
|
}
|
|
57
66
|
/**
|
|
58
67
|
* Indicates we hit a fatal error while processing incoming data from the Fluid Service.
|
|
@@ -75,18 +84,14 @@ export declare class DataProcessingError extends LoggingError implements IErrorB
|
|
|
75
84
|
/**
|
|
76
85
|
* Create a new `DataProcessingError` detected and raised within the Fluid Framework.
|
|
77
86
|
*/
|
|
78
|
-
static create(errorMessage: string, dataProcessingCodepath: string, messageLike?:
|
|
87
|
+
static create(errorMessage: string, dataProcessingCodepath: string, messageLike?: MessageLike, props?: ITelemetryPropertiesExt, stackTraceLimit?: number): IFluidErrorBase;
|
|
79
88
|
/**
|
|
80
89
|
* Wrap the given error in a `DataProcessingError`, unless the error is already of a known type
|
|
81
90
|
* with the exception of a normalized {@link LoggingError}, which will still be wrapped.
|
|
82
91
|
*
|
|
83
92
|
* In either case, the error will have some relevant properties added for telemetry.
|
|
84
93
|
*
|
|
85
|
-
* @remarks
|
|
86
|
-
*
|
|
87
|
-
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
88
|
-
* one day we will move away from throwing these errors but rather we'll return them.
|
|
89
|
-
* But an unrecognized error needs to be classified as `DataProcessingError`.
|
|
94
|
+
* @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.
|
|
90
95
|
*
|
|
91
96
|
* @param originalError - The error to be converted.
|
|
92
97
|
* @param dataProcessingCodepath - Which code-path failed while processing data.
|
|
@@ -94,7 +99,7 @@ export declare class DataProcessingError extends LoggingError implements IErrorB
|
|
|
94
99
|
*
|
|
95
100
|
* @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.
|
|
96
101
|
*/
|
|
97
|
-
static wrapIfUnrecognized(originalError: unknown, dataProcessingCodepath: string, messageLike?:
|
|
102
|
+
static wrapIfUnrecognized(originalError: unknown, dataProcessingCodepath: string, messageLike?: MessageLike): IFluidErrorBase;
|
|
98
103
|
}
|
|
99
104
|
/**
|
|
100
105
|
* Error indicating that two Fluid layers are incompatible.
|
|
@@ -128,7 +133,7 @@ export declare class LayerIncompatibilityError extends LoggingError implements I
|
|
|
128
133
|
*
|
|
129
134
|
* @internal
|
|
130
135
|
*/
|
|
131
|
-
export declare const extractSafePropertiesFromMessage: (messageLike:
|
|
136
|
+
export declare const extractSafePropertiesFromMessage: (messageLike: MessageLike) => {
|
|
132
137
|
messageClientId: string | undefined;
|
|
133
138
|
messageSequenceNumber: number | undefined;
|
|
134
139
|
messageClientSequenceNumber: number | undefined;
|
package/lib/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC5F,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,EAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAE7F,OAAO,EACN,YAAY,EAKZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,wBAAwB,GAC9B,OAAO,CAAC,SAAS,CAInB;
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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"}
|
package/lib/error.js
CHANGED
|
@@ -18,6 +18,82 @@ export function validatePrecondition(condition, message, props) {
|
|
|
18
18
|
throw new UsageError(message, props);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates an error during data processing (DataProcessingError or DataCorruptionError) with telemetry properties.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* This helper allows customizing the stack trace limit during error creation, which is useful
|
|
26
|
+
* for capturing more context in error scenarios. It delegates to {@link wrapOrAnnotateError}
|
|
27
|
+
* for the actual error wrapping/annotation logic.
|
|
28
|
+
*
|
|
29
|
+
* @param factory - Factory function that creates the specific error type.
|
|
30
|
+
* @param errorMessage - The error message to use.
|
|
31
|
+
* @param codepath - Identifier for the code path where the error was detected.
|
|
32
|
+
* @param messageLike - Optional message properties to include in telemetry.
|
|
33
|
+
* @param props - Additional telemetry properties to attach to the error.
|
|
34
|
+
* @param stackTraceLimit - Optional limit for the stack trace depth.
|
|
35
|
+
* @returns The created error with telemetry properties attached.
|
|
36
|
+
*/
|
|
37
|
+
function buildDataProcessingError(factory, errorMessage, codepath, messageLike, props = {}, stackTraceLimit) {
|
|
38
|
+
const ErrorConfig = Error;
|
|
39
|
+
const originalStackTraceLimit = ErrorConfig.stackTraceLimit;
|
|
40
|
+
try {
|
|
41
|
+
if (stackTraceLimit !== undefined) {
|
|
42
|
+
ErrorConfig.stackTraceLimit = stackTraceLimit;
|
|
43
|
+
}
|
|
44
|
+
const error = wrapDataProcessingErrorIfUnrecognized(factory, errorMessage, codepath, messageLike);
|
|
45
|
+
error.addTelemetryProperties(props);
|
|
46
|
+
return error;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
// Reset the stack trace limit to the original value
|
|
50
|
+
if (stackTraceLimit !== undefined) {
|
|
51
|
+
ErrorConfig.stackTraceLimit = originalStackTraceLimit;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Wraps an unrecognized error into a data processing error (DataProcessingError or DataCorruptionError)
|
|
57
|
+
* using the provided factory.
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* This function handles two cases:
|
|
61
|
+
* - **Unrecognized/external errors**: Wrapped using the provided factory function to create a proper
|
|
62
|
+
* Fluid error type (DataProcessingError or DataCorruptionError).
|
|
63
|
+
* - **Recognized Fluid errors**: Not wrapped, but annotated with data processing telemetry properties.
|
|
64
|
+
*
|
|
65
|
+
* An error is considered "unrecognized" if it's external (from outside Fluid) or has the
|
|
66
|
+
* {@link NORMALIZED_ERROR_TYPE} error type (indicating it was normalized but not classified).
|
|
67
|
+
*
|
|
68
|
+
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
69
|
+
* one day we will move away from throwing these errors but rather we'll return them.
|
|
70
|
+
* But an unrecognized error needs to be classified appropriately (e.g., as DataProcessingError).
|
|
71
|
+
*
|
|
72
|
+
* @param factory - Factory function that creates the specific error type for wrapping unrecognized errors.
|
|
73
|
+
* @param originalError - The error to be wrapped or annotated.
|
|
74
|
+
* @param codepath - Identifier for the code path where the error was detected.
|
|
75
|
+
* @param messageLike - Optional message properties to include in telemetry.
|
|
76
|
+
* @returns The wrapped or annotated error as an {@link IFluidErrorBase}.
|
|
77
|
+
*/
|
|
78
|
+
function wrapDataProcessingErrorIfUnrecognized(factory, originalError, codepath, messageLike) {
|
|
79
|
+
const props = {
|
|
80
|
+
dataProcessingError: 1,
|
|
81
|
+
dataProcessingCodepath: codepath,
|
|
82
|
+
...(messageLike === undefined ? undefined : extractSafePropertiesFromMessage(messageLike)),
|
|
83
|
+
};
|
|
84
|
+
const normalizedError = normalizeError(originalError, { props });
|
|
85
|
+
// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,
|
|
86
|
+
// but if so they are still suitable to be wrapped as DataProcessingError.
|
|
87
|
+
if (isExternalError(normalizedError) ||
|
|
88
|
+
normalizedError.errorType === NORMALIZED_ERROR_TYPE) {
|
|
89
|
+
// Create a new DataProcessingError to wrap this external error
|
|
90
|
+
const error = wrapError(normalizedError, (message) => factory(message));
|
|
91
|
+
// Copy over the props above and any others added to this error since first being normalized
|
|
92
|
+
error.addTelemetryProperties(normalizedError.getTelemetryProperties());
|
|
93
|
+
return error;
|
|
94
|
+
}
|
|
95
|
+
return normalizedError;
|
|
96
|
+
}
|
|
21
97
|
/**
|
|
22
98
|
* Generic wrapper for an unrecognized/uncategorized error object
|
|
23
99
|
*
|
|
@@ -63,6 +139,12 @@ export class DataCorruptionError extends LoggingError {
|
|
|
63
139
|
this.errorType = FluidErrorTypes.dataCorruptionError;
|
|
64
140
|
this.canRetry = false;
|
|
65
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Create a new `DataCorruptionError` detected and raised within the Fluid Framework.
|
|
144
|
+
*/
|
|
145
|
+
static create(errorMessage, dataCorruptionCodepath, messageLike, props = {}, stackTraceLimit) {
|
|
146
|
+
return buildDataProcessingError((message) => new DataCorruptionError(message, {}), errorMessage, dataCorruptionCodepath, messageLike, props, stackTraceLimit);
|
|
147
|
+
}
|
|
66
148
|
}
|
|
67
149
|
/**
|
|
68
150
|
* Indicates we hit a fatal error while processing incoming data from the Fluid Service.
|
|
@@ -88,22 +170,7 @@ export class DataProcessingError extends LoggingError {
|
|
|
88
170
|
* Create a new `DataProcessingError` detected and raised within the Fluid Framework.
|
|
89
171
|
*/
|
|
90
172
|
static create(errorMessage, dataProcessingCodepath, messageLike, props = {}, stackTraceLimit) {
|
|
91
|
-
|
|
92
|
-
const originalStackTraceLimit = ErrorConfig.stackTraceLimit;
|
|
93
|
-
try {
|
|
94
|
-
if (stackTraceLimit !== undefined) {
|
|
95
|
-
ErrorConfig.stackTraceLimit = stackTraceLimit;
|
|
96
|
-
}
|
|
97
|
-
const dataProcessingError = DataProcessingError.wrapIfUnrecognized(errorMessage, dataProcessingCodepath, messageLike);
|
|
98
|
-
dataProcessingError.addTelemetryProperties(props);
|
|
99
|
-
return dataProcessingError;
|
|
100
|
-
}
|
|
101
|
-
finally {
|
|
102
|
-
// Reset the stack trace limit to the original value
|
|
103
|
-
if (stackTraceLimit !== undefined) {
|
|
104
|
-
ErrorConfig.stackTraceLimit = originalStackTraceLimit;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
173
|
+
return buildDataProcessingError((message) => new DataProcessingError(message), errorMessage, dataProcessingCodepath, messageLike, props, stackTraceLimit);
|
|
107
174
|
}
|
|
108
175
|
/**
|
|
109
176
|
* Wrap the given error in a `DataProcessingError`, unless the error is already of a known type
|
|
@@ -111,11 +178,7 @@ export class DataProcessingError extends LoggingError {
|
|
|
111
178
|
*
|
|
112
179
|
* In either case, the error will have some relevant properties added for telemetry.
|
|
113
180
|
*
|
|
114
|
-
* @remarks
|
|
115
|
-
*
|
|
116
|
-
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
117
|
-
* one day we will move away from throwing these errors but rather we'll return them.
|
|
118
|
-
* But an unrecognized error needs to be classified as `DataProcessingError`.
|
|
181
|
+
* @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.
|
|
119
182
|
*
|
|
120
183
|
* @param originalError - The error to be converted.
|
|
121
184
|
* @param dataProcessingCodepath - Which code-path failed while processing data.
|
|
@@ -124,25 +187,7 @@ export class DataProcessingError extends LoggingError {
|
|
|
124
187
|
* @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.
|
|
125
188
|
*/
|
|
126
189
|
static wrapIfUnrecognized(originalError, dataProcessingCodepath, messageLike) {
|
|
127
|
-
|
|
128
|
-
dataProcessingError: 1,
|
|
129
|
-
dataProcessingCodepath,
|
|
130
|
-
...(messageLike === undefined
|
|
131
|
-
? undefined
|
|
132
|
-
: extractSafePropertiesFromMessage(messageLike)),
|
|
133
|
-
};
|
|
134
|
-
const normalizedError = normalizeError(originalError, { props });
|
|
135
|
-
// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,
|
|
136
|
-
// but if so they are still suitable to be wrapped as DataProcessingError.
|
|
137
|
-
if (isExternalError(normalizedError) ||
|
|
138
|
-
normalizedError.errorType === NORMALIZED_ERROR_TYPE) {
|
|
139
|
-
// Create a new DataProcessingError to wrap this external error
|
|
140
|
-
const dataProcessingError = wrapError(normalizedError, (message) => new DataProcessingError(message));
|
|
141
|
-
// Copy over the props above and any others added to this error since first being normalized
|
|
142
|
-
dataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());
|
|
143
|
-
return dataProcessingError;
|
|
144
|
-
}
|
|
145
|
-
return normalizedError;
|
|
190
|
+
return wrapDataProcessingErrorIfUnrecognized((errorMessage, props) => new DataProcessingError(errorMessage, props), originalError, dataProcessingCodepath, messageLike);
|
|
146
191
|
}
|
|
147
192
|
}
|
|
148
193
|
/**
|
package/lib/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IErrorBase, ITelemetryBaseProperties } from \"@fluidframework/core-interfaces\";\nimport {\n\tFluidErrorTypes,\n\ttype IGenericError,\n\ttype ILayerIncompatibilityError,\n\ttype IUsageError,\n} from \"@fluidframework/core-interfaces/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tisExternalError,\n\tnormalizeError,\n\twrapError,\n} from \"./errorLogging.js\";\nimport type { IFluidErrorBase } from \"./fluidErrorBase.js\";\nimport type { ITelemetryPropertiesExt } from \"./telemetryTypes.js\";\n\n/**\n * Throws a UsageError with the given message if the condition is not met.\n * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).\n *\n * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.\n * @param message - The message to include in the error when the condition does not hold.\n * @param props - Telemetry props to include on the error when the condition does not hold.\n * @internal\n */\nexport function validatePrecondition(\n\tcondition: boolean,\n\tmessage: string,\n\tprops?: ITelemetryBaseProperties,\n): asserts condition {\n\tif (!condition) {\n\t\tthrow new UsageError(message, props);\n\t}\n}\n\n/**\n * Generic wrapper for an unrecognized/uncategorized error object\n *\n * @internal\n */\nexport class GenericError extends LoggingError implements IGenericError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.genericError;\n\n\t/**\n\t * Create a new GenericError\n\t * @param message - Error message\n\t * @param error - inner error object\n\t * @param props - Telemetry props to include when the error is logged\n\t */\n\tpublic constructor(\n\t\tmessage: string,\n\t\t// TODO: Use `unknown` instead (API breaking change because error is not just an input parameter, but a public member of the class)\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\tpublic readonly error?: any,\n\t\tprops?: ITelemetryBaseProperties,\n\t) {\n\t\t// Don't try to log the inner error\n\t\tsuper(message, props, new Set([\"error\"]));\n\t}\n}\n\n/**\n * Error indicating an API is being used improperly resulting in an invalid operation.\n *\n * @internal\n */\nexport class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.usageError;\n\n\tpublic constructor(message: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, usageError: true });\n\t}\n}\n\n/**\n * DataCorruptionError indicates that we encountered definitive evidence that the data at rest\n * backing this container is corrupted, and this container would never be expected to load properly again\n *\n * @internal\n */\nexport class DataCorruptionError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.dataCorruptionError;\n\tpublic readonly canRetry = false;\n\n\tpublic constructor(message: string, props: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, dataProcessingError: 1 });\n\t}\n}\n\n/**\n * Indicates we hit a fatal error while processing incoming data from the Fluid Service.\n *\n * @remarks\n *\n * The error will often originate in the dataStore or DDS implementation that is responding to incoming changes.\n * This differs from {@link DataCorruptionError} in that this may be a transient error that will not repro in another\n * client or session.\n *\n * @internal\n */\nexport class DataProcessingError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\t/**\n\t * {@inheritDoc IFluidErrorBase.errorType}\n\t */\n\tpublic readonly errorType = FluidErrorTypes.dataProcessingError;\n\n\tpublic readonly canRetry = false;\n\n\tprivate constructor(errorMessage: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(errorMessage, props);\n\t}\n\n\t/**\n\t * Create a new `DataProcessingError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: Partial<\n\t\t\tPick<\n\t\t\t\tISequencedDocumentMessage,\n\t\t\t\t| \"clientId\"\n\t\t\t\t| \"sequenceNumber\"\n\t\t\t\t| \"clientSequenceNumber\"\n\t\t\t\t| \"referenceSequenceNumber\"\n\t\t\t\t| \"minimumSequenceNumber\"\n\t\t\t\t| \"timestamp\"\n\t\t\t>\n\t\t>,\n\t\tprops: ITelemetryPropertiesExt = {},\n\t\tstackTraceLimit?: number,\n\t): IFluidErrorBase {\n\t\tconst ErrorConfig = Error as unknown as { stackTraceLimit: number };\n\t\tconst originalStackTraceLimit = ErrorConfig.stackTraceLimit;\n\t\ttry {\n\t\t\tif (stackTraceLimit !== undefined) {\n\t\t\t\tErrorConfig.stackTraceLimit = stackTraceLimit;\n\t\t\t}\n\n\t\t\tconst dataProcessingError = DataProcessingError.wrapIfUnrecognized(\n\t\t\t\terrorMessage,\n\t\t\t\tdataProcessingCodepath,\n\t\t\t\tmessageLike,\n\t\t\t);\n\t\t\tdataProcessingError.addTelemetryProperties(props);\n\n\t\t\treturn dataProcessingError;\n\t\t} finally {\n\t\t\t// Reset the stack trace limit to the original value\n\t\t\tif (stackTraceLimit !== undefined) {\n\t\t\t\tErrorConfig.stackTraceLimit = originalStackTraceLimit;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Wrap the given error in a `DataProcessingError`, unless the error is already of a known type\n\t * with the exception of a normalized {@link LoggingError}, which will still be wrapped.\n\t *\n\t * In either case, the error will have some relevant properties added for telemetry.\n\t *\n\t * @remarks\n\t *\n\t * We wrap conditionally since known error types represent well-understood failure modes, and ideally\n\t * one day we will move away from throwing these errors but rather we'll return them.\n\t * But an unrecognized error needs to be classified as `DataProcessingError`.\n\t *\n\t * @param originalError - The error to be converted.\n\t * @param dataProcessingCodepath - Which code-path failed while processing data.\n\t * @param messageLike - Message to include info about via telemetry props.\n\t *\n\t * @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.\n\t */\n\tpublic static wrapIfUnrecognized(\n\t\toriginalError: unknown,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: Partial<\n\t\t\tPick<\n\t\t\t\tISequencedDocumentMessage,\n\t\t\t\t| \"clientId\"\n\t\t\t\t| \"sequenceNumber\"\n\t\t\t\t| \"clientSequenceNumber\"\n\t\t\t\t| \"referenceSequenceNumber\"\n\t\t\t\t| \"minimumSequenceNumber\"\n\t\t\t\t| \"timestamp\"\n\t\t\t>\n\t\t>,\n\t): IFluidErrorBase {\n\t\tconst props = {\n\t\t\tdataProcessingError: 1,\n\t\t\tdataProcessingCodepath,\n\t\t\t...(messageLike === undefined\n\t\t\t\t? undefined\n\t\t\t\t: extractSafePropertiesFromMessage(messageLike)),\n\t\t};\n\n\t\tconst normalizedError = normalizeError(originalError, { props });\n\t\t// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,\n\t\t// but if so they are still suitable to be wrapped as DataProcessingError.\n\t\tif (\n\t\t\tisExternalError(normalizedError) ||\n\t\t\tnormalizedError.errorType === NORMALIZED_ERROR_TYPE\n\t\t) {\n\t\t\t// Create a new DataProcessingError to wrap this external error\n\t\t\tconst dataProcessingError = wrapError(\n\t\t\t\tnormalizedError,\n\t\t\t\t(message: string) => new DataProcessingError(message),\n\t\t\t);\n\n\t\t\t// Copy over the props above and any others added to this error since first being normalized\n\t\t\tdataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());\n\n\t\t\treturn dataProcessingError;\n\t\t}\n\t\treturn normalizedError;\n\t}\n}\n\n/**\n * Error indicating that two Fluid layers are incompatible.\n * See {@link @fluidframework/core-interfaces#ILayerIncompatibilityError} for more details.\n *\n * @internal\n */\nexport class LayerIncompatibilityError\n\textends LoggingError\n\timplements ILayerIncompatibilityError\n{\n\tpublic readonly errorType = FluidErrorTypes.layerIncompatibilityError;\n\tpublic readonly layer: string;\n\tpublic readonly layerVersion: string;\n\tpublic readonly incompatibleLayer: string;\n\tpublic readonly incompatibleLayerVersion: string;\n\tpublic readonly compatibilityRequirementsInMonths: number;\n\tpublic readonly actualDifferenceInMonths: number;\n\tpublic readonly details: string;\n\n\tpublic constructor(\n\t\tmessage: string,\n\t\tincompatibilityProps: {\n\t\t\tlayer: string;\n\t\t\tlayerVersion: string;\n\t\t\tincompatibleLayer: string;\n\t\t\tincompatibleLayerVersion: string;\n\t\t\tcompatibilityRequirementsInMonths: number;\n\t\t\tactualDifferenceInMonths: number;\n\t\t\tdetails: string;\n\t\t},\n\t\ttelemetryProps?: ITelemetryBaseProperties,\n\t) {\n\t\tsuper(message, {\n\t\t\t...incompatibilityProps,\n\t\t\t...telemetryProps,\n\t\t\tlayerIncompatibilityError: true,\n\t\t});\n\t\tthis.layer = incompatibilityProps.layer;\n\t\tthis.layerVersion = incompatibilityProps.layerVersion;\n\t\tthis.incompatibleLayer = incompatibilityProps.incompatibleLayer;\n\t\tthis.incompatibleLayerVersion = incompatibilityProps.incompatibleLayerVersion;\n\t\tthis.compatibilityRequirementsInMonths =\n\t\t\tincompatibilityProps.compatibilityRequirementsInMonths;\n\t\tthis.actualDifferenceInMonths = incompatibilityProps.actualDifferenceInMonths;\n\t\tthis.details = incompatibilityProps.details;\n\t}\n}\n\n/**\n * Extracts specific properties from the provided message that we know are safe to log.\n *\n * @param messageLike - Message to include info about via telemetry props.\n *\n * @internal\n */\nexport const extractSafePropertiesFromMessage = (\n\tmessageLike: Partial<\n\t\tPick<\n\t\t\tISequencedDocumentMessage,\n\t\t\t| \"clientId\"\n\t\t\t| \"sequenceNumber\"\n\t\t\t| \"clientSequenceNumber\"\n\t\t\t| \"referenceSequenceNumber\"\n\t\t\t| \"minimumSequenceNumber\"\n\t\t\t| \"timestamp\"\n\t\t>\n\t>,\n): {\n\tmessageClientId: string | undefined;\n\tmessageSequenceNumber: number | undefined;\n\tmessageClientSequenceNumber: number | undefined;\n\tmessageReferenceSequenceNumber: number | undefined;\n\tmessageMinimumSequenceNumber: number | undefined;\n\tmessageTimestamp: number | undefined;\n} => ({\n\tmessageClientId: messageLike.clientId === null ? \"null\" : messageLike.clientId,\n\tmessageSequenceNumber: messageLike.sequenceNumber,\n\tmessageClientSequenceNumber: messageLike.clientSequenceNumber,\n\tmessageReferenceSequenceNumber: messageLike.referenceSequenceNumber,\n\tmessageMinimumSequenceNumber: messageLike.minimumSequenceNumber,\n\tmessageTimestamp: messageLike.timestamp,\n});\n"]}
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IErrorBase, ITelemetryBaseProperties } from \"@fluidframework/core-interfaces\";\nimport {\n\tFluidErrorTypes,\n\ttype IGenericError,\n\ttype ILayerIncompatibilityError,\n\ttype IUsageError,\n} from \"@fluidframework/core-interfaces/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tisExternalError,\n\tnormalizeError,\n\twrapError,\n} from \"./errorLogging.js\";\nimport type { IFluidErrorBase } from \"./fluidErrorBase.js\";\nimport type { ITelemetryPropertiesExt } from \"./telemetryTypes.js\";\n\n/**\n * A subset of `ISequencedDocumentMessage` properties that are safe to log for telemetry.\n * @internal\n */\nexport type MessageLike = Partial<\n\tPick<\n\t\tISequencedDocumentMessage,\n\t\t| \"clientId\"\n\t\t| \"sequenceNumber\"\n\t\t| \"clientSequenceNumber\"\n\t\t| \"referenceSequenceNumber\"\n\t\t| \"minimumSequenceNumber\"\n\t\t| \"timestamp\"\n\t>\n>;\n\n/**\n * Throws a UsageError with the given message if the condition is not met.\n * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).\n *\n * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.\n * @param message - The message to include in the error when the condition does not hold.\n * @param props - Telemetry props to include on the error when the condition does not hold.\n * @internal\n */\nexport function validatePrecondition(\n\tcondition: boolean,\n\tmessage: string,\n\tprops?: ITelemetryBaseProperties,\n): asserts condition {\n\tif (!condition) {\n\t\tthrow new UsageError(message, props);\n\t}\n}\n\n/**\n * Creates an error during data processing (DataProcessingError or DataCorruptionError) with telemetry properties.\n *\n * @remarks\n * This helper allows customizing the stack trace limit during error creation, which is useful\n * for capturing more context in error scenarios. It delegates to {@link wrapOrAnnotateError}\n * for the actual error wrapping/annotation logic.\n *\n * @param factory - Factory function that creates the specific error type.\n * @param errorMessage - The error message to use.\n * @param codepath - Identifier for the code path where the error was detected.\n * @param messageLike - Optional message properties to include in telemetry.\n * @param props - Additional telemetry properties to attach to the error.\n * @param stackTraceLimit - Optional limit for the stack trace depth.\n * @returns The created error with telemetry properties attached.\n */\nfunction buildDataProcessingError(\n\tfactory: (message: string) => LoggingError & IFluidErrorBase,\n\terrorMessage: string,\n\tcodepath: string,\n\tmessageLike?: MessageLike,\n\tprops: ITelemetryPropertiesExt = {},\n\tstackTraceLimit?: number,\n): IFluidErrorBase {\n\tconst ErrorConfig = Error as unknown as { stackTraceLimit: number };\n\tconst originalStackTraceLimit = ErrorConfig.stackTraceLimit;\n\ttry {\n\t\tif (stackTraceLimit !== undefined) {\n\t\t\tErrorConfig.stackTraceLimit = stackTraceLimit;\n\t\t}\n\n\t\tconst error = wrapDataProcessingErrorIfUnrecognized(\n\t\t\tfactory,\n\t\t\terrorMessage,\n\t\t\tcodepath,\n\t\t\tmessageLike,\n\t\t);\n\t\terror.addTelemetryProperties(props);\n\n\t\treturn error;\n\t} finally {\n\t\t// Reset the stack trace limit to the original value\n\t\tif (stackTraceLimit !== undefined) {\n\t\t\tErrorConfig.stackTraceLimit = originalStackTraceLimit;\n\t\t}\n\t}\n}\n\n/**\n * Wraps an unrecognized error into a data processing error (DataProcessingError or DataCorruptionError)\n * using the provided factory.\n *\n * @remarks\n * This function handles two cases:\n * - **Unrecognized/external errors**: Wrapped using the provided factory function to create a proper\n * Fluid error type (DataProcessingError or DataCorruptionError).\n * - **Recognized Fluid errors**: Not wrapped, but annotated with data processing telemetry properties.\n *\n * An error is considered \"unrecognized\" if it's external (from outside Fluid) or has the\n * {@link NORMALIZED_ERROR_TYPE} error type (indicating it was normalized but not classified).\n *\n * We wrap conditionally since known error types represent well-understood failure modes, and ideally\n * one day we will move away from throwing these errors but rather we'll return them.\n * But an unrecognized error needs to be classified appropriately (e.g., as DataProcessingError).\n *\n * @param factory - Factory function that creates the specific error type for wrapping unrecognized errors.\n * @param originalError - The error to be wrapped or annotated.\n * @param codepath - Identifier for the code path where the error was detected.\n * @param messageLike - Optional message properties to include in telemetry.\n * @returns The wrapped or annotated error as an {@link IFluidErrorBase}.\n */\nfunction wrapDataProcessingErrorIfUnrecognized(\n\tfactory: (message: string) => LoggingError & IFluidErrorBase,\n\toriginalError: unknown,\n\tcodepath: string,\n\tmessageLike?: MessageLike,\n): IFluidErrorBase {\n\tconst props = {\n\t\tdataProcessingError: 1,\n\t\tdataProcessingCodepath: codepath,\n\t\t...(messageLike === undefined ? undefined : extractSafePropertiesFromMessage(messageLike)),\n\t};\n\n\tconst normalizedError = normalizeError(originalError, { props });\n\t// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,\n\t// but if so they are still suitable to be wrapped as DataProcessingError.\n\tif (\n\t\tisExternalError(normalizedError) ||\n\t\tnormalizedError.errorType === NORMALIZED_ERROR_TYPE\n\t) {\n\t\t// Create a new DataProcessingError to wrap this external error\n\t\tconst error = wrapError(normalizedError, (message: string) => factory(message));\n\n\t\t// Copy over the props above and any others added to this error since first being normalized\n\t\terror.addTelemetryProperties(normalizedError.getTelemetryProperties());\n\n\t\treturn error;\n\t}\n\treturn normalizedError;\n}\n\n/**\n * Generic wrapper for an unrecognized/uncategorized error object\n *\n * @internal\n */\nexport class GenericError extends LoggingError implements IGenericError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.genericError;\n\n\t/**\n\t * Create a new GenericError\n\t * @param message - Error message\n\t * @param error - inner error object\n\t * @param props - Telemetry props to include when the error is logged\n\t */\n\tpublic constructor(\n\t\tmessage: string,\n\t\t// TODO: Use `unknown` instead (API breaking change because error is not just an input parameter, but a public member of the class)\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\tpublic readonly error?: any,\n\t\tprops?: ITelemetryBaseProperties,\n\t) {\n\t\t// Don't try to log the inner error\n\t\tsuper(message, props, new Set([\"error\"]));\n\t}\n}\n\n/**\n * Error indicating an API is being used improperly resulting in an invalid operation.\n *\n * @internal\n */\nexport class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.usageError;\n\n\tpublic constructor(message: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, usageError: true });\n\t}\n}\n\n/**\n * DataCorruptionError indicates that we encountered definitive evidence that the data at rest\n * backing this container is corrupted, and this container would never be expected to load properly again\n *\n * @internal\n */\nexport class DataCorruptionError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\tpublic readonly errorType = FluidErrorTypes.dataCorruptionError;\n\tpublic readonly canRetry = false;\n\n\tpublic constructor(message: string, props: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, dataProcessingError: 1 });\n\t}\n\n\t/**\n\t * Create a new `DataCorruptionError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataCorruptionCodepath: string,\n\t\tmessageLike?: MessageLike,\n\t\tprops: ITelemetryPropertiesExt = {},\n\t\tstackTraceLimit?: number,\n\t): IFluidErrorBase {\n\t\treturn buildDataProcessingError(\n\t\t\t(message: string) => new DataCorruptionError(message, {}),\n\t\t\terrorMessage,\n\t\t\tdataCorruptionCodepath,\n\t\t\tmessageLike,\n\t\t\tprops,\n\t\t\tstackTraceLimit,\n\t\t);\n\t}\n}\n\n/**\n * Indicates we hit a fatal error while processing incoming data from the Fluid Service.\n *\n * @remarks\n *\n * The error will often originate in the dataStore or DDS implementation that is responding to incoming changes.\n * This differs from {@link DataCorruptionError} in that this may be a transient error that will not repro in another\n * client or session.\n *\n * @internal\n */\nexport class DataProcessingError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\t/**\n\t * {@inheritDoc IFluidErrorBase.errorType}\n\t */\n\tpublic readonly errorType = FluidErrorTypes.dataProcessingError;\n\n\tpublic readonly canRetry = false;\n\n\tprivate constructor(errorMessage: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(errorMessage, props);\n\t}\n\n\t/**\n\t * Create a new `DataProcessingError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: MessageLike,\n\t\tprops: ITelemetryPropertiesExt = {},\n\t\tstackTraceLimit?: number,\n\t): IFluidErrorBase {\n\t\treturn buildDataProcessingError(\n\t\t\t(message: string) => new DataProcessingError(message),\n\t\t\terrorMessage,\n\t\t\tdataProcessingCodepath,\n\t\t\tmessageLike,\n\t\t\tprops,\n\t\t\tstackTraceLimit,\n\t\t);\n\t}\n\n\t/**\n\t * Wrap the given error in a `DataProcessingError`, unless the error is already of a known type\n\t * with the exception of a normalized {@link LoggingError}, which will still be wrapped.\n\t *\n\t * In either case, the error will have some relevant properties added for telemetry.\n\t *\n\t * @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.\n\t *\n\t * @param originalError - The error to be converted.\n\t * @param dataProcessingCodepath - Which code-path failed while processing data.\n\t * @param messageLike - Message to include info about via telemetry props.\n\t *\n\t * @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.\n\t */\n\tpublic static wrapIfUnrecognized(\n\t\toriginalError: unknown,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: MessageLike,\n\t): IFluidErrorBase {\n\t\treturn wrapDataProcessingErrorIfUnrecognized(\n\t\t\t(errorMessage: string, props?: ITelemetryBaseProperties) =>\n\t\t\t\tnew DataProcessingError(errorMessage, props),\n\t\t\toriginalError,\n\t\t\tdataProcessingCodepath,\n\t\t\tmessageLike,\n\t\t);\n\t}\n}\n\n/**\n * Error indicating that two Fluid layers are incompatible.\n * See {@link @fluidframework/core-interfaces#ILayerIncompatibilityError} for more details.\n *\n * @internal\n */\nexport class LayerIncompatibilityError\n\textends LoggingError\n\timplements ILayerIncompatibilityError\n{\n\tpublic readonly errorType = FluidErrorTypes.layerIncompatibilityError;\n\tpublic readonly layer: string;\n\tpublic readonly layerVersion: string;\n\tpublic readonly incompatibleLayer: string;\n\tpublic readonly incompatibleLayerVersion: string;\n\tpublic readonly compatibilityRequirementsInMonths: number;\n\tpublic readonly actualDifferenceInMonths: number;\n\tpublic readonly details: string;\n\n\tpublic constructor(\n\t\tmessage: string,\n\t\tincompatibilityProps: {\n\t\t\tlayer: string;\n\t\t\tlayerVersion: string;\n\t\t\tincompatibleLayer: string;\n\t\t\tincompatibleLayerVersion: string;\n\t\t\tcompatibilityRequirementsInMonths: number;\n\t\t\tactualDifferenceInMonths: number;\n\t\t\tdetails: string;\n\t\t},\n\t\ttelemetryProps?: ITelemetryBaseProperties,\n\t) {\n\t\tsuper(message, {\n\t\t\t...incompatibilityProps,\n\t\t\t...telemetryProps,\n\t\t\tlayerIncompatibilityError: true,\n\t\t});\n\t\tthis.layer = incompatibilityProps.layer;\n\t\tthis.layerVersion = incompatibilityProps.layerVersion;\n\t\tthis.incompatibleLayer = incompatibilityProps.incompatibleLayer;\n\t\tthis.incompatibleLayerVersion = incompatibilityProps.incompatibleLayerVersion;\n\t\tthis.compatibilityRequirementsInMonths =\n\t\t\tincompatibilityProps.compatibilityRequirementsInMonths;\n\t\tthis.actualDifferenceInMonths = incompatibilityProps.actualDifferenceInMonths;\n\t\tthis.details = incompatibilityProps.details;\n\t}\n}\n\n/**\n * Extracts specific properties from the provided message that we know are safe to log.\n *\n * @param messageLike - Message to include info about via telemetry props.\n *\n * @internal\n */\nexport const extractSafePropertiesFromMessage = (\n\tmessageLike: MessageLike,\n): {\n\tmessageClientId: string | undefined;\n\tmessageSequenceNumber: number | undefined;\n\tmessageClientSequenceNumber: number | undefined;\n\tmessageReferenceSequenceNumber: number | undefined;\n\tmessageMinimumSequenceNumber: number | undefined;\n\tmessageTimestamp: number | undefined;\n} => ({\n\tmessageClientId: messageLike.clientId === null ? \"null\" : messageLike.clientId,\n\tmessageSequenceNumber: messageLike.sequenceNumber,\n\tmessageClientSequenceNumber: messageLike.clientSequenceNumber,\n\tmessageReferenceSequenceNumber: messageLike.referenceSequenceNumber,\n\tmessageMinimumSequenceNumber: messageLike.minimumSequenceNumber,\n\tmessageTimestamp: messageLike.timestamp,\n});\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
export { createChildMonitoringContext, type MonitoringContext, sessionStorageConfigProvider, mixinMonitoringContext, type IConfigProvider, loggerToMonitoringContext, wrapConfigProviderWithDefaults, createConfigBasedOptionsProxy, type OptionConfigReaders, } from "./config.js";
|
|
6
|
-
export { DataCorruptionError, DataProcessingError, extractSafePropertiesFromMessage, GenericError, UsageError, validatePrecondition, LayerIncompatibilityError, } from "./error.js";
|
|
6
|
+
export { DataCorruptionError, DataProcessingError, extractSafePropertiesFromMessage, GenericError, UsageError, validatePrecondition, LayerIncompatibilityError, type MessageLike, } from "./error.js";
|
|
7
7
|
export { extractLogSafeErrorProperties, generateErrorWithStack, generateStack, getCircularReplacer, type IFluidErrorAnnotations, isExternalError, isILoggingError, isTaggedTelemetryPropertyValue, LoggingError, NORMALIZED_ERROR_TYPE, normalizeError, overwriteStack, wrapError, wrapErrorAndLog, } from "./errorLogging.js";
|
|
8
8
|
export { EventEmitterWithErrorHandling } from "./eventEmitterWithErrorHandling.js";
|
|
9
9
|
export { connectedEventName, disconnectedEventName, raiseConnectedEvent, safeRaiseEvent, } from "./events.js";
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,eAAe,EACpB,yBAAyB,EACzB,8BAA8B,EAC9B,6BAA6B,EAC7B,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,eAAe,EACpB,yBAAyB,EACzB,8BAA8B,EAC9B,6BAA6B,EAC7B,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,WAAW,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,6BAA6B,EAC7B,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,eAAe,EACf,eAAe,EACf,8BAA8B,EAC9B,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,SAAS,EACT,eAAe,GACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EACN,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kBAAkB,EAClB,KAAK,eAAe,EACpB,YAAY,EACZ,2BAA2B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAC9B,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,2BAA2B,GAChC,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,KAAK,cAAc,EACnB,UAAU,GACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACN,sBAAsB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,OAAO,GACP,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,6BAA6B,EAC7B,kBAAkB,EAClB,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC"}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,4BAA4B,EAE5B,4BAA4B,EAC5B,sBAAsB,EAEtB,yBAAyB,EACzB,8BAA8B,EAC9B,6BAA6B,GAE7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,4BAA4B,EAE5B,4BAA4B,EAC5B,sBAAsB,EAEtB,yBAAyB,EACzB,8BAA8B,EAC9B,6BAA6B,GAE7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,yBAAyB,GAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,6BAA6B,EAC7B,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EAEnB,eAAe,EACf,eAAe,EACf,8BAA8B,EAC9B,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,SAAS,EACT,eAAe,GACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EACN,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kBAAkB,EAElB,YAAY,EACZ,2BAA2B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EAKV,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,GAEhB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EAEnB,UAAU,GACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACN,sBAAsB,GAItB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,mBAAmB,EAGnB,OAAO,GACP,MAAM,YAAY,CAAC;AAWpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tcreateChildMonitoringContext,\n\ttype MonitoringContext,\n\tsessionStorageConfigProvider,\n\tmixinMonitoringContext,\n\ttype IConfigProvider,\n\tloggerToMonitoringContext,\n\twrapConfigProviderWithDefaults,\n\tcreateConfigBasedOptionsProxy,\n\ttype OptionConfigReaders,\n} from \"./config.js\";\nexport {\n\tDataCorruptionError,\n\tDataProcessingError,\n\textractSafePropertiesFromMessage,\n\tGenericError,\n\tUsageError,\n\tvalidatePrecondition,\n\tLayerIncompatibilityError,\n\ttype MessageLike,\n} from \"./error.js\";\nexport {\n\textractLogSafeErrorProperties,\n\tgenerateErrorWithStack,\n\tgenerateStack,\n\tgetCircularReplacer,\n\ttype IFluidErrorAnnotations,\n\tisExternalError,\n\tisILoggingError,\n\tisTaggedTelemetryPropertyValue,\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tnormalizeError,\n\toverwriteStack,\n\twrapError,\n\twrapErrorAndLog,\n} from \"./errorLogging.js\";\nexport { EventEmitterWithErrorHandling } from \"./eventEmitterWithErrorHandling.js\";\nexport {\n\tconnectedEventName,\n\tdisconnectedEventName,\n\traiseConnectedEvent,\n\tsafeRaiseEvent,\n} from \"./events.js\";\nexport {\n\thasErrorInstanceId,\n\ttype IFluidErrorBase,\n\tisFluidError,\n\tisLayerIncompatibilityError,\n} from \"./fluidErrorBase.js\";\nexport {\n\teventNamespaceSeparator,\n\tcreateChildLogger,\n\tcreateMultiSinkLogger,\n\tformatTick,\n\ttype IPerformanceEventMarkers,\n\ttype ITelemetryLoggerPropertyBag,\n\ttype ITelemetryLoggerPropertyBags,\n\ttype MultiSinkLoggerProperties,\n\tnumberFromString,\n\tPerformanceEvent,\n\tTaggedLoggerAdapter,\n\ttagData,\n\ttagCodeArtifacts,\n\tTelemetryDataTag,\n\ttype TelemetryEventPropertyTypes,\n} from \"./logger.js\";\nexport {\n\tcreateMockLoggerExt,\n\ttype IMockLoggerExt,\n\tMockLogger,\n} from \"./mockLogger.js\";\nexport { ThresholdCounter } from \"./thresholdCounter.js\";\nexport {\n\tSampledTelemetryHelper,\n\ttype CustomMetrics,\n\ttype ICustomData,\n\ttype MeasureReturnType,\n} from \"./sampledTelemetryHelper.js\";\nexport {\n\tcreateSampledLogger,\n\ttype IEventSampler,\n\ttype ISampledTelemetryLogger,\n\tmeasure,\n} from \"./utils.js\";\nexport type {\n\tTelemetryEventPropertyTypeExt,\n\tITelemetryEventExt,\n\tITelemetryGenericEventExt,\n\tITelemetryErrorEventExt,\n\tITelemetryPerformanceEventExt,\n\tITelemetryLoggerExt,\n\tITelemetryPropertiesExt,\n\tTelemetryEventCategory,\n} from \"./telemetryTypes.js\";\nexport { TelemetryEventBatcher } from \"./telemetryEventBatcher.js\";\nexport { allowIncompatibleLayersKey, validateLayerCompatibility } from \"./layerCompatError.js\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/telemetry-utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.82.0",
|
|
4
4
|
"description": "Collection of telemetry relates utilities for Fluid",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -69,26 +69,26 @@
|
|
|
69
69
|
"temp-directory": "nyc/.nyc_output"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@fluid-internal/client-utils": "~2.
|
|
73
|
-
"@fluidframework/core-interfaces": "~2.
|
|
74
|
-
"@fluidframework/core-utils": "~2.
|
|
75
|
-
"@fluidframework/driver-definitions": "~2.
|
|
72
|
+
"@fluid-internal/client-utils": "~2.82.0",
|
|
73
|
+
"@fluidframework/core-interfaces": "~2.82.0",
|
|
74
|
+
"@fluidframework/core-utils": "~2.82.0",
|
|
75
|
+
"@fluidframework/driver-definitions": "~2.82.0",
|
|
76
76
|
"debug": "^4.3.4",
|
|
77
77
|
"uuid": "^11.1.0"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
81
81
|
"@biomejs/biome": "~1.9.3",
|
|
82
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
82
|
+
"@fluid-internal/mocha-test-setup": "~2.82.0",
|
|
83
83
|
"@fluid-tools/build-cli": "^0.63.0",
|
|
84
84
|
"@fluidframework/build-common": "^2.0.3",
|
|
85
85
|
"@fluidframework/build-tools": "^0.63.0",
|
|
86
|
-
"@fluidframework/eslint-config-fluid": "~2.
|
|
86
|
+
"@fluidframework/eslint-config-fluid": "~2.82.0",
|
|
87
87
|
"@fluidframework/telemetry-utils-previous": "npm:@fluidframework/telemetry-utils@2.81.0",
|
|
88
88
|
"@microsoft/api-extractor": "7.52.11",
|
|
89
89
|
"@types/debug": "^4.1.5",
|
|
90
90
|
"@types/mocha": "^10.0.10",
|
|
91
|
-
"@types/node": "
|
|
91
|
+
"@types/node": "~20.19.30",
|
|
92
92
|
"@types/sinon": "^17.0.3",
|
|
93
93
|
"c8": "^10.1.3",
|
|
94
94
|
"concurrently": "^9.2.1",
|
package/src/error.ts
CHANGED
|
@@ -22,6 +22,22 @@ import {
|
|
|
22
22
|
import type { IFluidErrorBase } from "./fluidErrorBase.js";
|
|
23
23
|
import type { ITelemetryPropertiesExt } from "./telemetryTypes.js";
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* A subset of `ISequencedDocumentMessage` properties that are safe to log for telemetry.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export type MessageLike = Partial<
|
|
30
|
+
Pick<
|
|
31
|
+
ISequencedDocumentMessage,
|
|
32
|
+
| "clientId"
|
|
33
|
+
| "sequenceNumber"
|
|
34
|
+
| "clientSequenceNumber"
|
|
35
|
+
| "referenceSequenceNumber"
|
|
36
|
+
| "minimumSequenceNumber"
|
|
37
|
+
| "timestamp"
|
|
38
|
+
>
|
|
39
|
+
>;
|
|
40
|
+
|
|
25
41
|
/**
|
|
26
42
|
* Throws a UsageError with the given message if the condition is not met.
|
|
27
43
|
* Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).
|
|
@@ -41,6 +57,107 @@ export function validatePrecondition(
|
|
|
41
57
|
}
|
|
42
58
|
}
|
|
43
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Creates an error during data processing (DataProcessingError or DataCorruptionError) with telemetry properties.
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* This helper allows customizing the stack trace limit during error creation, which is useful
|
|
65
|
+
* for capturing more context in error scenarios. It delegates to {@link wrapOrAnnotateError}
|
|
66
|
+
* for the actual error wrapping/annotation logic.
|
|
67
|
+
*
|
|
68
|
+
* @param factory - Factory function that creates the specific error type.
|
|
69
|
+
* @param errorMessage - The error message to use.
|
|
70
|
+
* @param codepath - Identifier for the code path where the error was detected.
|
|
71
|
+
* @param messageLike - Optional message properties to include in telemetry.
|
|
72
|
+
* @param props - Additional telemetry properties to attach to the error.
|
|
73
|
+
* @param stackTraceLimit - Optional limit for the stack trace depth.
|
|
74
|
+
* @returns The created error with telemetry properties attached.
|
|
75
|
+
*/
|
|
76
|
+
function buildDataProcessingError(
|
|
77
|
+
factory: (message: string) => LoggingError & IFluidErrorBase,
|
|
78
|
+
errorMessage: string,
|
|
79
|
+
codepath: string,
|
|
80
|
+
messageLike?: MessageLike,
|
|
81
|
+
props: ITelemetryPropertiesExt = {},
|
|
82
|
+
stackTraceLimit?: number,
|
|
83
|
+
): IFluidErrorBase {
|
|
84
|
+
const ErrorConfig = Error as unknown as { stackTraceLimit: number };
|
|
85
|
+
const originalStackTraceLimit = ErrorConfig.stackTraceLimit;
|
|
86
|
+
try {
|
|
87
|
+
if (stackTraceLimit !== undefined) {
|
|
88
|
+
ErrorConfig.stackTraceLimit = stackTraceLimit;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const error = wrapDataProcessingErrorIfUnrecognized(
|
|
92
|
+
factory,
|
|
93
|
+
errorMessage,
|
|
94
|
+
codepath,
|
|
95
|
+
messageLike,
|
|
96
|
+
);
|
|
97
|
+
error.addTelemetryProperties(props);
|
|
98
|
+
|
|
99
|
+
return error;
|
|
100
|
+
} finally {
|
|
101
|
+
// Reset the stack trace limit to the original value
|
|
102
|
+
if (stackTraceLimit !== undefined) {
|
|
103
|
+
ErrorConfig.stackTraceLimit = originalStackTraceLimit;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Wraps an unrecognized error into a data processing error (DataProcessingError or DataCorruptionError)
|
|
110
|
+
* using the provided factory.
|
|
111
|
+
*
|
|
112
|
+
* @remarks
|
|
113
|
+
* This function handles two cases:
|
|
114
|
+
* - **Unrecognized/external errors**: Wrapped using the provided factory function to create a proper
|
|
115
|
+
* Fluid error type (DataProcessingError or DataCorruptionError).
|
|
116
|
+
* - **Recognized Fluid errors**: Not wrapped, but annotated with data processing telemetry properties.
|
|
117
|
+
*
|
|
118
|
+
* An error is considered "unrecognized" if it's external (from outside Fluid) or has the
|
|
119
|
+
* {@link NORMALIZED_ERROR_TYPE} error type (indicating it was normalized but not classified).
|
|
120
|
+
*
|
|
121
|
+
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
122
|
+
* one day we will move away from throwing these errors but rather we'll return them.
|
|
123
|
+
* But an unrecognized error needs to be classified appropriately (e.g., as DataProcessingError).
|
|
124
|
+
*
|
|
125
|
+
* @param factory - Factory function that creates the specific error type for wrapping unrecognized errors.
|
|
126
|
+
* @param originalError - The error to be wrapped or annotated.
|
|
127
|
+
* @param codepath - Identifier for the code path where the error was detected.
|
|
128
|
+
* @param messageLike - Optional message properties to include in telemetry.
|
|
129
|
+
* @returns The wrapped or annotated error as an {@link IFluidErrorBase}.
|
|
130
|
+
*/
|
|
131
|
+
function wrapDataProcessingErrorIfUnrecognized(
|
|
132
|
+
factory: (message: string) => LoggingError & IFluidErrorBase,
|
|
133
|
+
originalError: unknown,
|
|
134
|
+
codepath: string,
|
|
135
|
+
messageLike?: MessageLike,
|
|
136
|
+
): IFluidErrorBase {
|
|
137
|
+
const props = {
|
|
138
|
+
dataProcessingError: 1,
|
|
139
|
+
dataProcessingCodepath: codepath,
|
|
140
|
+
...(messageLike === undefined ? undefined : extractSafePropertiesFromMessage(messageLike)),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const normalizedError = normalizeError(originalError, { props });
|
|
144
|
+
// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,
|
|
145
|
+
// but if so they are still suitable to be wrapped as DataProcessingError.
|
|
146
|
+
if (
|
|
147
|
+
isExternalError(normalizedError) ||
|
|
148
|
+
normalizedError.errorType === NORMALIZED_ERROR_TYPE
|
|
149
|
+
) {
|
|
150
|
+
// Create a new DataProcessingError to wrap this external error
|
|
151
|
+
const error = wrapError(normalizedError, (message: string) => factory(message));
|
|
152
|
+
|
|
153
|
+
// Copy over the props above and any others added to this error since first being normalized
|
|
154
|
+
error.addTelemetryProperties(normalizedError.getTelemetryProperties());
|
|
155
|
+
|
|
156
|
+
return error;
|
|
157
|
+
}
|
|
158
|
+
return normalizedError;
|
|
159
|
+
}
|
|
160
|
+
|
|
44
161
|
/**
|
|
45
162
|
* Generic wrapper for an unrecognized/uncategorized error object
|
|
46
163
|
*
|
|
@@ -93,6 +210,26 @@ export class DataCorruptionError extends LoggingError implements IErrorBase, IFl
|
|
|
93
210
|
public constructor(message: string, props: ITelemetryBaseProperties) {
|
|
94
211
|
super(message, { ...props, dataProcessingError: 1 });
|
|
95
212
|
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Create a new `DataCorruptionError` detected and raised within the Fluid Framework.
|
|
216
|
+
*/
|
|
217
|
+
public static create(
|
|
218
|
+
errorMessage: string,
|
|
219
|
+
dataCorruptionCodepath: string,
|
|
220
|
+
messageLike?: MessageLike,
|
|
221
|
+
props: ITelemetryPropertiesExt = {},
|
|
222
|
+
stackTraceLimit?: number,
|
|
223
|
+
): IFluidErrorBase {
|
|
224
|
+
return buildDataProcessingError(
|
|
225
|
+
(message: string) => new DataCorruptionError(message, {}),
|
|
226
|
+
errorMessage,
|
|
227
|
+
dataCorruptionCodepath,
|
|
228
|
+
messageLike,
|
|
229
|
+
props,
|
|
230
|
+
stackTraceLimit,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
96
233
|
}
|
|
97
234
|
|
|
98
235
|
/**
|
|
@@ -124,41 +261,18 @@ export class DataProcessingError extends LoggingError implements IErrorBase, IFl
|
|
|
124
261
|
public static create(
|
|
125
262
|
errorMessage: string,
|
|
126
263
|
dataProcessingCodepath: string,
|
|
127
|
-
messageLike?:
|
|
128
|
-
Pick<
|
|
129
|
-
ISequencedDocumentMessage,
|
|
130
|
-
| "clientId"
|
|
131
|
-
| "sequenceNumber"
|
|
132
|
-
| "clientSequenceNumber"
|
|
133
|
-
| "referenceSequenceNumber"
|
|
134
|
-
| "minimumSequenceNumber"
|
|
135
|
-
| "timestamp"
|
|
136
|
-
>
|
|
137
|
-
>,
|
|
264
|
+
messageLike?: MessageLike,
|
|
138
265
|
props: ITelemetryPropertiesExt = {},
|
|
139
266
|
stackTraceLimit?: number,
|
|
140
267
|
): IFluidErrorBase {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
errorMessage,
|
|
150
|
-
dataProcessingCodepath,
|
|
151
|
-
messageLike,
|
|
152
|
-
);
|
|
153
|
-
dataProcessingError.addTelemetryProperties(props);
|
|
154
|
-
|
|
155
|
-
return dataProcessingError;
|
|
156
|
-
} finally {
|
|
157
|
-
// Reset the stack trace limit to the original value
|
|
158
|
-
if (stackTraceLimit !== undefined) {
|
|
159
|
-
ErrorConfig.stackTraceLimit = originalStackTraceLimit;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
268
|
+
return buildDataProcessingError(
|
|
269
|
+
(message: string) => new DataProcessingError(message),
|
|
270
|
+
errorMessage,
|
|
271
|
+
dataProcessingCodepath,
|
|
272
|
+
messageLike,
|
|
273
|
+
props,
|
|
274
|
+
stackTraceLimit,
|
|
275
|
+
);
|
|
162
276
|
}
|
|
163
277
|
|
|
164
278
|
/**
|
|
@@ -167,11 +281,7 @@ export class DataProcessingError extends LoggingError implements IErrorBase, IFl
|
|
|
167
281
|
*
|
|
168
282
|
* In either case, the error will have some relevant properties added for telemetry.
|
|
169
283
|
*
|
|
170
|
-
* @remarks
|
|
171
|
-
*
|
|
172
|
-
* We wrap conditionally since known error types represent well-understood failure modes, and ideally
|
|
173
|
-
* one day we will move away from throwing these errors but rather we'll return them.
|
|
174
|
-
* But an unrecognized error needs to be classified as `DataProcessingError`.
|
|
284
|
+
* @remarks See `wrapDataProcessingErrorIfUnrecognized` for details on wrapping behavior.
|
|
175
285
|
*
|
|
176
286
|
* @param originalError - The error to be converted.
|
|
177
287
|
* @param dataProcessingCodepath - Which code-path failed while processing data.
|
|
@@ -182,45 +292,15 @@ export class DataProcessingError extends LoggingError implements IErrorBase, IFl
|
|
|
182
292
|
public static wrapIfUnrecognized(
|
|
183
293
|
originalError: unknown,
|
|
184
294
|
dataProcessingCodepath: string,
|
|
185
|
-
messageLike?:
|
|
186
|
-
Pick<
|
|
187
|
-
ISequencedDocumentMessage,
|
|
188
|
-
| "clientId"
|
|
189
|
-
| "sequenceNumber"
|
|
190
|
-
| "clientSequenceNumber"
|
|
191
|
-
| "referenceSequenceNumber"
|
|
192
|
-
| "minimumSequenceNumber"
|
|
193
|
-
| "timestamp"
|
|
194
|
-
>
|
|
195
|
-
>,
|
|
295
|
+
messageLike?: MessageLike,
|
|
196
296
|
): IFluidErrorBase {
|
|
197
|
-
|
|
198
|
-
|
|
297
|
+
return wrapDataProcessingErrorIfUnrecognized(
|
|
298
|
+
(errorMessage: string, props?: ITelemetryBaseProperties) =>
|
|
299
|
+
new DataProcessingError(errorMessage, props),
|
|
300
|
+
originalError,
|
|
199
301
|
dataProcessingCodepath,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
: extractSafePropertiesFromMessage(messageLike)),
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const normalizedError = normalizeError(originalError, { props });
|
|
206
|
-
// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,
|
|
207
|
-
// but if so they are still suitable to be wrapped as DataProcessingError.
|
|
208
|
-
if (
|
|
209
|
-
isExternalError(normalizedError) ||
|
|
210
|
-
normalizedError.errorType === NORMALIZED_ERROR_TYPE
|
|
211
|
-
) {
|
|
212
|
-
// Create a new DataProcessingError to wrap this external error
|
|
213
|
-
const dataProcessingError = wrapError(
|
|
214
|
-
normalizedError,
|
|
215
|
-
(message: string) => new DataProcessingError(message),
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
// Copy over the props above and any others added to this error since first being normalized
|
|
219
|
-
dataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());
|
|
220
|
-
|
|
221
|
-
return dataProcessingError;
|
|
222
|
-
}
|
|
223
|
-
return normalizedError;
|
|
302
|
+
messageLike,
|
|
303
|
+
);
|
|
224
304
|
}
|
|
225
305
|
}
|
|
226
306
|
|
|
@@ -280,17 +360,7 @@ export class LayerIncompatibilityError
|
|
|
280
360
|
* @internal
|
|
281
361
|
*/
|
|
282
362
|
export const extractSafePropertiesFromMessage = (
|
|
283
|
-
messageLike:
|
|
284
|
-
Pick<
|
|
285
|
-
ISequencedDocumentMessage,
|
|
286
|
-
| "clientId"
|
|
287
|
-
| "sequenceNumber"
|
|
288
|
-
| "clientSequenceNumber"
|
|
289
|
-
| "referenceSequenceNumber"
|
|
290
|
-
| "minimumSequenceNumber"
|
|
291
|
-
| "timestamp"
|
|
292
|
-
>
|
|
293
|
-
>,
|
|
363
|
+
messageLike: MessageLike,
|
|
294
364
|
): {
|
|
295
365
|
messageClientId: string | undefined;
|
|
296
366
|
messageSequenceNumber: number | undefined;
|
package/src/index.ts
CHANGED
package/biome.jsonc
DELETED