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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
package/src/config.ts CHANGED
@@ -2,39 +2,41 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ITelemetryBaseLogger, ITelemetryLogger } from "@fluidframework/common-definitions";
6
- import { Lazy } from "@fluidframework/common-utils";
7
-
8
- export type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;
5
+ import {
6
+ ITelemetryBaseLogger,
7
+ IConfigProviderBase,
8
+ ConfigTypes,
9
+ } from "@fluidframework/core-interfaces";
10
+ import { Lazy } from "@fluidframework/core-utils";
11
+ import { createChildLogger, tagCodeArtifacts } from "./logger";
12
+ import { ITelemetryLoggerExt } from "./telemetryTypes";
9
13
 
10
14
  /**
11
- * Base interface for providing configurations to enable/disable/control features
15
+ * Explicitly typed interface for reading configurations.
16
+ *
17
+ * @internal
12
18
  */
13
- export interface IConfigProviderBase {
14
- getRawConfig(name: string): ConfigTypes;
19
+ export interface IConfigProvider extends IConfigProviderBase {
20
+ getBoolean(name: string): boolean | undefined;
21
+ getNumber(name: string): number | undefined;
22
+ getString(name: string): string | undefined;
23
+ getBooleanArray(name: string): boolean[] | undefined;
24
+ getNumberArray(name: string): number[] | undefined;
25
+ getStringArray(name: string): string[] | undefined;
15
26
  }
16
-
17
- /**
18
- * Explicitly typed interface for reading configurations
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
- }
28
27
  /**
29
28
  * Creates a base configuration provider based on `sessionStorage`
30
29
  *
31
30
  * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store
31
+ *
32
+ * @internal
32
33
  */
33
- export const sessionStorageConfigProvider =
34
- new Lazy<IConfigProviderBase>(() => inMemoryConfigProvider(safeSessionStorage()));
34
+ export const sessionStorageConfigProvider = new Lazy<IConfigProviderBase>(() =>
35
+ inMemoryConfigProvider(safeSessionStorage()),
36
+ );
35
37
 
36
38
  const NullConfigProvider: IConfigProviderBase = {
37
- getRawConfig: () => undefined,
39
+ getRawConfig: () => undefined,
38
40
  };
39
41
 
40
42
  /**
@@ -44,45 +46,47 @@ const NullConfigProvider: IConfigProviderBase = {
44
46
  * @returns A base configuration provider with
45
47
  * the supplied `Storage` instance as the underlying config store
46
48
  */
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;
49
+ export const inMemoryConfigProvider = (storage: Storage | undefined): IConfigProviderBase => {
50
+ if (storage !== undefined && storage !== null) {
51
+ return new CachedConfigProvider(undefined, {
52
+ getRawConfig: (name: string): ConfigTypes | undefined => {
53
+ try {
54
+ return stronglyTypedParse(storage.getItem(name) ?? undefined)?.raw;
55
+ } catch {
56
+ return undefined;
57
+ }
58
+ },
59
+ });
60
+ }
61
+ return NullConfigProvider;
60
62
  };
61
63
 
62
64
  interface ConfigTypeStringToType {
63
- number: number;
64
- string: string;
65
- boolean: boolean;
66
- ["number[]"]: number[];
67
- ["string[]"]: string[];
68
- ["boolean[]"]: boolean[];
65
+ number: number;
66
+ string: string;
67
+ boolean: boolean;
68
+ ["number[]"]: number[];
69
+ ["string[]"]: string[];
70
+ ["boolean[]"]: boolean[];
69
71
  }
70
72
 
71
73
  type PrimitiveTypeStrings = "number" | "string" | "boolean";
72
74
 
73
75
  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
- }
76
+ switch (type) {
77
+ case "boolean":
78
+ case "number":
79
+ case "string": {
80
+ return true;
81
+ }
82
+ default: {
83
+ return false;
84
+ }
85
+ }
82
86
  }
83
87
 
84
88
  interface StronglyTypedValue extends Partial<ConfigTypeStringToType> {
85
- raw: ConfigTypes;
89
+ raw: ConfigTypes;
86
90
  }
87
91
  /**
88
92
  * Takes any supported config type, and returns the value with a strong type. If the type of
@@ -94,172 +98,233 @@ interface StronglyTypedValue extends Partial<ConfigTypeStringToType> {
94
98
  * will be return with a string type for the consumer to handle further if necessary.
95
99
  */
