@fluidframework/telemetry-utils 2.0.0-dev.2.3.0.115467 → 2.0.0-dev.4.1.0.148229

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 (104) 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 +18 -5
  6. package/dist/config.js.map +1 -1
  7. package/dist/debugLogger.d.ts.map +1 -1
  8. package/dist/debugLogger.js +12 -1
  9. package/dist/debugLogger.js.map +1 -1
  10. package/dist/errorLogging.d.ts +8 -7
  11. package/dist/errorLogging.d.ts.map +1 -1
  12. package/dist/errorLogging.js +23 -20
  13. package/dist/errorLogging.js.map +1 -1
  14. package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
  15. package/dist/eventEmitterWithErrorHandling.js.map +1 -1
  16. package/dist/events.d.ts.map +1 -1
  17. package/dist/events.js.map +1 -1
  18. package/dist/fluidErrorBase.d.ts.map +1 -1
  19. package/dist/fluidErrorBase.js +4 -4
  20. package/dist/fluidErrorBase.js.map +1 -1
  21. package/dist/index.d.ts +3 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/logger.d.ts +15 -4
  25. package/dist/logger.d.ts.map +1 -1
  26. package/dist/logger.js +69 -11
  27. package/dist/logger.js.map +1 -1
  28. package/dist/mockLogger.d.ts +12 -2
  29. package/dist/mockLogger.d.ts.map +1 -1
  30. package/dist/mockLogger.js +24 -2
  31. package/dist/mockLogger.js.map +1 -1
  32. package/dist/packageVersion.d.ts +1 -1
  33. package/dist/packageVersion.js +1 -1
  34. package/dist/packageVersion.js.map +1 -1
  35. package/dist/sampledTelemetryHelper.d.ts.map +1 -1
  36. package/dist/sampledTelemetryHelper.js.map +1 -1
  37. package/dist/telemetryTypes.d.ts +81 -0
  38. package/dist/telemetryTypes.d.ts.map +1 -0
  39. package/dist/telemetryTypes.js +7 -0
  40. package/dist/telemetryTypes.js.map +1 -0
  41. package/dist/thresholdCounter.d.ts.map +1 -1
  42. package/dist/thresholdCounter.js.map +1 -1
  43. package/dist/utils.d.ts.map +1 -1
  44. package/dist/utils.js.map +1 -1
  45. package/lib/config.d.ts.map +1 -1
  46. package/lib/config.js +18 -5
  47. package/lib/config.js.map +1 -1
  48. package/lib/debugLogger.d.ts.map +1 -1
  49. package/lib/debugLogger.js +13 -2
  50. package/lib/debugLogger.js.map +1 -1
  51. package/lib/errorLogging.d.ts +8 -7
  52. package/lib/errorLogging.d.ts.map +1 -1
  53. package/lib/errorLogging.js +23 -20
  54. package/lib/errorLogging.js.map +1 -1
  55. package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
  56. package/lib/eventEmitterWithErrorHandling.js.map +1 -1
  57. package/lib/events.d.ts.map +1 -1
  58. package/lib/events.js.map +1 -1
  59. package/lib/fluidErrorBase.d.ts.map +1 -1
  60. package/lib/fluidErrorBase.js +4 -4
  61. package/lib/fluidErrorBase.js.map +1 -1
  62. package/lib/index.d.ts +3 -2
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js +2 -2
  65. package/lib/index.js.map +1 -1
  66. package/lib/logger.d.ts +15 -4
  67. package/lib/logger.d.ts.map +1 -1
  68. package/lib/logger.js +69 -12
  69. package/lib/logger.js.map +1 -1
  70. package/lib/mockLogger.d.ts +12 -2
  71. package/lib/mockLogger.d.ts.map +1 -1
  72. package/lib/mockLogger.js +24 -2
  73. package/lib/mockLogger.js.map +1 -1
  74. package/lib/packageVersion.d.ts +1 -1
  75. package/lib/packageVersion.js +1 -1
  76. package/lib/packageVersion.js.map +1 -1
  77. package/lib/sampledTelemetryHelper.d.ts.map +1 -1
  78. package/lib/sampledTelemetryHelper.js.map +1 -1
  79. package/lib/telemetryTypes.d.ts +81 -0
  80. package/lib/telemetryTypes.d.ts.map +1 -0
  81. package/lib/telemetryTypes.js +6 -0
  82. package/lib/telemetryTypes.js.map +1 -0
  83. package/lib/thresholdCounter.d.ts.map +1 -1
  84. package/lib/thresholdCounter.js.map +1 -1
  85. package/lib/utils.d.ts.map +1 -1
  86. package/lib/utils.js.map +1 -1
  87. package/package.json +49 -48
  88. package/prettier.config.cjs +1 -1
  89. package/src/config.ts +185 -173
  90. package/src/debugLogger.ts +128 -111
  91. package/src/errorLogging.ts +306 -300
  92. package/src/eventEmitterWithErrorHandling.ts +16 -12
  93. package/src/events.ts +26 -26
  94. package/src/fluidErrorBase.ts +42 -38
  95. package/src/index.ts +29 -9
  96. package/src/logger.ts +568 -500
  97. package/src/mockLogger.ts +118 -88
  98. package/src/packageVersion.ts +1 -1
  99. package/src/sampledTelemetryHelper.ts +122 -122
  100. package/src/telemetryTypes.ts +96 -0
  101. package/src/thresholdCounter.ts +34 -34
  102. package/src/utils.ts +15 -15
  103. package/tsconfig.esnext.json +6 -6
  104. package/tsconfig.json +9 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/telemetry-utils",
