@fluidframework/telemetry-utils 1.4.0-115997 → 2.0.0-dev-rc.1.0.0.224419

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