96
100
  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
- }
101
+ let output: ConfigTypes = input;
102
+ let defaultReturn: Pick<StronglyTypedValue, "raw" | "string"> | undefined;
103
+ // we do special handling for strings to try and coerce
104
+ // them into a config type if we can. This makes it easy
105
+ // for config sources like sessionStorage which only
106
+ // holds strings
107
+ if (typeof input === "string") {
108
+ try {
109
+ output = JSON.parse(input) as ConfigTypes;
110
+ // we succeeded in parsing, but we don't support parsing
111
+ // for any object as we can't do it type safely
112
+ // so in this case, the default return will be string
113
+ // rather than undefined, and the consumer
114
+ // can parse, as we don't want to provide
115
+ // a false sense of security by just
116
+ // casting.
117
+ defaultReturn = { raw: input, string: input };
118
+ } catch {
119
+ // No-op
120
+ }
121
+ }
116
122
 
117
- if (output === undefined) {
118
- return defaultReturn;
119
- }
123
+ if (output === undefined) {
124
+ return defaultReturn;
125
+ }
120
126
 
121
- const outputType = typeof output;
122
- if (isPrimitiveType(outputType)) {
123
- return { ...defaultReturn, raw: input, [outputType]: output };
124
- }
127
+ const outputType = typeof output;
128
+ if (isPrimitiveType(outputType)) {
129
+ return { ...defaultReturn, raw: input, [outputType]: output };
130
+ }
125
131
 
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
- }
132
+ if (Array.isArray(output)) {
133
+ const firstType = typeof output[0];
134
+ // ensure the first elements is a primitive type
135
+ if (!isPrimitiveType(firstType)) {
136
+ return defaultReturn;
137
+ }
138
+ // ensue all the elements types are homogeneous
139
+ // aka they all have the same type as the first
140
+ for (const v of output) {
141
+ if (typeof v !== firstType) {
142
+ return defaultReturn;
143
+ }
144
+ }
145
+ return { ...defaultReturn, raw: input, [`${firstType}[]`]: output };
146
+ }
141
147
 
142
- return defaultReturn;
148
+ return defaultReturn;
143
149
  }
144
150
 
145
- /** Referencing the `sessionStorage` variable can throw in some environments such as Node */
151
+ /**
152
+ * `sessionStorage` is undefined in some environments such as Node and web pages with session storage disabled.
153
+ */
146
154
  const safeSessionStorage = (): Storage | undefined => {
147
- try {
148
- return sessionStorage !== null ? sessionStorage : undefined;
149
- } catch { return undefined; }
155
+ // For some configurations accessing "globalThis.sessionStorage" throws
156
+ // "'sessionStorage' property from 'Window': Access is denied for this document" rather than returning undefined.
157
+ // Therefor check for it before accessing.
158
+ try {
159
+ // Using globalThis and checking for undefined is preferred over just accessing global sessionStorage
160
+ // since it avoids an exception when running in node.
161
+ // In some cases this has returned null when disabled in the browser, so ensure its undefined in that case:
162
+ return globalThis.sessionStorage ?? undefined;
163
+ } catch {
164
+ // For browsers which error on the above when session storage is disabled:
165
+ return undefined;
166
+ }
150
167
  };
151
168
 
152
169
  /**
153
170
  * Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances
154
171
  */
