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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.eslintrc.js +11 -13
  2. package/.mocharc.js +2 -2
  3. package/api-extractor.json +2 -2
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +3 -3
  6. package/dist/config.js.map +1 -1
  7. package/dist/debugLogger.d.ts.map +1 -1
  8. package/dist/debugLogger.js.map +1 -1
  9. package/dist/errorLogging.d.ts +5 -5
  10. package/dist/errorLogging.d.ts.map +1 -1
  11. package/dist/errorLogging.js +20 -18
  12. package/dist/errorLogging.js.map +1 -1
  13. package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
  14. package/dist/eventEmitterWithErrorHandling.js.map +1 -1
  15. package/dist/events.d.ts.map +1 -1
  16. package/dist/events.js.map +1 -1
  17. package/dist/fluidErrorBase.d.ts.map +1 -1
  18. package/dist/fluidErrorBase.js +4 -4
  19. package/dist/fluidErrorBase.js.map +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/logger.d.ts.map +1 -1
  24. package/dist/logger.js +13 -12
  25. package/dist/logger.js.map +1 -1
  26. package/dist/mockLogger.d.ts +5 -5
  27. package/dist/mockLogger.d.ts.map +1 -1
  28. package/dist/mockLogger.js +5 -5
  29. package/dist/mockLogger.js.map +1 -1
  30. package/dist/packageVersion.d.ts +1 -1
  31. package/dist/packageVersion.js +1 -1
  32. package/dist/packageVersion.js.map +1 -1
  33. package/dist/sampledTelemetryHelper.d.ts.map +1 -1
  34. package/dist/sampledTelemetryHelper.js.map +1 -1
  35. package/dist/telemetryTypes.d.ts.map +1 -1
  36. package/dist/telemetryTypes.js.map +1 -1
  37. package/dist/thresholdCounter.d.ts.map +1 -1
  38. package/dist/thresholdCounter.js.map +1 -1
  39. package/dist/utils.d.ts.map +1 -1
  40. package/dist/utils.js.map +1 -1
  41. package/lib/config.d.ts.map +1 -1
  42. package/lib/config.js +3 -3
  43. package/lib/config.js.map +1 -1
  44. package/lib/debugLogger.d.ts.map +1 -1
  45. package/lib/debugLogger.js +1 -1
  46. package/lib/debugLogger.js.map +1 -1
  47. package/lib/errorLogging.d.ts +5 -5
  48. package/lib/errorLogging.d.ts.map +1 -1
  49. package/lib/errorLogging.js +20 -18
  50. package/lib/errorLogging.js.map +1 -1
  51. package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
  52. package/lib/eventEmitterWithErrorHandling.js.map +1 -1
  53. package/lib/events.d.ts.map +1 -1
  54. package/lib/events.js.map +1 -1
  55. package/lib/fluidErrorBase.d.ts.map +1 -1
  56. package/lib/fluidErrorBase.js +4 -4
  57. package/lib/fluidErrorBase.js.map +1 -1
  58. package/lib/index.d.ts +2 -2
  59. package/lib/index.d.ts.map +1 -1
  60. package/lib/index.js +2 -2
  61. package/lib/index.js.map +1 -1
  62. package/lib/logger.d.ts.map +1 -1
  63. package/lib/logger.js +14 -13
  64. package/lib/logger.js.map +1 -1
  65. package/lib/mockLogger.d.ts +5 -5
  66. package/lib/mockLogger.d.ts.map +1 -1
  67. package/lib/mockLogger.js +5 -5
  68. package/lib/mockLogger.js.map +1 -1
  69. package/lib/packageVersion.d.ts +1 -1
  70. package/lib/packageVersion.js +1 -1
  71. package/lib/packageVersion.js.map +1 -1
  72. package/lib/sampledTelemetryHelper.d.ts.map +1 -1
  73. package/lib/sampledTelemetryHelper.js.map +1 -1
  74. package/lib/telemetryTypes.d.ts.map +1 -1
  75. package/lib/telemetryTypes.js.map +1 -1
  76. package/lib/thresholdCounter.d.ts.map +1 -1
  77. package/lib/thresholdCounter.js.map +1 -1
  78. package/lib/utils.d.ts.map +1 -1
  79. package/lib/utils.js.map +1 -1
  80. package/package.json +107 -110
  81. package/prettier.config.cjs +1 -1
  82. package/src/config.ts +173 -172
  83. package/src/debugLogger.ts +118 -111
  84. package/src/errorLogging.ts +302 -299
  85. package/src/eventEmitterWithErrorHandling.ts +16 -12
  86. package/src/events.ts +26 -26
  87. package/src/fluidErrorBase.ts +42 -38
  88. package/src/index.ts +26 -16
  89. package/src/logger.ts +541 -533
  90. package/src/mockLogger.ts +113 -107
  91. package/src/packageVersion.ts +1 -1
  92. package/src/sampledTelemetryHelper.ts +122 -122
  93. package/src/telemetryTypes.ts +37 -37
  94. package/src/thresholdCounter.ts +34 -34
  95. package/src/utils.ts +15 -15
  96. package/tsconfig.esnext.json +6 -6
  97. package/tsconfig.json +9 -13