3
- "version": "2.0.0-dev.2.3.0.115467",
3
+ "version": "2.0.0-dev.4.1.0.148229",
4
4
  "description": "Collection of telemetry relates utilities for Fluid",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -18,35 +18,6 @@
18
18
  "./lib/indexNode.js": "./lib/indexBrowser.js"
19
19
  },
20
20
  "types": "dist/index.d.ts",
21
- "scripts": {
22
- "build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
23
- "build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
24
- "build:compile": "concurrently npm:build:commonjs npm:build:esnext",
25
- "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
26
- "build:esnext": "tsc --project ./tsconfig.esnext.json",
27
- "build:full": "npm run build",
28
- "build:full:compile": "npm run build:compile",
29
- "build:genver": "gen-version",
30
- "build:test": "tsc --project ./src/test/tsconfig.json",
31
- "bump-version": "npm version minor --no-push --no-git-tag-version && npm run build:genver",
32
- "ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
33
- "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
34
- "eslint": "eslint --format stylish src",
35
- "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
36
- "format": "npm run prettier:fix",
37
- "lint": "npm run eslint",
38
- "lint:fix": "npm run eslint:fix",
39
- "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
40
- "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
41
- "test": "npm run test:mocha",
42
- "test:coverage": "nyc npm run test:report",
43
- "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
44
- "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
45
- "test:report": "npm test -- -- --reporter xunit --reporter-option output=nyc/mocha-junit-report.xml",
46
- "tsc": "tsc",
47
- "typetests:gen": "flub generate typetests --generate --dir .",
48
- "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
49
- },
50
21
  "nyc": {
51
22
  "all": true,
52
23
  "cache-dir": "nyc/.cache",
@@ -69,39 +40,69 @@
69
40
  },
70
41
  "dependencies": {
71
42
  "@fluidframework/common-definitions": "^0.20.1",
72
- "@fluidframework/common-utils": "^1.0.0",
43
+ "@fluidframework/common-utils": "^1.1.1",
73
44
  "debug": "^4.1.1",
74
45
  "events": "^3.1.0",
75
46
  "uuid": "^8.3.1"
76
47
  },
77
48
  "devDependencies": {
78
- "@fluid-tools/build-cli": "^0.7.0",
49
+ "@fluid-tools/build-cli": "^0.13.1",
79
50
  "@fluidframework/build-common": "^1.1.0",
80
- "@fluidframework/build-tools": "^0.7.0",
81
- "@fluidframework/eslint-config-fluid": "^1.2.0",
82
- "@fluidframework/mocha-test-setup": ">=2.0.0-dev.2.3.0.115467 <2.0.0-dev.3.0.0",
83
- "@fluidframework/telemetry-utils-previous": "npm:@fluidframework/telemetry-utils@2.0.0-internal.2.2.0",
84
- "@microsoft/api-extractor": "^7.22.2",
85
- "@rushstack/eslint-config": "^2.5.1",
51
+ "@fluidframework/build-tools": "^0.13.1",
52
+ "@fluidframework/eslint-config-fluid": "^2.0.0",
53
+ "@fluidframework/mocha-test-setup": "2.0.0-dev.4.1.0.148229",
54
+ "@fluidframework/telemetry-utils-previous": "npm:@fluidframework/telemetry-utils@2.0.0-internal.4.0.0",
55
+ "@microsoft/api-extractor": "^7.34.4",
86
56
  "@types/debug": "^4.1.5",
87
57
  "@types/events": "^3.0.0",
88
58
  "@types/mocha": "^9.1.1",
89
- "@types/node": "^14.18.0",
90
- "concurrently": "^6.2.0",
59
+ "@types/node": "^14.18.38",
60
+ "@types/uuid": "^8.3.0",
61
+ "concurrently": "^7.6.0",
91
62
  "copyfiles": "^2.4.1",
92
- "cross-env": "^7.0.2",
63
+ "cross-env": "^7.0.3",
93
64
  "eslint": "~8.6.0",
94
- "mocha": "^10.0.0",
95
- "nyc": "^15.0.0",
65
+ "mocha": "^10.2.0",
66
+ "mocha-json-output-reporter": "^2.0.1",
67
+ "mocha-multi-reporters": "^1.5.1",
68
+ "moment": "^2.21.0",
69
+ "nyc": "^15.1.0",
96
70
  "prettier": "~2.6.2",
97
- "rimraf": "^2.6.2",
71
+ "rimraf": "^4.4.0",
98
72
  "sinon": "^7.4.2",
99
73
  "typescript": "~4.5.5"
100
74
  },