155
172
  export class CachedConfigProvider implements IConfigProvider {
156
- private readonly configCache = new Map<string, StronglyTypedValue>();
157
- private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
173
+ private readonly configCache = new Map<string, StronglyTypedValue>();
174
+ private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
158
175
 
159
- constructor(
160
- ... orderedBaseProviders: (IConfigProviderBase | undefined)[]
161
- ) {
162
- this.orderedBaseProviders = [];
163
- const knownProviders = new Set<IConfigProviderBase>();
164
- const candidateProviders = [...orderedBaseProviders];
165
- while (candidateProviders.length > 0) {
166
- const baseProvider = candidateProviders.shift()!;
167
- if (baseProvider !== undefined
168
- && isConfigProviderBase(baseProvider)
169
- && !knownProviders.has(baseProvider)
170
- ) {
171
- knownProviders.add(baseProvider);
172
- if (baseProvider instanceof CachedConfigProvider) {
173
- candidateProviders.push(...baseProvider.orderedBaseProviders);
174
- } else {
175
- this.orderedBaseProviders.push(baseProvider);
176
- }
177
- }
178
- }
179
- }
180
- getBoolean(name: string): boolean | undefined {
181
- return this.getCacheEntry(name)?.boolean;
182
- }
183
- getNumber(name: string): number | undefined {
184
- return this.getCacheEntry(name)?.number;
185
- }
186
- getString(name: string): string | undefined {
187
- return this.getCacheEntry(name)?.string;
188
- }
189
- getBooleanArray(name: string): boolean[] | undefined {
190
- return this.getCacheEntry(name)?.["boolean[]"];
191
- }
192
- getNumberArray(name: string): number[] | undefined {
193
- return this.getCacheEntry(name)?.["number[]"];
194
- }
195
- getStringArray(name: string): string[] | undefined {
196
- return this.getCacheEntry(name)?.["string[]"];
197
- }
176
+ constructor(
177
+ private readonly logger?: ITelemetryBaseLogger,
178
+ ...orderedBaseProviders: (IConfigProviderBase | undefined)[]
179
+ ) {
180
+ this.orderedBaseProviders = [];
181
+ const knownProviders = new Set<IConfigProviderBase>();
182
+ const candidateProviders = [...orderedBaseProviders];
183
+ while (candidateProviders.length > 0) {
184
+ const baseProvider = candidateProviders.shift()!;
185
+ if (
186
+ baseProvider !== undefined &&
187
+ isConfigProviderBase(baseProvider) &&
188
+ !knownProviders.has(baseProvider)
189
+ ) {
190
+ knownProviders.add(baseProvider);
191
+ if (baseProvider instanceof CachedConfigProvider) {
192
+ candidateProviders.push(...baseProvider.orderedBaseProviders);
193
+ } else {
194
+ this.orderedBaseProviders.push(baseProvider);
195
+ }
196
+ }
197
+ }
198
+ }
199
+ getBoolean(name: string): boolean | undefined {
200
+ return this.getCacheEntry(name)?.boolean;
201
+ }
202
+ getNumber(name: string): number | undefined {
203
+ return this.getCacheEntry(name)?.number;
204
+ }
205
+ getString(name: string): string | undefined {
206
+ return this.getCacheEntry(name)?.string;
207
+ }
208
+ getBooleanArray(name: string): boolean[] | undefined {
209
+ return this.getCacheEntry(name)?.["boolean[]"];
210
+ }
211
+ getNumberArray(name: string): number[] | undefined {
212
+ return this.getCacheEntry(name)?.["number[]"];
213
+ }
214
+ getStringArray(name: string): string[] | undefined {
215
+ return this.getCacheEntry(name)?.["string[]"];
216
+ }
198
217
 
199
- getRawConfig(name: string): ConfigTypes {
200
- return this.getCacheEntry(name)?.raw;
201
- }
218
+ getRawConfig(name: string): ConfigTypes {
219
+ return this.getCacheEntry(name)?.raw;
220
+ }
202
221
 
203
- private getCacheEntry(name: string): StronglyTypedValue | undefined {
204
- if (!this.configCache.has(name)) {
205
- for (const provider of this.orderedBaseProviders) {
206
- const parsed = stronglyTypedParse(provider?.getRawConfig(name));
207
- if (parsed !== undefined) {
208
- this.configCache.set(name, parsed);
209
- return parsed;
210
- }
211
- }
212
- // configs are immutable, if the first lookup returned no results, all lookups should
213
- this.configCache.set(name, { raw: undefined });
214
- }
215
- return this.configCache.get(name);
216
- }
222
+ private getCacheEntry(name: string): StronglyTypedValue | undefined {
223
+ if (!this.configCache.has(name)) {
224
+ for (const provider of this.orderedBaseProviders) {
225
+ const parsed = stronglyTypedParse(provider?.getRawConfig(name));
226
+ if (parsed !== undefined) {
227
+ this.configCache.set(name, parsed);
228
+ this.logger?.send({
229
+ category: "generic",
230
+ eventName: "ConfigRead",
231
+ ...tagCodeArtifacts({
232
+ configName: name,
233
+ configValue: JSON.stringify(parsed),
234
+ }),
235
+ });
236
+ return parsed;
237
+ }
238
+ }
239
+ // configs are immutable, if the first lookup returned no results, all lookups should
240
+ this.configCache.set(name, { raw: undefined });
241
+ }
242
+ return this.configCache.get(name);
243
+ }
217
244
  }
218
245
 