package/src/config.ts CHANGED
@@ -11,30 +11,31 @@ export type ConfigTypes = string | number | boolean | number[] | string[] | bool
11
11
  * Base interface for providing configurations to enable/disable/control features
12
12
  */
13
13
  export interface IConfigProviderBase {
14
- getRawConfig(name: string): ConfigTypes;
14
+ getRawConfig(name: string): ConfigTypes;
15
15
  }
16
16
 
17
17
  /**
18
18
  * Explicitly typed interface for reading configurations
19
19
  */
20
- export interface IConfigProvider extends IConfigProviderBase {
21
- getBoolean(name: string): boolean | undefined;
22
- getNumber(name: string): number | undefined;
23
- getString(name: string): string | undefined;
24
- getBooleanArray(name: string): boolean[] | undefined;
25
- getNumberArray(name: string): number[] | undefined;
26
- getStringArray(name: string): string[] | undefined;
27
- }
20
+ export interface IConfigProvider extends IConfigProviderBase {
21
+ getBoolean(name: string): boolean | undefined;
22
+ getNumber(name: string): number | undefined;
23
+ getString(name: string): string | undefined;
24
+ getBooleanArray(name: string): boolean[] | undefined;
25
+ getNumberArray(name: string): number[] | undefined;
26
+ getStringArray(name: string): string[] | undefined;
27
+ }
28
28
  /**
29
29
  * Creates a base configuration provider based on `sessionStorage`
30
30
  *
31
31
  * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store
32
32
  */
33
- export const sessionStorageConfigProvider =
34
- new Lazy<IConfigProviderBase>(() => inMemoryConfigProvider(safeSessionStorage()));
33
+ export const sessionStorageConfigProvider = new Lazy<IConfigProviderBase>(() =>
34
+ inMemoryConfigProvider(safeSessionStorage()),
35
+ );
35
36
 
36
37
  const NullConfigProvider: IConfigProviderBase = {
37
- getRawConfig: () => undefined,
38
+ getRawConfig: () => undefined,
38
39
  };
39
40
 
40
41
  /**
@@ -44,45 +45,44 @@ const NullConfigProvider: IConfigProviderBase = {
44
45
  * @returns A base configuration provider with
45
46
  * the supplied `Storage` instance as the underlying config store
46
47
  */