101
75
  "typeValidation": {
102
- "version": "2.0.0-internal.2.3.0",
103
- "baselineRange": ">=2.0.0-internal.2.2.0 <2.0.0-internal.2.3.0",
104
- "baselineVersion": "2.0.0-internal.2.2.0",
105
76
  "broken": {}
77
+ },
78
+ "scripts": {
79
+ "build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
80
+ "build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
81
+ "build:compile": "concurrently npm:build:commonjs npm:build:esnext",
82
+ "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
83
+ "build:esnext": "tsc --project ./tsconfig.esnext.json",
84
+ "build:full": "npm run build",
85
+ "build:full:compile": "npm run build:compile",
86
+ "build:genver": "gen-version",
87
+ "build:test": "tsc --project ./src/test/tsconfig.json",
88
+ "bump-version": "npm version minor --no-push --no-git-tag-version && npm run build:genver",
89
+ "ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
90
+ "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
91
+ "eslint": "eslint --format stylish src",
92
+ "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
93
+ "format": "npm run prettier:fix",
94
+ "lint": "npm run prettier && npm run eslint",
95
+ "lint:fix": "npm run prettier:fix && npm run eslint:fix",
96
+ "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
97
+ "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
98
+ "test": "npm run test:mocha",
99
+ "test:coverage": "nyc npm run test:report",
100
+ "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
101
+ "test:mocha:multireport": "cross-env FLUID_TEST_MULTIREPORT=1 npm run test:mocha",
102
+ "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
103
+ "test:report": "npm test -- -- --reporter xunit --reporter-option output=nyc/mocha-junit-report.xml",
104
+ "tsc": "tsc",
105
+ "typetests:gen": "fluid-type-test-generator",
106
+ "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
106
107
  }
107
- }
108
+ }
@@ -4,5 +4,5 @@
4
4
  */
5
5
 
6
6
  module.exports = {
7
- ...require("@fluidframework/build-common/prettier.config.cjs"),
7
+ ...require("@fluidframework/build-common/prettier.config.cjs"),
8
8
  };
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,182 @@ 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
- /** `sessionStorage` is undefined in some environments such as Node */
145
+ /** `sessionStorage` is undefined in some environments such as Node and web pages with session storage disabled */
146
146
  const safeSessionStorage = (): Storage | undefined => {
147
- return globalThis.sessionStorage;
147
+ // For some configurations accessing "globalThis.sessionStorage" throws
148
+ // "'sessionStorage' property from 'Window': Access is denied for this document" rather than returning undefined.
149
+ // Therefor check for it before accessing.
150
+ try {
151
+ // Using globalThis and checking for undefined is preferred over just accessing global sessionStorage
152
+ // since it avoids an exception when running in node.
153
+ // In some cases this has returned null when disabled in the browser, so ensure its undefined in that case:
154
+ return globalThis.sessionStorage ?? undefined;
155
+ } catch {
156
+ // For browsers which error on the above when session storage is disabled:
157
+ return undefined;
158
+ }
148
159
  };
149
160
 
150
161
  /**
151
162
  * Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances
152
163
  */