219
246
  /**
220
- * A type containing both a telemetry logger and a configuration provider
247
+ * A type containing both a telemetry logger and a configuration provider.
248
+ *
249
+ * @internal
221
250
  */
222
- export interface MonitoringContext<
223
- L extends ITelemetryBaseLogger = ITelemetryLogger,
224
- > {
225
- config: IConfigProvider;
226
- logger: L;
251
+ export interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt> {
252
+ config: IConfigProvider;
253
+ logger: L;
227
254
  }
228
255
 
229
- export function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(
230
- obj: L): obj is L & MonitoringContext<L> {
231
- const maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;
232
- return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;
256
+ /**
257
+ * Determines whether or not the provided object is a {@link MonitoringContext}.
258
+ * @remarks Can be used for type-narrowing.
259
+ *
260
+ * @internal
261
+ */
262
+ export function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(
263
+ obj: L,
264
+ ): obj is L & MonitoringContext<L> {
265
+ const maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;
266
+ return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;
233
267
  }
234
268
 
235
- export function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(
236
- logger: L): MonitoringContext<L> {
237
- if (loggerIsMonitoringContext<L>(logger)) {
238
- return logger;
239
- }
240
- return mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);
269
+ /**
270
+ * Creates a {@link MonitoringContext} from the provided logger, if it isn't already one.
271
+ *
272
+ * @internal
273
+ */
274
+ export function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(
275
+ logger: L,
276
+ ): MonitoringContext<L> {
277
+ if (loggerIsMonitoringContext<L>(logger)) {
278
+ return logger;
279
+ }
280
+ return mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);
241
281
  }
242
282
 
243
- export function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(
244
- logger: L, ... configs: (IConfigProviderBase | undefined)[]) {
245
- if (loggerIsMonitoringContext<L>(logger)) {
246
- throw new Error("Logger is already a monitoring context");
247
- }
248
- /**
249
- * this is the tricky bit we use for now to smuggle monitoring context around.
250
- * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.
251
- * We then expose it as a Monitoring context, so via types we hide the outer logger methods.
252
- * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext
253
- * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties
254
- * of the MonitoringContext and get the config provider.
255
- */
256
- const mc: L & Partial<MonitoringContext<L>> = logger;
257
- mc.config = new CachedConfigProvider(...configs);
258
- mc.logger = logger;
259
- return mc as MonitoringContext<L>;
283
+ /**
284
+ * Creates a {@link MonitoringContext} from the provided logger.
285
+ *
286
+ * @remarks
287
+ * Assumes that the provided logger is not itself already a {@link MonitoringContext}, and will throw an error if it is.
288
+ * If you are unsure, use {@link loggerToMonitoringContext} instead.
289
+ *
290
+ * @throws If the provided logger is already a {@link MonitoringContext}.
291
+ *
292
+ * @internal
293
+ */
294
+ export function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(
295
+ logger: L,
296
+ ...configs: (IConfigProviderBase | undefined)[]
297
+ ): MonitoringContext<L> {
298
+ if (loggerIsMonitoringContext<L>(logger)) {
299
+ throw new Error("Logger is already a monitoring context");
300
+ }
301
+ /**
302
+ * this is the tricky bit we use for now to smuggle monitoring context around.
303
+ * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.
304
+ * We then expose it as a Monitoring context, so via types we hide the outer logger methods.
305
+ * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext
306
+ * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties
307
+ * of the MonitoringContext and get the config provider.
308
+ */
309
+ const mc: L & Partial<MonitoringContext<L>> = logger;
310
+ mc.config = new CachedConfigProvider(logger, ...configs);
311
+ mc.logger = logger;
312
+ return mc as MonitoringContext<L>;
260
313
  }
261
314
 
262
315
  function isConfigProviderBase(obj: unknown): obj is IConfigProviderBase {
263
- const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;
264
- return typeof (maybeConfig?.getRawConfig) === "function";
316
+ const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;
317
+ return typeof maybeConfig?.getRawConfig === "function";
318
+ }
319
+
320
+ /**
321
+ * Creates a child logger with a {@link MonitoringContext}.
322
+ *
323
+ * @see {@link loggerToMonitoringContext}
324
+ * @internal
325
+ */
326
+ export function createChildMonitoringContext(
327
+ props: Parameters<typeof createChildLogger>[0],
328
+ ): MonitoringContext {
329
+ return loggerToMonitoringContext(createChildLogger(props));
265
330
  }