47
- export const inMemoryConfigProvider =
48
- (storage: Storage | undefined): IConfigProviderBase => {
49
- if (storage !== undefined && storage !== null) {
50
- return new CachedConfigProvider({
51
- getRawConfig: (name: string) => {
52
- try {
53
- return stronglyTypedParse(storage.getItem(name) ?? undefined)?.raw;
54
- } catch { }
55
- return undefined;
56
- },
57
- });
58
- }
59
- return NullConfigProvider;
48
+ export const inMemoryConfigProvider = (storage: Storage | undefined): IConfigProviderBase => {
49
+ if (storage !== undefined && storage !== null) {
50
+ return new CachedConfigProvider({
51
+ getRawConfig: (name: string) => {
52
+ try {
53
+ return stronglyTypedParse(storage.getItem(name) ?? undefined)?.raw;
54
+ } catch {}
55
+ return undefined;
56
+ },
57
+ });
58
+ }
59
+ return NullConfigProvider;
60
60
  };
61
61
 
62
62
  interface ConfigTypeStringToType {
63
- number: number;
64
- string: string;
65
- boolean: boolean;
66
- ["number[]"]: number[];
67
- ["string[]"]: string[];
68
- ["boolean[]"]: boolean[];
63
+ number: number;
64
+ string: string;
65
+ boolean: boolean;
66
+ ["number[]"]: number[];
67
+ ["string[]"]: string[];
68
+ ["boolean[]"]: boolean[];
69
69
  }
70
70
 
71
71
  type PrimitiveTypeStrings = "number" | "string" | "boolean";
72
72
 
73
73
  function isPrimitiveType(type: string): type is PrimitiveTypeStrings {
74
- switch (type) {
75
- case "boolean":
76
- case "number":
77
- case "string":
78
- return true;
79
- default:
80
- return false;
81
- }
74
+ switch (type) {
75
+ case "boolean":
76
+ case "number":
77
+ case "string":
78
+ return true;
79
+ default:
80
+ return false;
81
+ }
82
82
  }
83
83
 
84
84
  interface StronglyTypedValue extends Partial<ConfigTypeStringToType> {
85
- raw: ConfigTypes;
85
+ raw: ConfigTypes;
86
86
  }
87
87
  /**
88
88
  * Takes any supported config type, and returns the value with a strong type. If the type of
@@ -94,170 +94,171 @@ interface StronglyTypedValue extends Partial<ConfigTypeStringToType> {
94
94
  * will be return with a string type for the consumer to handle further if necessary.
95
95
  */
96
96
  function stronglyTypedParse(input: ConfigTypes): StronglyTypedValue | undefined {
97
- let output: ConfigTypes = input;
98
- let defaultReturn: Pick<StronglyTypedValue, "raw" | "string"> | undefined;
99
- // we do special handling for strings to try and coerce
100
- // them into a config type if we can. This makes it easy
101
- // for config sources like sessionStorage which only
102
- // holds strings
103
- if (typeof input === "string") {
104
- try {
105
- output = JSON.parse(input);
106
- // we succeeded in parsing, but we don't support parsing
107
- // for any object as we can't do it type safely
108
- // so in this case, the default return will be string
109
- // rather than undefined, and the consumer
110
- // can parse, as we don't want to provide
111
- // a false sense of security by just
112
- // casting.
113
- defaultReturn = { raw: input, string: input };
114
- } catch { }
115
- }
97
+ let output: ConfigTypes = input;
98
+ let defaultReturn: Pick<StronglyTypedValue, "raw" | "string"> | undefined;
99
+ // we do special handling for strings to try and coerce
100
+ // them into a config type if we can. This makes it easy
101
+ // for config sources like sessionStorage which only
102
+ // holds strings
103
+ if (typeof input === "string") {
104
+ try {
105
+ output = JSON.parse(input);
106
+ // we succeeded in parsing, but we don't support parsing
107
+ // for any object as we can't do it type safely
108
+ // so in this case, the default return will be string
109
+ // rather than undefined, and the consumer
110
+ // can parse, as we don't want to provide
111
+ // a false sense of security by just
112
+ // casting.
113
+ defaultReturn = { raw: input, string: input };
114
+ } catch {}
115
+ }
116
116
 
117
- if (output === undefined) {
118
- return defaultReturn;
119
- }
117
+ if (output === undefined) {
118
+ return defaultReturn;
119
+ }
120
120
 
121
- const outputType = typeof output;
122
- if (isPrimitiveType(outputType)) {
123
- return { ...defaultReturn, raw: input, [outputType]: output };
124
- }
121
+ const outputType = typeof output;
122
+ if (isPrimitiveType(outputType)) {
123
+ return { ...defaultReturn, raw: input, [outputType]: output };
124
+ }
125
125
 
126
- if (Array.isArray(output)) {
127
- const firstType = typeof output[0];
128
- // ensure the first elements is a primitive type
129
- if (!isPrimitiveType(firstType)) {
130
- return defaultReturn;
131
- }
132
- // ensue all the elements types are homogeneous
133
- // aka they all have the same type as the first
134
- for (const v of output) {
135
- if (typeof v !== firstType) {
136
- return defaultReturn;
137
- }
138
- }
139
- return { ...defaultReturn, raw: input, [`${firstType}[]`]: output };
140
- }
126
+ if (Array.isArray(output)) {
127
+ const firstType = typeof output[0];
128
+ // ensure the first elements is a primitive type
129
+ if (!isPrimitiveType(firstType)) {
130
+ return defaultReturn;
131
+ }
132
+ // ensue all the elements types are homogeneous
133
+ // aka they all have the same type as the first
134
+ for (const v of output) {
135
+ if (typeof v !== firstType) {
136
+ return defaultReturn;
137
+ }
138
+ }
139
+ return { ...defaultReturn, raw: input, [`${firstType}[]`]: output };
140
+ }
141
141
 
142
- return defaultReturn;
142
+ return defaultReturn;
143
143
  }
144
144
 
145
145
  /** `sessionStorage` is undefined in some environments such as Node */
146
146
  const safeSessionStorage = (): Storage | undefined => {
147
- return globalThis.sessionStorage;
147
+ return globalThis.sessionStorage;
148
148
  };
149
149
 
150
150
  /**
151
151
  * Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances
152
152
  */
153
153
  export class CachedConfigProvider implements IConfigProvider {
154
- private readonly configCache = new Map<string, StronglyTypedValue>();
155
- private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
154
+ private readonly configCache = new Map<string, StronglyTypedValue>();
155
+ private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
156
156
 
157
- constructor(
158
- ... orderedBaseProviders: (IConfigProviderBase | undefined)[]
159
- ) {
160
- this.orderedBaseProviders = [];
161
- const knownProviders = new Set<IConfigProviderBase>();
162
- const candidateProviders = [...orderedBaseProviders];
163
- while (candidateProviders.length > 0) {
164
- const baseProvider = candidateProviders.shift()!;
165
- if (baseProvider !== undefined
166
- && isConfigProviderBase(baseProvider)
167
- && !knownProviders.has(baseProvider)
168
- ) {
169
- knownProviders.add(baseProvider);
170
- if (baseProvider instanceof CachedConfigProvider) {
171
- candidateProviders.push(...baseProvider.orderedBaseProviders);
172
- } else {
173
- this.orderedBaseProviders.push(baseProvider);
174
- }
175
- }
176
- }
177
- }
178
- getBoolean(name: string): boolean | undefined {
179
- return this.getCacheEntry(name)?.boolean;
180
- }
181
- getNumber(name: string): number | undefined {
182
- return this.getCacheEntry(name)?.number;
183
- }
184
- getString(name: string): string | undefined {
185
- return this.getCacheEntry(name)?.string;
186
- }
187
- getBooleanArray(name: string): boolean[] | undefined {
188
- return this.getCacheEntry(name)?.["boolean[]"];
189
- }
190
- getNumberArray(name: string): number[] | undefined {
191
- return this.getCacheEntry(name)?.["number[]"];
192
- }
193
- getStringArray(name: string): string[] | undefined {
194
- return this.getCacheEntry(name)?.["string[]"];
195
- }
157
+ constructor(...orderedBaseProviders: (IConfigProviderBase | undefined)[]) {
158
+ this.orderedBaseProviders = [];
159
+ const knownProviders = new Set<IConfigProviderBase>();
160
+ const candidateProviders = [...orderedBaseProviders];
161
+ while (candidateProviders.length > 0) {
162
+ const baseProvider = candidateProviders.shift()!;
163
+ if (
164
+ baseProvider !== undefined &&
165
+ isConfigProviderBase(baseProvider) &&
166
+ !knownProviders.has(baseProvider)
167
+ ) {
168
+ knownProviders.add(baseProvider);
169
+ if (baseProvider instanceof CachedConfigProvider) {
170
+ candidateProviders.push(...baseProvider.orderedBaseProviders);
171
+ } else {
172
+ this.orderedBaseProviders.push(baseProvider);
173
+ }
174
+ }
175
+ }
176
+ }
177
+ getBoolean(name: string): boolean | undefined {
178
+ return this.getCacheEntry(name)?.boolean;
179
+ }
180
+ getNumber(name: string): number | undefined {
181
+ return this.getCacheEntry(name)?.number;
182
+ }
183
+ getString(name: string): string | undefined {
184
+ return this.getCacheEntry(name)?.string;
185
+ }
186
+ getBooleanArray(name: string): boolean[] | undefined {
187
+ return this.getCacheEntry(name)?.["boolean[]"];
188
+ }
189
+ getNumberArray(name: string): number[] | undefined {
190
+ return this.getCacheEntry(name)?.["number[]"];
191
+ }
192
+ getStringArray(name: string): string[] | undefined {
193
+ return this.getCacheEntry(name)?.["string[]"];
194
+ }
196
195
 
197
- getRawConfig(name: string): ConfigTypes {
198
- return this.getCacheEntry(name)?.raw;
199
- }
196
+ getRawConfig(name: string): ConfigTypes {
197
+ return this.getCacheEntry(name)?.raw;
198
+ }
200
199
 
201
- private getCacheEntry(name: string): StronglyTypedValue | undefined {
202
- if (!this.configCache.has(name)) {
203
- for (const provider of this.orderedBaseProviders) {
204
- const parsed = stronglyTypedParse(provider?.getRawConfig(name));
205
- if (parsed !== undefined) {
206
- this.configCache.set(name, parsed);
207
- return parsed;
208
- }
209
- }
210
- // configs are immutable, if the first lookup returned no results, all lookups should
211
- this.configCache.set(name, { raw: undefined });
212
- }
213
- return this.configCache.get(name);
214
- }
200
+ private getCacheEntry(name: string): StronglyTypedValue | undefined {
201
+ if (!this.configCache.has(name)) {
202
+ for (const provider of this.orderedBaseProviders) {
203
+ const parsed = stronglyTypedParse(provider?.getRawConfig(name));
204
+ if (parsed !== undefined) {
205
+ this.configCache.set(name, parsed);
206
+ return parsed;
207
+ }
208
+ }
209
+ // configs are immutable, if the first lookup returned no results, all lookups should
210
+ this.configCache.set(name, { raw: undefined });
211
+ }
212
+ return this.configCache.get(name);
213
+ }
215
214
  }
216
215
 
217
216
  /**
218
217
  * A type containing both a telemetry logger and a configuration provider
219
218
  */
220
- export interface MonitoringContext<
221
- L extends ITelemetryBaseLogger = ITelemetryLogger,
222
- > {
223
- config: IConfigProvider;
224
- logger: L;
219
+ export interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger> {
220
+ config: IConfigProvider;
221
+ logger: L;
225
222
  }
226
223
 
227
224
  export function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(
228
- obj: L): obj is L & MonitoringContext<L> {
229
- const maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;
230
- return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;
225
+ obj: L,
226
+ ): obj is L & MonitoringContext<L> {
227
+ const maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;
228
+ return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;
231
229
  }
232
230
 
233
231
  export function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(
234
- logger: L): MonitoringContext<L> {
235
- if (loggerIsMonitoringContext<L>(logger)) {
236
- return logger;
237
- }
238
- return mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);
232
+ logger: L,
233
+ ): MonitoringContext<L> {
234
+ if (loggerIsMonitoringContext<L>(logger)) {
235
+ return logger;
236
+ }
237
+ return mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);
239
238
  }
