@fluidframework/telemetry-utils 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.224419
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +12 -13
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +249 -0
- package/README.md +68 -1
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/telemetry-utils.api.md +444 -0
- package/dist/config.d.ts +47 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +88 -38
- package/dist/config.js.map +1 -1
- package/dist/error.d.ts +112 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +159 -0
- package/dist/error.js.map +1 -0
- package/dist/errorLogging.d.ts +86 -20
- package/dist/errorLogging.d.ts.map +1 -1
- package/dist/errorLogging.js +190 -60
- package/dist/errorLogging.js.map +1 -1
- package/dist/eventEmitterWithErrorHandling.d.ts +9 -3
- package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
- package/dist/eventEmitterWithErrorHandling.js +16 -3
- package/dist/eventEmitterWithErrorHandling.js.map +1 -1
- package/dist/events.d.ts +27 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +26 -2
- package/dist/events.js.map +1 -1
- package/dist/fluidErrorBase.d.ts +57 -16
- package/dist/fluidErrorBase.d.ts.map +1 -1
- package/dist/fluidErrorBase.js +27 -14
- package/dist/fluidErrorBase.js.map +1 -1
- package/dist/index.d.ts +12 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -21
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +267 -51
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +423 -132
- package/dist/logger.js.map +1 -1
- package/dist/mockLogger.d.ts +39 -12
- package/dist/mockLogger.d.ts.map +1 -1
- package/dist/mockLogger.js +105 -22
- package/dist/mockLogger.js.map +1 -1
- package/dist/sampledTelemetryHelper.d.ts +18 -12
- package/dist/sampledTelemetryHelper.d.ts.map +1 -1
- package/dist/sampledTelemetryHelper.js +28 -19
- package/dist/sampledTelemetryHelper.js.map +1 -1
- package/dist/telemetry-utils-alpha.d.ts +290 -0
- package/dist/telemetry-utils-beta.d.ts +264 -0
- package/dist/telemetry-utils-public.d.ts +264 -0
- package/dist/telemetry-utils-untrimmed.d.ts +1102 -0
- package/dist/telemetryTypes.d.ts +115 -0
- package/dist/telemetryTypes.d.ts.map +1 -0
- package/dist/telemetryTypes.js +7 -0
- package/dist/telemetryTypes.js.map +1 -0
- package/dist/thresholdCounter.d.ts +6 -5
- package/dist/thresholdCounter.d.ts.map +1 -1
- package/dist/thresholdCounter.js +4 -3
- package/dist/thresholdCounter.js.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/utils.d.ts +54 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +58 -3
- package/dist/utils.js.map +1 -1
- package/lib/config.d.ts +47 -16
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +85 -36
- package/lib/config.js.map +1 -1
- package/lib/error.d.ts +112 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +150 -0
- package/lib/error.js.map +1 -0
- package/lib/errorLogging.d.ts +86 -20
- package/lib/errorLogging.d.ts.map +1 -1
- package/lib/errorLogging.js +189 -60
- package/lib/errorLogging.js.map +1 -1
- package/lib/eventEmitterWithErrorHandling.d.ts +9 -3
- package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
- package/lib/eventEmitterWithErrorHandling.js +15 -2
- package/lib/eventEmitterWithErrorHandling.js.map +1 -1
- package/lib/events.d.ts +27 -3
- package/lib/events.d.ts.map +1 -1
- package/lib/events.js +26 -2
- package/lib/events.js.map +1 -1
- package/lib/fluidErrorBase.d.ts +57 -16
- package/lib/fluidErrorBase.d.ts.map +1 -1
- package/lib/fluidErrorBase.js +27 -14
- package/lib/fluidErrorBase.js.map +1 -1
- package/lib/index.d.ts +12 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +11 -11
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +267 -51
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +415 -131
- package/lib/logger.js.map +1 -1
- package/lib/mockLogger.d.ts +39 -12
- package/lib/mockLogger.d.ts.map +1 -1
- package/lib/mockLogger.js +106 -23
- package/lib/mockLogger.js.map +1 -1
- package/lib/sampledTelemetryHelper.d.ts +18 -12
- package/lib/sampledTelemetryHelper.d.ts.map +1 -1
- package/lib/sampledTelemetryHelper.js +26 -17
- package/lib/sampledTelemetryHelper.js.map +1 -1
- package/lib/telemetry-utils-alpha.d.ts +290 -0
- package/lib/telemetry-utils-beta.d.ts +264 -0
- package/lib/telemetry-utils-public.d.ts +264 -0
- package/lib/telemetry-utils-untrimmed.d.ts +1102 -0
- package/lib/telemetryTypes.d.ts +115 -0
- package/lib/telemetryTypes.d.ts.map +1 -0
- package/lib/telemetryTypes.js +6 -0
- package/lib/telemetryTypes.js.map +1 -0
- package/lib/thresholdCounter.d.ts +6 -5
- package/lib/thresholdCounter.d.ts.map +1 -1
- package/lib/thresholdCounter.js +4 -3
- package/lib/thresholdCounter.js.map +1 -1
- package/lib/utils.d.ts +54 -3
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +56 -2
- package/lib/utils.js.map +1 -1
- package/package.json +86 -57
- package/prettier.config.cjs +8 -0
- package/src/config.ts +254 -189
- package/src/error.ts +235 -0
- package/src/errorLogging.ts +440 -290
- package/src/eventEmitterWithErrorHandling.ts +26 -14
- package/src/events.ts +54 -25
- package/src/fluidErrorBase.ts +94 -46
- package/src/index.ts +76 -17
- package/src/logger.ts +966 -505
- package/src/mockLogger.ts +225 -83
- package/src/sampledTelemetryHelper.ts +136 -128
- package/src/telemetryTypes.ts +140 -0
- package/src/thresholdCounter.ts +38 -37
- package/src/utils.ts +108 -17
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/debugLogger.d.ts +0 -39
- package/dist/debugLogger.d.ts.map +0 -1
- package/dist/debugLogger.js +0 -101
- package/dist/debugLogger.js.map +0 -1
- package/dist/packageVersion.d.ts +0 -9
- package/dist/packageVersion.d.ts.map +0 -1
- package/dist/packageVersion.js +0 -12
- package/dist/packageVersion.js.map +0 -1
- package/lib/debugLogger.d.ts +0 -39
- package/lib/debugLogger.d.ts.map +0 -1
- package/lib/debugLogger.js +0 -97
- package/lib/debugLogger.js.map +0 -1
- package/lib/packageVersion.d.ts +0 -9
- package/lib/packageVersion.d.ts.map +0 -1
- package/lib/packageVersion.js +0 -9
- package/lib/packageVersion.js.map +0 -1
- package/src/debugLogger.ts +0 -126
- package/src/packageVersion.ts +0 -9
package/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 {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
*
|
|
15
|
+
* Explicitly typed interface for reading configurations.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
12
18
|
*/
|
|
13
|
-
export interface IConfigProviderBase {
|
|
14
|
-
|
|
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
|
-
|
|
34
|
+
export const sessionStorageConfigProvider = new Lazy<IConfigProviderBase>(() =>
|
|
35
|
+
inMemoryConfigProvider(safeSessionStorage()),
|
|
36
|
+
);
|
|
35
37
|
|
|
36
38
|
const NullConfigProvider: IConfigProviderBase = {
|
|
37
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
if (output === undefined) {
|
|
124
|
+
return defaultReturn;
|
|
125
|
+
}
|
|
120
126
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
const outputType = typeof output;
|
|
128
|
+
if (isPrimitiveType(outputType)) {
|
|
129
|
+
return { ...defaultReturn, raw: input, [outputType]: output };
|
|
130
|
+
}
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
148
|
+
return defaultReturn;
|
|
143
149
|
}
|
|
144
150
|
|
|
145
|
-
/**
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
157
|
-
|
|
173
|
+
private readonly configCache = new Map<string, StronglyTypedValue>();
|
|
174
|
+
private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
|
|
158
175
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
218
|
+
getRawConfig(name: string): ConfigTypes {
|
|
219
|
+
return this.getCacheEntry(name)?.raw;
|
|
220
|
+
}
|
|
202
221
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
-
|
|
264
|
-
|
|
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
|
}
|