153
164
  export class CachedConfigProvider implements IConfigProvider {
154
- private readonly configCache = new Map<string, StronglyTypedValue>();
155
- private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
165
+ private readonly configCache = new Map<string, StronglyTypedValue>();
166
+ private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];
156
167
 
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
- }
168
+ constructor(...orderedBaseProviders: (IConfigProviderBase | undefined)[]) {
169
+ this.orderedBaseProviders = [];
170
+ const knownProviders = new Set<IConfigProviderBase>();
171
+ const candidateProviders = [...orderedBaseProviders];
172
+ while (candidateProviders.length > 0) {
173
+ const baseProvider = candidateProviders.shift()!;
174
+ if (
175
+ baseProvider !== undefined &&
176
+ isConfigProviderBase(baseProvider) &&
177
+ !knownProviders.has(baseProvider)
178
+ ) {
179
+ knownProviders.add(baseProvider);
180
+ if (baseProvider instanceof CachedConfigProvider) {
181
+ candidateProviders.push(...baseProvider.orderedBaseProviders);
182
+ } else {
183
+ this.orderedBaseProviders.push(baseProvider);
184
+ }
185
+ }
186
+ }
187
+ }
188
+ getBoolean(name: string): boolean | undefined {
189
+ return this.getCacheEntry(name)?.boolean;
190
+ }
191
+ getNumber(name: string): number | undefined {
192
+ return this.getCacheEntry(name)?.number;
193
+ }
194
+ getString(name: string): string | undefined {
195
+ return this.getCacheEntry(name)?.string;
196
+ }
197
+ getBooleanArray(name: string): boolean[] | undefined {
198
+ return this.getCacheEntry(name)?.["boolean[]"];
199
+ }
200
+ getNumberArray(name: string): number[] | undefined {
201
+ return this.getCacheEntry(name)?.["number[]"];
202
+ }
203
+ getStringArray(name: string): string[] | undefined {
204
+ return this.getCacheEntry(name)?.["string[]"];
205
+ }
196
206
 
197
- getRawConfig(name: string): ConfigTypes {
198
- return this.getCacheEntry(name)?.raw;
199
- }
207
+ getRawConfig(name: string): ConfigTypes {
208
+ return this.getCacheEntry(name)?.raw;
209
+ }
200
210
 
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
- }
211
+ private getCacheEntry(name: string): StronglyTypedValue | undefined {
212
+ if (!this.configCache.has(name)) {
213
+ for (const provider of this.orderedBaseProviders) {
214
+ const parsed = stronglyTypedParse(provider?.getRawConfig(name));
215
+ if (parsed !== undefined) {
216
+ this.configCache.set(name, parsed);
217
+ return parsed;
218
+ }
219
+ }
220
+ // configs are immutable, if the first lookup returned no results, all lookups should
221
+ this.configCache.set(name, { raw: undefined });
222
+ }
223
+ return this.configCache.get(name);
224
+ }
215
225
  }
216
226
 
217
227
  /**
218
228
  * A type containing both a telemetry logger and a configuration provider
219
229
  */
220
- export interface MonitoringContext<
221
- L extends ITelemetryBaseLogger = ITelemetryLogger,
222
- > {
223
- config: IConfigProvider;
224
- logger: L;
230
+ export interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger> {
231
+ config: IConfigProvider;
232
+ logger: L;
225
233
  }
226
234
 
227
235
  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;
236
+ obj: L,
237
+ ): obj is L & MonitoringContext<L> {
238
+ const maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;
239
+ return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;
231
240
  }
232
241
 
233
242
  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);
243
+ logger: L,
244
+ ): MonitoringContext<L> {
245
+ if (loggerIsMonitoringContext<L>(logger)) {
246
+ return logger;
247
+ }
248
+ return mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);
239
249
  }
240
250
 
241
251
  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>;
252
+ logger: L,
253
+ ...configs: (IConfigProviderBase | undefined)[]
254
+ ) {
255
+ if (loggerIsMonitoringContext<L>(logger)) {
256
+ throw new Error("Logger is already a monitoring context");
257
+ }
258
+ /**
259
+ * this is the tricky bit we use for now to smuggle monitoring context around.
260
+ * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.
261
+ * We then expose it as a Monitoring context, so via types we hide the outer logger methods.
262
+ * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext
263
+ * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties
264
+ * of the MonitoringContext and get the config provider.
265
+ */
266
+ const mc: L & Partial<MonitoringContext<L>> = logger;
267
+ mc.config = new CachedConfigProvider(...configs);
268
+ mc.logger = logger;
269
+ return mc as MonitoringContext<L>;
258
270
  }
259
271
 
260
272
  function isConfigProviderBase(obj: unknown): obj is IConfigProviderBase {
261
- const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;
262
- return typeof (maybeConfig?.getRawConfig) === "function";
273
+ const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;
274
+ return typeof maybeConfig?.getRawConfig === "function";
263
275
  }