240
239
 
241
240
  export function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(
242
- logger: L, ... configs: (IConfigProviderBase | undefined)[]) {
243
- if (loggerIsMonitoringContext<L>(logger)) {
244
- throw new Error("Logger is already a monitoring context");
245
- }
246
- /**
247
- * this is the tricky bit we use for now to smuggle monitoring context around.
248
- * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.
249
- * We then expose it as a Monitoring context, so via types we hide the outer logger methods.
250
- * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext
251
- * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties
252
- * of the MonitoringContext and get the config provider.
253
- */
254
- const mc: L & Partial<MonitoringContext<L>> = logger;
255
- mc.config = new CachedConfigProvider(...configs);
256
- mc.logger = logger;
257
- return mc as MonitoringContext<L>;
241
+ logger: L,
242
+ ...configs: (IConfigProviderBase | undefined)[]
243
+ ) {
244
+ if (loggerIsMonitoringContext<L>(logger)) {
245
+ throw new Error("Logger is already a monitoring context");
246
+ }
247
+ /**
248
+ * this is the tricky bit we use for now to smuggle monitoring context around.
249
+ * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.
250
+ * We then expose it as a Monitoring context, so via types we hide the outer logger methods.
251
+ * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext
252
+ * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties
253
+ * of the MonitoringContext and get the config provider.
254
+ */
255
+ const mc: L & Partial<MonitoringContext<L>> = logger;
256
+ mc.config = new CachedConfigProvider(...configs);
257
+ mc.logger = logger;
258
+ return mc as MonitoringContext<L>;
258
259
  }
259
260
 
260
261
  function isConfigProviderBase(obj: unknown): obj is IConfigProviderBase {
261
- const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;
262
- return typeof (maybeConfig?.getRawConfig) === "function";
262
+ const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;
263
+ return typeof maybeConfig?.getRawConfig === "function";
263
264
  }