@fluidframework/telemetry-utils 0.52.0 → 0.54.0-47413
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/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +212 -0
- package/dist/config.js.map +1 -0
- package/dist/errorLogging.d.ts +10 -0
- package/dist/errorLogging.d.ts.map +1 -1
- package/dist/errorLogging.js +50 -39
- package/dist/errorLogging.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +5 -0
- package/dist/logger.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/config.d.ts +65 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +204 -0
- package/lib/config.js.map +1 -0
- package/lib/errorLogging.d.ts +10 -0
- package/lib/errorLogging.d.ts.map +1 -1
- package/lib/errorLogging.js +48 -38
- package/lib/errorLogging.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +5 -0
- package/lib/logger.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +3 -3
- package/src/config.ts +265 -0
- package/src/errorLogging.ts +62 -53
- package/src/index.ts +9 -0
- package/src/logger.ts +15 -2
- package/src/packageVersion.ts +1 -1
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { ITelemetryBaseLogger, ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
6
|
+
import { Lazy } from "@fluidframework/common-utils";
|
|
7
|
+
export declare type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Base interface for providing configurations to enable/disable/control features
|
|
10
|
+
*/
|
|
11
|
+
export interface IConfigProviderBase {
|
|
12
|
+
getRawConfig(name: string): ConfigTypes;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Explicitly typed interface for reading configurations
|
|
16
|
+
*/
|
|
17
|
+
export interface IConfigProvider extends IConfigProviderBase {
|
|
18
|
+
getBoolean(name: string): boolean | undefined;
|
|
19
|
+
getNumber(name: string): number | undefined;
|
|
20
|
+
getString(name: string): string | undefined;
|
|
21
|
+
getBooleanArray(name: string): boolean[] | undefined;
|
|
22
|
+
getNumberArray(name: string): number[] | undefined;
|
|
23
|
+
getStringArray(name: string): string[] | undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a base configuration provider based on `sessionStorage`
|
|
27
|
+
*
|
|
28
|
+
* @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store
|
|
29
|
+
*/
|
|
30
|
+
export declare const sessionStorageConfigProvider: Lazy<IConfigProviderBase>;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a base configuration provider based on the supplied `Storage` instance
|
|
33
|
+
*
|
|
34
|
+
* @param storage - instance of `Storage` to be used as storage media for the config
|
|
35
|
+
* @returns A base configuration provider with
|
|
36
|
+
* the supplied `Storage` instance as the underlying config store
|
|
37
|
+
*/
|
|
38
|
+
export declare const inMemoryConfigProvider: (storage: Storage | undefined) => IConfigProviderBase;
|
|
39
|
+
/**
|
|
40
|
+
* Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances
|
|
41
|
+
*/
|
|
42
|
+
export declare class CachedConfigProvider implements IConfigProvider {
|
|
43
|
+
private readonly configCache;
|
|
44
|
+
private readonly orderedBaseProviders;
|
|
45
|
+
constructor(...orderedBaseProviders: (IConfigProviderBase | undefined)[]);
|
|
46
|
+
getBoolean(name: string): boolean | undefined;
|
|
47
|
+
getNumber(name: string): number | undefined;
|
|
48
|
+
getString(name: string): string | undefined;
|
|
49
|
+
getBooleanArray(name: string): boolean[] | undefined;
|
|
50
|
+
getNumberArray(name: string): number[] | undefined;
|
|
51
|
+
getStringArray(name: string): string[] | undefined;
|
|
52
|
+
getRawConfig(name: string): ConfigTypes;
|
|
53
|
+
private getCacheEntry;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A type containing both a telemetry logger and a configuration provider
|
|
57
|
+
*/
|
|
58
|
+
export interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger> {
|
|
59
|
+
config: IConfigProvider;
|
|
60
|
+
logger: L;
|
|
61
|
+
}
|
|
62
|
+
export declare function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(obj: L): obj is L & MonitoringContext<L>;
|
|
63
|
+
export declare function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(logger: L): MonitoringContext<L>;
|
|
64
|
+
export declare function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(logger: L, ...configs: (IConfigProviderBase | undefined)[]): MonitoringContext<L>;
|
|
65
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAEpD,oBAAY,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,CAAC;AAElG;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;CAC3C;AAED;;GAEG;AACF,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IACzD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,SAAS,CAAC;IACrD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IACnD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;CACrD;AACF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,2BAC4C,CAAC;AAMtF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,YACrB,OAAO,GAAG,SAAS,KAAG,mBAYnC,CAAC;AA4FF;;GAEG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyC;IACrE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAsC;gBAGvE,GAAI,oBAAoB,EAAE,CAAC,mBAAmB,GAAG,SAAS,CAAC,EAAE;IAoBjE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAG7C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAG3C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAG3C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,SAAS;IAGpD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAGlD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAIlD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAIvC,OAAO,CAAC,aAAa;CAcxB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAC9B,CAAC,SAAS,oBAAoB,GAAG,gBAAgB;IAEjD,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,CAAC,CAAC;CACb;AAED,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,oBAAoB,GAAG,gBAAgB,EACvF,GAAG,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAG3C;AAED,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,oBAAoB,GAAG,gBAAgB,EACvF,MAAM,EAAE,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAKnC;AAED,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,oBAAoB,GAAG,gBAAgB,EACpF,MAAM,EAAE,CAAC,EAAE,GAAI,OAAO,EAAE,CAAC,mBAAmB,GAAG,SAAS,CAAC,EAAE,wBAgB9D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mixinMonitoringContext = exports.loggerToMonitoringContext = exports.loggerIsMonitoringContext = exports.CachedConfigProvider = exports.inMemoryConfigProvider = exports.sessionStorageConfigProvider = void 0;
|
|
4
|
+
const common_utils_1 = require("@fluidframework/common-utils");
|
|
5
|
+
/**
|
|
6
|
+
* Creates a base configuration provider based on `sessionStorage`
|
|
7
|
+
*
|
|
8
|
+
* @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store
|
|
9
|
+
*/
|
|
10
|
+
exports.sessionStorageConfigProvider = new common_utils_1.Lazy(() => exports.inMemoryConfigProvider(safeSessionStorage()));
|
|
11
|
+
const NullConfigProvider = {
|
|
12
|
+
getRawConfig: () => undefined,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Creates a base configuration provider based on the supplied `Storage` instance
|
|
16
|
+
*
|
|
17
|
+
* @param storage - instance of `Storage` to be used as storage media for the config
|
|
18
|
+
* @returns A base configuration provider with
|
|
19
|
+
* the supplied `Storage` instance as the underlying config store
|
|
20
|
+
*/
|
|
21
|
+
const inMemoryConfigProvider = (storage) => {
|
|
22
|
+
if (storage !== undefined && storage !== null) {
|
|
23
|
+
return new CachedConfigProvider({
|
|
24
|
+
getRawConfig: (name) => {
|
|
25
|
+
var _a, _b;
|
|
26
|
+
try {
|
|
27
|
+
return (_b = stronglyTypedParse((_a = storage.getItem(name)) !== null && _a !== void 0 ? _a : undefined)) === null || _b === void 0 ? void 0 : _b.raw;
|
|
28
|
+
}
|
|
29
|
+
catch (_c) { }
|
|
30
|
+
return undefined;
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return NullConfigProvider;
|
|
35
|
+
};
|
|
36
|
+
exports.inMemoryConfigProvider = inMemoryConfigProvider;
|
|
37
|
+
function isPrimitiveType(type) {
|
|
38
|
+
switch (type) {
|
|
39
|
+
case "boolean":
|
|
40
|
+
case "number":
|
|
41
|
+
case "string":
|
|
42
|
+
return true;
|
|
43
|
+
default:
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Takes any supported config type, and returns the value with a strong type. If the type of
|
|
49
|
+
* the config is not a supported type undefined will be returned.
|
|
50
|
+
* The user of this function should cache the result to avoid duplicated work.
|
|
51
|
+
*
|
|
52
|
+
* Strings will be attempted to be parsed and coerced into a strong config type.
|
|
53
|
+
* if it is not possible to parsed and coerce a string to a strong config type the original string
|
|
54
|
+
* will be return with a string type for the consumer to handle further if necessary.
|
|
55
|
+
*/
|
|
56
|
+
function stronglyTypedParse(input) {
|
|
57
|
+
let output = input;
|
|
58
|
+
let defaultReturn;
|
|
59
|
+
// we do special handling for strings to try and coerce
|
|
60
|
+
// them into a config type if we can. This makes it easy
|
|
61
|
+
// for config sources like sessionStorage which only
|
|
62
|
+
// holds strings
|
|
63
|
+
if (typeof input === "string") {
|
|
64
|
+
try {
|
|
65
|
+
output = JSON.parse(input);
|
|
66
|
+
// we succeeded in parsing, but we don't support parsing
|
|
67
|
+
// for any object as we can't do it type safely
|
|
68
|
+
// so in this case, the default return will be string
|
|
69
|
+
// rather than undefined, and the consumer
|
|
70
|
+
// can parse, as we don't want to provide
|
|
71
|
+
// a false sense of security by just
|
|
72
|
+
// casting.
|
|
73
|
+
defaultReturn = { raw: input, string: input };
|
|
74
|
+
}
|
|
75
|
+
catch (_a) { }
|
|
76
|
+
}
|
|
77
|
+
if (output === undefined) {
|
|
78
|
+
return defaultReturn;
|
|
79
|
+
}
|
|
80
|
+
const outputType = typeof output;
|
|
81
|
+
if (isPrimitiveType(outputType)) {
|
|
82
|
+
return Object.assign(Object.assign({}, defaultReturn), { raw: input, [outputType]: output });
|
|
83
|
+
}
|
|
84
|
+
if (Array.isArray(output)) {
|
|
85
|
+
const firstType = typeof output[0];
|
|
86
|
+
// ensure the first elements is a primitive type
|
|
87
|
+
if (!isPrimitiveType(firstType)) {
|
|
88
|
+
return defaultReturn;
|
|
89
|
+
}
|
|
90
|
+
// ensue all the elements types are homogeneous
|
|
91
|
+
// aka they all have the same type as the first
|
|
92
|
+
for (const v of output) {
|
|
93
|
+
if (typeof v !== firstType) {
|
|
94
|
+
return defaultReturn;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return Object.assign(Object.assign({}, defaultReturn), { raw: input, [`${firstType}[]`]: output });
|
|
98
|
+
}
|
|
99
|
+
return defaultReturn;
|
|
100
|
+
}
|
|
101
|
+
/** Referencing the `sessionStorage` variable can throw in some environments such as Node */
|
|
102
|
+
const safeSessionStorage = () => {
|
|
103
|
+
try {
|
|
104
|
+
return sessionStorage !== null ? sessionStorage : undefined;
|
|
105
|
+
}
|
|
106
|
+
catch (_a) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances
|
|
112
|
+
*/
|
|
113
|
+
class CachedConfigProvider {
|
|
114
|
+
constructor(...orderedBaseProviders) {
|
|
115
|
+
this.configCache = new Map();
|
|
116
|
+
this.orderedBaseProviders = [];
|
|
117
|
+
const knownProviders = new Set();
|
|
118
|
+
const candidateProviders = [...orderedBaseProviders];
|
|
119
|
+
while (candidateProviders.length > 0) {
|
|
120
|
+
const baseProvider = candidateProviders.shift();
|
|
121
|
+
if (baseProvider !== undefined
|
|
122
|
+
&& isConfigProviderBase(baseProvider)
|
|
123
|
+
&& !knownProviders.has(baseProvider)) {
|
|
124
|
+
knownProviders.add(baseProvider);
|
|
125
|
+
if (baseProvider instanceof CachedConfigProvider) {
|
|
126
|
+
candidateProviders.push(...baseProvider.orderedBaseProviders);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.orderedBaseProviders.push(baseProvider);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
getBoolean(name) {
|
|
135
|
+
var _a;
|
|
136
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a.boolean;
|
|
137
|
+
}
|
|
138
|
+
getNumber(name) {
|
|
139
|
+
var _a;
|
|
140
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a.number;
|
|
141
|
+
}
|
|
142
|
+
getString(name) {
|
|
143
|
+
var _a;
|
|
144
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a.string;
|
|
145
|
+
}
|
|
146
|
+
getBooleanArray(name) {
|
|
147
|
+
var _a;
|
|
148
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a["boolean[]"];
|
|
149
|
+
}
|
|
150
|
+
getNumberArray(name) {
|
|
151
|
+
var _a;
|
|
152
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a["number[]"];
|
|
153
|
+
}
|
|
154
|
+
getStringArray(name) {
|
|
155
|
+
var _a;
|
|
156
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a["string[]"];
|
|
157
|
+
}
|
|
158
|
+
getRawConfig(name) {
|
|
159
|
+
var _a;
|
|
160
|
+
return (_a = this.getCacheEntry(name)) === null || _a === void 0 ? void 0 : _a.raw;
|
|
161
|
+
}
|
|
162
|
+
getCacheEntry(name) {
|
|
163
|
+
if (!this.configCache.has(name)) {
|
|
164
|
+
for (const provider of this.orderedBaseProviders) {
|
|
165
|
+
const parsed = stronglyTypedParse(provider === null || provider === void 0 ? void 0 : provider.getRawConfig(name));
|
|
166
|
+
if (parsed !== undefined) {
|
|
167
|
+
this.configCache.set(name, parsed);
|
|
168
|
+
return parsed;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// configs are immutable, if the first lookup returned no results, all lookups should
|
|
172
|
+
this.configCache.set(name, { raw: undefined });
|
|
173
|
+
}
|
|
174
|
+
return this.configCache.get(name);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.CachedConfigProvider = CachedConfigProvider;
|
|
178
|
+
function loggerIsMonitoringContext(obj) {
|
|
179
|
+
const maybeConfig = obj;
|
|
180
|
+
return isConfigProviderBase(maybeConfig === null || maybeConfig === void 0 ? void 0 : maybeConfig.config) && (maybeConfig === null || maybeConfig === void 0 ? void 0 : maybeConfig.logger) !== undefined;
|
|
181
|
+
}
|
|
182
|
+
exports.loggerIsMonitoringContext = loggerIsMonitoringContext;
|
|
183
|
+
function loggerToMonitoringContext(logger) {
|
|
184
|
+
if (loggerIsMonitoringContext(logger)) {
|
|
185
|
+
return logger;
|
|
186
|
+
}
|
|
187
|
+
return mixinMonitoringContext(logger, exports.sessionStorageConfigProvider.value);
|
|
188
|
+
}
|
|
189
|
+
exports.loggerToMonitoringContext = loggerToMonitoringContext;
|
|
190
|
+
function mixinMonitoringContext(logger, ...configs) {
|
|
191
|
+
if (loggerIsMonitoringContext(logger)) {
|
|
192
|
+
throw new Error("Logger is already a monitoring context");
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* this is the tricky bit we use for now to smuggle monitoring context around.
|
|
196
|
+
* To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.
|
|
197
|
+
* We then expose it as a Monitoring context, so via types we hide the outer logger methods.
|
|
198
|
+
* To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext
|
|
199
|
+
* so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties
|
|
200
|
+
* of the MonitoringContext and get the config provider.
|
|
201
|
+
*/
|
|
202
|
+
const mc = logger;
|
|
203
|
+
mc.config = new CachedConfigProvider(...configs);
|
|
204
|
+
mc.logger = logger;
|
|
205
|
+
return mc;
|
|
206
|
+
}
|
|
207
|
+
exports.mixinMonitoringContext = mixinMonitoringContext;
|
|
208
|
+
function isConfigProviderBase(obj) {
|
|
209
|
+
const maybeConfig = obj;
|
|
210
|
+
return typeof (maybeConfig === null || maybeConfig === void 0 ? void 0 : maybeConfig.getRawConfig) === "function";
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { ITelemetryBaseLogger, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { Lazy } from \"@fluidframework/common-utils\";\n\nexport type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;\n\n/**\n * Base interface for providing configurations to enable/disable/control features\n */\nexport interface IConfigProviderBase {\n getRawConfig(name: string): ConfigTypes;\n}\n\n/**\n * Explicitly typed interface for reading configurations\n */\n export interface IConfigProvider extends IConfigProviderBase {\n getBoolean(name: string): boolean | undefined;\n getNumber(name: string): number | undefined;\n getString(name: string): string | undefined;\n getBooleanArray(name: string): boolean[] | undefined;\n getNumberArray(name: string): number[] | undefined;\n getStringArray(name: string): string[] | undefined;\n }\n/**\n * Creates a base configuration provider based on `sessionStorage`\n *\n * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store\n */\nexport const sessionStorageConfigProvider =\n new Lazy<IConfigProviderBase>(() => inMemoryConfigProvider(safeSessionStorage()));\n\nconst NullConfigProvider: IConfigProviderBase = {\n getRawConfig: () => undefined,\n};\n\n/**\n * Creates a base configuration provider based on the supplied `Storage` instance\n *\n * @param storage - instance of `Storage` to be used as storage media for the config\n * @returns A base configuration provider with\n * the supplied `Storage` instance as the underlying config store\n */\nexport const inMemoryConfigProvider =\n (storage: Storage | undefined): IConfigProviderBase => {\n if (storage !== undefined && storage !== null) {\n return new CachedConfigProvider({\n getRawConfig: (name: string) => {\n try {\n return stronglyTypedParse(storage.getItem(name) ?? undefined)?.raw;\n } catch { }\n return undefined;\n },\n });\n }\n return NullConfigProvider;\n};\n\ninterface ConfigTypeStringToType {\n number: number;\n string: string;\n boolean: boolean;\n [\"number[]\"]: number[];\n [\"string[]\"]: string[];\n [\"boolean[]\"]: boolean[];\n}\n\ntype PrimitiveTypeStrings = \"number\" | \"string\" | \"boolean\";\n\nfunction isPrimitiveType(type: string): type is PrimitiveTypeStrings {\n switch (type) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n return true;\n default:\n return false;\n }\n}\n\ninterface StronglyTypedValue extends Partial<ConfigTypeStringToType> {\n raw: ConfigTypes;\n}\n/**\n * Takes any supported config type, and returns the value with a strong type. If the type of\n * the config is not a supported type undefined will be returned.\n * The user of this function should cache the result to avoid duplicated work.\n *\n * Strings will be attempted to be parsed and coerced into a strong config type.\n * if it is not possible to parsed and coerce a string to a strong config type the original string\n * will be return with a string type for the consumer to handle further if necessary.\n */\nfunction stronglyTypedParse(input: ConfigTypes): StronglyTypedValue | undefined {\n let output: ConfigTypes = input;\n let defaultReturn: Pick<StronglyTypedValue,\"raw\" | \"string\"> | undefined;\n // we do special handling for strings to try and coerce\n // them into a config type if we can. This makes it easy\n // for config sources like sessionStorage which only\n // holds strings\n if (typeof input === \"string\") {\n try {\n output = JSON.parse(input);\n // we succeeded in parsing, but we don't support parsing\n // for any object as we can't do it type safely\n // so in this case, the default return will be string\n // rather than undefined, and the consumer\n // can parse, as we don't want to provide\n // a false sense of security by just\n // casting.\n defaultReturn = { raw: input, string: input };\n } catch { }\n }\n\n if (output === undefined) {\n return defaultReturn;\n }\n\n const outputType = typeof output;\n if (isPrimitiveType(outputType)) {\n return { ...defaultReturn, raw: input, [outputType]: output };\n }\n\n if (Array.isArray(output)) {\n const firstType = typeof output[0];\n // ensure the first elements is a primitive type\n if (!isPrimitiveType(firstType)) {\n return defaultReturn;\n }\n // ensue all the elements types are homogeneous\n // aka they all have the same type as the first\n for (const v of output) {\n if (typeof v !== firstType) {\n return defaultReturn;\n }\n }\n return { ...defaultReturn, raw: input, [`${firstType}[]`]: output };\n }\n\n return defaultReturn;\n}\n\n/** Referencing the `sessionStorage` variable can throw in some environments such as Node */\nconst safeSessionStorage = (): Storage | undefined => {\n try {\n return sessionStorage !== null ? sessionStorage : undefined;\n } catch { return undefined; }\n};\n\n/**\n * Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances\n */\nexport class CachedConfigProvider implements IConfigProvider {\n private readonly configCache = new Map<string, StronglyTypedValue>();\n private readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];\n\n constructor(\n ... orderedBaseProviders: (IConfigProviderBase | undefined)[]\n ) {\n this.orderedBaseProviders = [];\n const knownProviders = new Set<IConfigProviderBase>();\n const candidateProviders = [...orderedBaseProviders];\n while (candidateProviders.length > 0) {\n const baseProvider = candidateProviders.shift()!;\n if (baseProvider !== undefined\n && isConfigProviderBase(baseProvider)\n && !knownProviders.has(baseProvider)\n ) {\n knownProviders.add(baseProvider);\n if (baseProvider instanceof CachedConfigProvider) {\n candidateProviders.push(...baseProvider.orderedBaseProviders);\n } else {\n this.orderedBaseProviders.push(baseProvider);\n }\n }\n }\n }\n getBoolean(name: string): boolean | undefined {\n return this.getCacheEntry(name)?.boolean;\n }\n getNumber(name: string): number | undefined {\n return this.getCacheEntry(name)?.number;\n }\n getString(name: string): string | undefined {\n return this.getCacheEntry(name)?.string;\n }\n getBooleanArray(name: string): boolean[] | undefined {\n return this.getCacheEntry(name)?.[\"boolean[]\"];\n }\n getNumberArray(name: string): number[] | undefined {\n return this.getCacheEntry(name)?.[\"number[]\"];\n }\n getStringArray(name: string): string[] | undefined {\n return this.getCacheEntry(name)?.[\"string[]\"];\n }\n\n getRawConfig(name: string): ConfigTypes {\n return this.getCacheEntry(name)?.raw;\n }\n\n private getCacheEntry(name: string): StronglyTypedValue | undefined {\n if (!this.configCache.has(name)) {\n for (const provider of this.orderedBaseProviders) {\n const parsed = stronglyTypedParse(provider?.getRawConfig(name));\n if (parsed !== undefined) {\n this.configCache.set(name, parsed);\n return parsed;\n }\n }\n // configs are immutable, if the first lookup returned no results, all lookups should\n this.configCache.set(name, { raw: undefined });\n }\n return this.configCache.get(name);\n }\n}\n\n/**\n * A type containing both a telemetry logger and a configuration provider\n */\nexport interface MonitoringContext<\n L extends ITelemetryBaseLogger = ITelemetryLogger\n> {\n config: IConfigProvider;\n logger: L;\n}\n\nexport function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(\n obj: L): obj is L & MonitoringContext<L> {\n const maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;\n return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;\n}\n\nexport function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(\n logger: L): MonitoringContext<L> {\n if(loggerIsMonitoringContext<L>(logger)) {\n return logger;\n }\n return mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);\n}\n\nexport function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLogger>(\n logger: L, ... configs: (IConfigProviderBase | undefined)[]) {\n if (loggerIsMonitoringContext<L>(logger)) {\n throw new Error(\"Logger is already a monitoring context\");\n }\n /**\n * this is the tricky bit we use for now to smuggle monitoring context around.\n * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.\n * We then expose it as a Monitoring context, so via types we hide the outer logger methods.\n * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext\n * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties\n * of the MonitoringContext and get the config provider.\n */\n const mc: L & Partial<MonitoringContext<L>> = logger;\n mc.config = new CachedConfigProvider(...configs);\n mc.logger = logger;\n return mc as MonitoringContext<L>;\n}\n\nfunction isConfigProviderBase(obj: unknown): obj is IConfigProviderBase {\n const maybeConfig = obj as Partial<IConfigProviderBase> | undefined;\n return typeof (maybeConfig?.getRawConfig) === \"function\";\n}\n"]}
|
package/dist/errorLogging.d.ts
CHANGED
|
@@ -24,6 +24,16 @@ export interface IFluidErrorAnnotations {
|
|
|
24
24
|
* @param annotations - Annotations to apply to the normalized error
|
|
25
25
|
*/
|
|
26
26
|
export declare function normalizeError(error: unknown, annotations?: IFluidErrorAnnotations): IFluidErrorBase;
|
|
27
|
+
/**
|
|
28
|
+
* The purpose of this function is to provide ability to capture stack context quickly.
|
|
29
|
+
* Accessing new Error().stack is slow, and the slowest part is accessing stack property itself.
|
|
30
|
+
* There are scenarios where we generate error with stack, but error is handled in most cases and
|
|
31
|
+
* stack property is not accessed.
|
|
32
|
+
* For such cases it's better to not read stack property right away, but rather delay it until / if it's needed
|
|
33
|
+
* Some browsers will populate stack right away, others require throwing Error, so we do auto-detection on the fly.
|
|
34
|
+
* @returns Error object that has stack populated.
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateErrorWithStack(): Error;
|
|
27
37
|
export declare function generateStack(): string | undefined;
|
|
28
38
|
/**
|
|
29
39
|
* Create a new error, wrapping and caused by the given unknown error.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorLogging.d.ts","sourceRoot":"","sources":["../src/errorLogging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,aAAa,EACb,4BAA4B,EAC5B,gBAAgB,EAChB,oBAAoB,EACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAEH,eAAe,EAGlB,MAAM,kBAAkB,CAAC;AAO1B,sEAAsE;AACtE,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO;aAiBhD,MAAM;;;EAkBrC;AAED,6CAA6C;AAC7C,eAAO,MAAM,eAAe,MAAO,GAAG,uBAAwE,CAAC;AAW/G,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACnC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,oBAAoB,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"errorLogging.d.ts","sourceRoot":"","sources":["../src/errorLogging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,aAAa,EACb,4BAA4B,EAC5B,gBAAgB,EAChB,oBAAoB,EACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAEH,eAAe,EAGlB,MAAM,kBAAkB,CAAC;AAO1B,sEAAsE;AACtE,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO;aAiBhD,MAAM;;;EAkBrC;AAED,6CAA6C;AAC7C,eAAO,MAAM,eAAe,MAAO,GAAG,uBAAwE,CAAC;AAW/G,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACnC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,OAAO,EACd,WAAW,GAAE,sBAA2B,GACzC,eAAe,CA+BjB;AAID;;;;;;;;GAQG;AACF,wBAAgB,sBAAsB,IAAI,KAAK,CAgB/C;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;GAOG;AACF,wBAAgB,SAAS,CAAC,CAAC,SAAS,eAAe,EAChD,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,GACnC,CAAC,CAiBH;AAED,sGAAsG;AACtG,wBAAgB,eAAe,CAAC,CAAC,SAAS,eAAe,EACrD,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,EAClC,MAAM,EAAE,gBAAgB,KAa3B;AAWD;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,4BAA4B,CAExF;AAiCD;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAM,YAAW,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC;IAYlG,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAXzC,QAAQ,CAAC,eAAe,SAAU;IAElC;;;;;OAKG;gBAEC,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,oBAAoB,EACX,oBAAoB,GAAE,GAAG,CAAC,MAAM,CAAa;IAYlE;;OAEG;IACI,sBAAsB,CAAC,KAAK,EAAE,oBAAoB;IAIzD;;OAEG;IACI,sBAAsB,IAAI,oBAAoB;CASxD"}
|
package/dist/errorLogging.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.LoggingError = exports.isTaggedTelemetryPropertyValue = exports.wrapErrorAndLog = exports.wrapError = exports.generateStack = exports.normalizeError = exports.isILoggingError = exports.extractLogSafeErrorProperties = void 0;
|
|
7
|
+
exports.LoggingError = exports.isTaggedTelemetryPropertyValue = exports.wrapErrorAndLog = exports.wrapError = exports.generateStack = exports.generateErrorWithStack = exports.normalizeError = exports.isILoggingError = exports.extractLogSafeErrorProperties = void 0;
|
|
8
8
|
const uuid_1 = require("uuid");
|
|
9
9
|
const fluidErrorBase_1 = require("./fluidErrorBase");
|
|
10
10
|
/** @returns true if value is an object but neither null nor an array */
|
|
@@ -54,25 +54,6 @@ function copyProps(target, source) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
/** Simplest possible implementation of IFluidErrorBase */
|
|
58
|
-
class SimpleFluidError {
|
|
59
|
-
constructor(errorProps) {
|
|
60
|
-
this.telemetryProps = {};
|
|
61
|
-
this.name = "Error";
|
|
62
|
-
this.errorType = errorProps.errorType;
|
|
63
|
-
this.fluidErrorCode = errorProps.fluidErrorCode;
|
|
64
|
-
this.message = errorProps.message;
|
|
65
|
-
this.stack = errorProps.stack;
|
|
66
|
-
this.errorInstanceId = uuid_1.v4();
|
|
67
|
-
this.addTelemetryProperties(errorProps);
|
|
68
|
-
}
|
|
69
|
-
getTelemetryProperties() {
|
|
70
|
-
return this.telemetryProps;
|
|
71
|
-
}
|
|
72
|
-
addTelemetryProperties(props) {
|
|
73
|
-
copyProps(this.telemetryProps, props);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
57
|
/** For backwards compatibility with pre-fluidErrorCode valid errors */
|
|
77
58
|
function patchWithErrorCode(legacyError) {
|
|
78
59
|
const patchMe = legacyError;
|
|
@@ -103,7 +84,7 @@ function normalizeError(error, annotations = {}) {
|
|
|
103
84
|
errorType: "genericError",
|
|
104
85
|
fluidErrorCode: "",
|
|
105
86
|
message,
|
|
106
|
-
stack
|
|
87
|
+
stack,
|
|
107
88
|
});
|
|
108
89
|
fluidError.addTelemetryProperties(Object.assign(Object.assign({}, annotations.props), { untrustedOrigin: 1 }));
|
|
109
90
|
if (typeof (error) !== "object") {
|
|
@@ -113,18 +94,34 @@ function normalizeError(error, annotations = {}) {
|
|
|
113
94
|
return fluidError;
|
|
114
95
|
}
|
|
115
96
|
exports.normalizeError = normalizeError;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
97
|
+
let stackPopulatedOnCreation;
|
|
98
|
+
/**
|
|
99
|
+
* The purpose of this function is to provide ability to capture stack context quickly.
|
|
100
|
+
* Accessing new Error().stack is slow, and the slowest part is accessing stack property itself.
|
|
101
|
+
* There are scenarios where we generate error with stack, but error is handled in most cases and
|
|
102
|
+
* stack property is not accessed.
|
|
103
|
+
* For such cases it's better to not read stack property right away, but rather delay it until / if it's needed
|
|
104
|
+
* Some browsers will populate stack right away, others require throwing Error, so we do auto-detection on the fly.
|
|
105
|
+
* @returns Error object that has stack populated.
|
|
106
|
+
*/
|
|
107
|
+
function generateErrorWithStack() {
|
|
108
|
+
const err = new Error("<<generated stack>>");
|
|
109
|
+
if (stackPopulatedOnCreation === undefined) {
|
|
110
|
+
stackPopulatedOnCreation = (err.stack !== undefined);
|
|
111
|
+
}
|
|
112
|
+
if (stackPopulatedOnCreation) {
|
|
113
|
+
return err;
|
|
126
114
|
}
|
|
127
|
-
|
|
115
|
+
try {
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
return e;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.generateErrorWithStack = generateErrorWithStack;
|
|
123
|
+
function generateStack() {
|
|
124
|
+
return generateErrorWithStack().stack;
|
|
128
125
|
}
|
|
129
126
|
exports.generateStack = generateStack;
|
|
130
127
|
/**
|
|
@@ -139,13 +136,7 @@ function wrapError(innerError, newErrorFn) {
|
|
|
139
136
|
const { message, stack, } = extractLogSafeErrorProperties(innerError, false /* sanitizeStack */);
|
|
140
137
|
const newError = newErrorFn(message);
|
|
141
138
|
if (stack !== undefined) {
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
Object.assign(newError, { stack });
|
|
145
|
-
}
|
|
146
|
-
catch (errorSettingStack) {
|
|
147
|
-
newError.addTelemetryProperties({ stack2: stack });
|
|
148
|
-
}
|
|
139
|
+
overwriteStack(newError, stack);
|
|
149
140
|
}
|
|
150
141
|
if (fluidErrorBase_1.hasErrorInstanceId(innerError)) {
|
|
151
142
|
newError.addTelemetryProperties({ innerErrorInstanceId: innerError.errorInstanceId });
|
|
@@ -166,6 +157,15 @@ function wrapErrorAndLog(innerError, newErrorFn, logger) {
|
|
|
166
157
|
return newError;
|
|
167
158
|
}
|
|
168
159
|
exports.wrapErrorAndLog = wrapErrorAndLog;
|
|
160
|
+
function overwriteStack(error, stack) {
|
|
161
|
+
// supposedly setting stack on an Error can throw.
|
|
162
|
+
try {
|
|
163
|
+
Object.assign(error, { stack });
|
|
164
|
+
}
|
|
165
|
+
catch (errorSettingStack) {
|
|
166
|
+
error.addTelemetryProperties({ stack2: stack });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
169
|
/**
|
|
170
170
|
* Type guard to identify if a particular value (loosely) appears to be a tagged telemetry property
|
|
171
171
|
*/
|
|
@@ -244,4 +244,15 @@ class LoggingError extends Error {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
exports.LoggingError = LoggingError;
|
|
247
|
+
/** Simple implementation of IFluidErrorBase, extending LoggingError */
|
|
248
|
+
class SimpleFluidError extends LoggingError {
|
|
249
|
+
constructor(errorProps) {
|
|
250
|
+
super(errorProps.message);
|
|
251
|
+
this.errorType = errorProps.errorType;
|
|
252
|
+
this.fluidErrorCode = errorProps.fluidErrorCode;
|
|
253
|
+
if (errorProps.stack !== undefined) {
|
|
254
|
+
overwriteStack(this, errorProps.stack);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
247
258
|
//# sourceMappingURL=errorLogging.js.map
|
package/dist/errorLogging.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorLogging.js","sourceRoot":"","sources":["../src/errorLogging.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ILoggingError,\n ITaggedTelemetryPropertyType,\n ITelemetryLogger,\n ITelemetryProperties,\n} from \"@fluidframework/common-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport {\n hasErrorInstanceId,\n IFluidErrorBase,\n isFluidError,\n isValidLegacyError,\n} from \"./fluidErrorBase\";\n\n/** @returns true if value is an object but neither null nor an array */\nconst isRegularObject = (value: any): boolean => {\n return value !== null && !Array.isArray(value) && typeof value === \"object\";\n};\n\n/** Inspect the given error for common \"safe\" props and return them */\nexport function extractLogSafeErrorProperties(error: any, sanitizeStack: boolean) {\n const removeMessageFromStack = (stack: string, errorName?: string) => {\n if (!sanitizeStack) {\n return stack;\n }\n const stackFrames = stack.split(\"\\n\");\n stackFrames.shift(); // Remove \"[ErrorName]: [ErrorMessage]\"\n if (errorName !== undefined) {\n stackFrames.unshift(errorName); // Add \"[ErrorName]\"\n }\n return stackFrames.join(\"\\n\");\n };\n\n const message = (typeof error?.message === \"string\")\n ? error.message as string\n : String(error);\n\n const safeProps: { message: string; errorType?: string; stack?: string } = {\n message,\n };\n\n if (isRegularObject(error)) {\n const { errorType, stack, name } = error;\n\n if (typeof errorType === \"string\") {\n safeProps.errorType = errorType;\n }\n\n if (typeof stack === \"string\") {\n const errorName = (typeof name === \"string\") ? name : undefined;\n safeProps.stack = removeMessageFromStack(stack, errorName);\n }\n }\n\n return safeProps;\n}\n\n/** type guard for ILoggingError interface */\nexport const isILoggingError = (x: any): x is ILoggingError => typeof x?.getTelemetryProperties === \"function\";\n\n/** Copy props from source onto target, but do not overwrite an existing prop that matches */\nfunction copyProps(target: ITelemetryProperties | LoggingError, source: ITelemetryProperties) {\n for (const key of Object.keys(source)) {\n if (target[key] === undefined) {\n target[key] = source[key];\n }\n }\n}\n\n/** Metadata to annotate an error object when annotating or normalizing it */\nexport interface IFluidErrorAnnotations {\n /** Telemetry props to log with the error */\n props?: ITelemetryProperties;\n}\n\n/** Simplest possible implementation of IFluidErrorBase */\nclass SimpleFluidError implements IFluidErrorBase {\n private readonly telemetryProps: ITelemetryProperties = {};\n\n readonly errorType: string;\n readonly fluidErrorCode: string;\n readonly message: string;\n readonly stack?: string;\n readonly name: string = \"Error\";\n readonly errorInstanceId: string;\n\n constructor(\n errorProps: Omit<IFluidErrorBase,\n | \"getTelemetryProperties\"\n | \"addTelemetryProperties\"\n | \"errorInstanceId\"\n | \"name\">,\n ) {\n this.errorType = errorProps.errorType;\n this.fluidErrorCode = errorProps.fluidErrorCode;\n this.message = errorProps.message;\n this.stack = errorProps.stack;\n this.errorInstanceId = uuid();\n\n this.addTelemetryProperties(errorProps);\n }\n\n getTelemetryProperties(): ITelemetryProperties {\n return this.telemetryProps;\n }\n\n addTelemetryProperties(props: ITelemetryProperties) {\n copyProps(this.telemetryProps, props);\n }\n}\n\n/** For backwards compatibility with pre-fluidErrorCode valid errors */\nfunction patchWithErrorCode(\n legacyError: Omit<IFluidErrorBase, \"fluidErrorCode\">,\n): asserts legacyError is IFluidErrorBase {\n const patchMe: { -readonly [P in \"fluidErrorCode\"]?: IFluidErrorBase[P] } = legacyError as any;\n if (patchMe.fluidErrorCode === undefined) {\n patchMe.fluidErrorCode = \"<error predates fluidErrorCode>\";\n }\n}\n\n/**\n * Normalize the given error yielding a valid Fluid Error\n * @returns A valid Fluid Error with any provided annotations applied\n * @param error - The error to normalize\n * @param annotations - Annotations to apply to the normalized error\n */\nexport function normalizeError(\n error: unknown,\n annotations: IFluidErrorAnnotations = {},\n): IFluidErrorBase {\n // Back-compat, while IFluidErrorBase is rolled out\n if (isValidLegacyError(error)) {\n patchWithErrorCode(error);\n }\n\n if (isFluidError(error)) {\n // We can simply add the telemetry props to the error and return it\n error.addTelemetryProperties(annotations.props ?? {});\n return error;\n }\n\n // We have to construct a new Fluid Error, copying safe properties over\n const { message, stack } = extractLogSafeErrorProperties(error, false /* sanitizeStack */);\n const fluidError: IFluidErrorBase = new SimpleFluidError({\n errorType: \"genericError\", // Match Container/Driver generic error type\n fluidErrorCode: \"\",\n message,\n stack: stack ?? generateStack(),\n });\n\n fluidError.addTelemetryProperties({\n ...annotations.props,\n untrustedOrigin: 1, // This will let us filter to errors not originated by our own code\n });\n\n if (typeof(error) !== \"object\") {\n // This is only interesting for non-objects\n fluidError.addTelemetryProperties({ typeofError: typeof(error) });\n }\n return fluidError;\n}\n\nexport function generateStack(): string | undefined {\n // Some browsers will populate stack right away, others require throwing Error\n let stack = new Error(\"<<generated stack>>\").stack;\n if (!stack) {\n try {\n throw new Error(\"<<generated stack>>\");\n } catch (e) {\n stack = e.stack;\n }\n }\n return stack;\n}\n\n/**\n * Create a new error, wrapping and caused by the given unknown error.\n * Copies the inner error's message and stack over but otherwise uses newErrorFn to define the error.\n * The inner error's instance id will also be logged for telemetry analysis.\n * @param innerError - An error from untrusted/unknown origins\n * @param newErrorFn - callback that will create a new error given the original error's message\n * @returns A new error object \"wrapping\" the given error\n */\n export function wrapError<T extends IFluidErrorBase>(\n innerError: unknown,\n newErrorFn: (message: string) => T,\n): T {\n const {\n message,\n stack,\n } = extractLogSafeErrorProperties(innerError, false /* sanitizeStack */);\n\n const newError = newErrorFn(message);\n\n if (stack !== undefined) {\n // supposedly setting stack on an Error can throw.\n try {\n Object.assign(newError, { stack });\n } catch (errorSettingStack) {\n newError.addTelemetryProperties({ stack2: stack });\n }\n }\n\n if (hasErrorInstanceId(innerError)) {\n newError.addTelemetryProperties({ innerErrorInstanceId: innerError.errorInstanceId });\n }\n\n return newError;\n}\n\n/** The same as wrapError, but also logs the innerError, including the wrapping error's instance id */\nexport function wrapErrorAndLog<T extends IFluidErrorBase>(\n innerError: unknown,\n newErrorFn: (message: string) => T,\n logger: ITelemetryLogger,\n) {\n const newError = wrapError(innerError, newErrorFn);\n const wrappedByErrorInstanceId = hasErrorInstanceId(newError)\n ? newError.errorInstanceId\n : undefined;\n\n logger.sendTelemetryEvent({\n eventName: \"WrapError\",\n wrappedByErrorInstanceId,\n }, innerError);\n\n return newError;\n}\n\n/**\n * Type guard to identify if a particular value (loosely) appears to be a tagged telemetry property\n */\nexport function isTaggedTelemetryPropertyValue(x: any): x is ITaggedTelemetryPropertyType {\n return (typeof(x?.value) !== \"object\" && typeof(x?.tag) === \"string\");\n}\n\n/**\n * Walk an object's enumerable properties to find those fit for telemetry.\n */\nfunction getValidTelemetryProps(obj: any, keysToOmit: Set<string>): ITelemetryProperties {\n const props: ITelemetryProperties = {};\n for (const key of Object.keys(obj)) {\n if (keysToOmit.has(key)) {\n continue;\n }\n const val = obj[key];\n switch (typeof val) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"undefined\":\n props[key] = val;\n break;\n default: {\n if (isTaggedTelemetryPropertyValue(val)) {\n props[key] = val;\n } else {\n // We don't support logging arbitrary objects\n props[key] = \"REDACTED (arbitrary object)\";\n }\n break;\n }\n }\n }\n return props;\n}\n\n/**\n * Base class for \"trusted\" errors we create, whose properties can generally be logged to telemetry safely.\n * All properties set on the object, or passed in (via the constructor or getTelemetryProperties),\n * will be logged in accordance with their tag, if present.\n *\n * PLEASE take care to avoid setting sensitive data on this object without proper tagging!\n */\nexport class LoggingError extends Error implements ILoggingError, Pick<IFluidErrorBase, \"errorInstanceId\"> {\n readonly errorInstanceId = uuid();\n\n /**\n * Create a new LoggingError\n * @param message - Error message to use for Error base class\n * @param props - telemetry props to include on the error for when it's logged\n * @param omitPropsFromLogging - properties by name to omit from telemetry props\n */\n constructor(\n message: string,\n props?: ITelemetryProperties,\n private readonly omitPropsFromLogging: Set<string> = new Set(),\n ) {\n super(message);\n\n // Don't log this list itself either\n omitPropsFromLogging.add(\"omitPropsFromLogging\");\n\n if (props) {\n this.addTelemetryProperties(props);\n }\n }\n\n /**\n * Add additional properties to be logged\n */\n public addTelemetryProperties(props: ITelemetryProperties) {\n copyProps(this, props);\n }\n\n /**\n * Get all properties fit to be logged to telemetry for this error\n */\n public getTelemetryProperties(): ITelemetryProperties {\n const taggableProps = getValidTelemetryProps(this, this.omitPropsFromLogging);\n // Include non-enumerable props inherited from Error that are not returned by getValidTelemetryProps\n return {\n ...taggableProps,\n stack: this.stack,\n message: this.message,\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errorLogging.js","sourceRoot":"","sources":["../src/errorLogging.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ILoggingError,\n ITaggedTelemetryPropertyType,\n ITelemetryLogger,\n ITelemetryProperties,\n} from \"@fluidframework/common-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport {\n hasErrorInstanceId,\n IFluidErrorBase,\n isFluidError,\n isValidLegacyError,\n} from \"./fluidErrorBase\";\n\n/** @returns true if value is an object but neither null nor an array */\nconst isRegularObject = (value: any): boolean => {\n return value !== null && !Array.isArray(value) && typeof value === \"object\";\n};\n\n/** Inspect the given error for common \"safe\" props and return them */\nexport function extractLogSafeErrorProperties(error: any, sanitizeStack: boolean) {\n const removeMessageFromStack = (stack: string, errorName?: string) => {\n if (!sanitizeStack) {\n return stack;\n }\n const stackFrames = stack.split(\"\\n\");\n stackFrames.shift(); // Remove \"[ErrorName]: [ErrorMessage]\"\n if (errorName !== undefined) {\n stackFrames.unshift(errorName); // Add \"[ErrorName]\"\n }\n return stackFrames.join(\"\\n\");\n };\n\n const message = (typeof error?.message === \"string\")\n ? error.message as string\n : String(error);\n\n const safeProps: { message: string; errorType?: string; stack?: string } = {\n message,\n };\n\n if (isRegularObject(error)) {\n const { errorType, stack, name } = error;\n\n if (typeof errorType === \"string\") {\n safeProps.errorType = errorType;\n }\n\n if (typeof stack === \"string\") {\n const errorName = (typeof name === \"string\") ? name : undefined;\n safeProps.stack = removeMessageFromStack(stack, errorName);\n }\n }\n\n return safeProps;\n}\n\n/** type guard for ILoggingError interface */\nexport const isILoggingError = (x: any): x is ILoggingError => typeof x?.getTelemetryProperties === \"function\";\n\n/** Copy props from source onto target, but do not overwrite an existing prop that matches */\nfunction copyProps(target: ITelemetryProperties | LoggingError, source: ITelemetryProperties) {\n for (const key of Object.keys(source)) {\n if (target[key] === undefined) {\n target[key] = source[key];\n }\n }\n}\n\n/** Metadata to annotate an error object when annotating or normalizing it */\nexport interface IFluidErrorAnnotations {\n /** Telemetry props to log with the error */\n props?: ITelemetryProperties;\n}\n\n/** For backwards compatibility with pre-fluidErrorCode valid errors */\nfunction patchWithErrorCode(\n legacyError: Omit<IFluidErrorBase, \"fluidErrorCode\">,\n): asserts legacyError is IFluidErrorBase {\n const patchMe: { -readonly [P in \"fluidErrorCode\"]?: IFluidErrorBase[P] } = legacyError as any;\n if (patchMe.fluidErrorCode === undefined) {\n patchMe.fluidErrorCode = \"<error predates fluidErrorCode>\";\n }\n}\n\n/**\n * Normalize the given error yielding a valid Fluid Error\n * @returns A valid Fluid Error with any provided annotations applied\n * @param error - The error to normalize\n * @param annotations - Annotations to apply to the normalized error\n */\nexport function normalizeError(\n error: unknown,\n annotations: IFluidErrorAnnotations = {},\n): IFluidErrorBase {\n // Back-compat, while IFluidErrorBase is rolled out\n if (isValidLegacyError(error)) {\n patchWithErrorCode(error);\n }\n\n if (isFluidError(error)) {\n // We can simply add the telemetry props to the error and return it\n error.addTelemetryProperties(annotations.props ?? {});\n return error;\n }\n\n // We have to construct a new Fluid Error, copying safe properties over\n const { message, stack } = extractLogSafeErrorProperties(error, false /* sanitizeStack */);\n const fluidError: IFluidErrorBase = new SimpleFluidError({\n errorType: \"genericError\", // Match Container/Driver generic error type\n fluidErrorCode: \"\",\n message,\n stack,\n });\n\n fluidError.addTelemetryProperties({\n ...annotations.props,\n untrustedOrigin: 1, // This will let us filter to errors not originated by our own code\n });\n\n if (typeof(error) !== \"object\") {\n // This is only interesting for non-objects\n fluidError.addTelemetryProperties({ typeofError: typeof(error) });\n }\n return fluidError;\n}\n\nlet stackPopulatedOnCreation: boolean | undefined;\n\n/**\n * The purpose of this function is to provide ability to capture stack context quickly.\n * Accessing new Error().stack is slow, and the slowest part is accessing stack property itself.\n * There are scenarios where we generate error with stack, but error is handled in most cases and\n * stack property is not accessed.\n * For such cases it's better to not read stack property right away, but rather delay it until / if it's needed\n * Some browsers will populate stack right away, others require throwing Error, so we do auto-detection on the fly.\n * @returns Error object that has stack populated.\n */\n export function generateErrorWithStack(): Error {\n const err = new Error(\"<<generated stack>>\");\n\n if (stackPopulatedOnCreation === undefined) {\n stackPopulatedOnCreation = (err.stack !== undefined);\n }\n\n if (stackPopulatedOnCreation) {\n return err;\n }\n\n try {\n throw err;\n } catch (e) {\n return e as Error;\n }\n}\n\nexport function generateStack(): string | undefined {\n return generateErrorWithStack().stack;\n}\n\n/**\n * Create a new error, wrapping and caused by the given unknown error.\n * Copies the inner error's message and stack over but otherwise uses newErrorFn to define the error.\n * The inner error's instance id will also be logged for telemetry analysis.\n * @param innerError - An error from untrusted/unknown origins\n * @param newErrorFn - callback that will create a new error given the original error's message\n * @returns A new error object \"wrapping\" the given error\n */\n export function wrapError<T extends IFluidErrorBase>(\n innerError: unknown,\n newErrorFn: (message: string) => T,\n): T {\n const {\n message,\n stack,\n } = extractLogSafeErrorProperties(innerError, false /* sanitizeStack */);\n\n const newError = newErrorFn(message);\n\n if (stack !== undefined) {\n overwriteStack(newError, stack);\n }\n\n if (hasErrorInstanceId(innerError)) {\n newError.addTelemetryProperties({ innerErrorInstanceId: innerError.errorInstanceId });\n }\n\n return newError;\n}\n\n/** The same as wrapError, but also logs the innerError, including the wrapping error's instance id */\nexport function wrapErrorAndLog<T extends IFluidErrorBase>(\n innerError: unknown,\n newErrorFn: (message: string) => T,\n logger: ITelemetryLogger,\n) {\n const newError = wrapError(innerError, newErrorFn);\n const wrappedByErrorInstanceId = hasErrorInstanceId(newError)\n ? newError.errorInstanceId\n : undefined;\n\n logger.sendTelemetryEvent({\n eventName: \"WrapError\",\n wrappedByErrorInstanceId,\n }, innerError);\n\n return newError;\n}\n\nfunction overwriteStack(error: IFluidErrorBase, stack: string) {\n // supposedly setting stack on an Error can throw.\n try {\n Object.assign(error, { stack });\n } catch (errorSettingStack) {\n error.addTelemetryProperties({ stack2: stack });\n }\n}\n\n/**\n * Type guard to identify if a particular value (loosely) appears to be a tagged telemetry property\n */\nexport function isTaggedTelemetryPropertyValue(x: any): x is ITaggedTelemetryPropertyType {\n return (typeof(x?.value) !== \"object\" && typeof(x?.tag) === \"string\");\n}\n\n/**\n * Walk an object's enumerable properties to find those fit for telemetry.\n */\nfunction getValidTelemetryProps(obj: any, keysToOmit: Set<string>): ITelemetryProperties {\n const props: ITelemetryProperties = {};\n for (const key of Object.keys(obj)) {\n if (keysToOmit.has(key)) {\n continue;\n }\n const val = obj[key];\n switch (typeof val) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"undefined\":\n props[key] = val;\n break;\n default: {\n if (isTaggedTelemetryPropertyValue(val)) {\n props[key] = val;\n } else {\n // We don't support logging arbitrary objects\n props[key] = \"REDACTED (arbitrary object)\";\n }\n break;\n }\n }\n }\n return props;\n}\n\n/**\n * Base class for \"trusted\" errors we create, whose properties can generally be logged to telemetry safely.\n * All properties set on the object, or passed in (via the constructor or getTelemetryProperties),\n * will be logged in accordance with their tag, if present.\n *\n * PLEASE take care to avoid setting sensitive data on this object without proper tagging!\n */\nexport class LoggingError extends Error implements ILoggingError, Pick<IFluidErrorBase, \"errorInstanceId\"> {\n readonly errorInstanceId = uuid();\n\n /**\n * Create a new LoggingError\n * @param message - Error message to use for Error base class\n * @param props - telemetry props to include on the error for when it's logged\n * @param omitPropsFromLogging - properties by name to omit from telemetry props\n */\n constructor(\n message: string,\n props?: ITelemetryProperties,\n private readonly omitPropsFromLogging: Set<string> = new Set(),\n ) {\n super(message);\n\n // Don't log this list itself either\n omitPropsFromLogging.add(\"omitPropsFromLogging\");\n\n if (props) {\n this.addTelemetryProperties(props);\n }\n }\n\n /**\n * Add additional properties to be logged\n */\n public addTelemetryProperties(props: ITelemetryProperties) {\n copyProps(this, props);\n }\n\n /**\n * Get all properties fit to be logged to telemetry for this error\n */\n public getTelemetryProperties(): ITelemetryProperties {\n const taggableProps = getValidTelemetryProps(this, this.omitPropsFromLogging);\n // Include non-enumerable props inherited from Error that are not returned by getValidTelemetryProps\n return {\n ...taggableProps,\n stack: this.stack,\n message: this.message,\n };\n }\n}\n\n/** Simple implementation of IFluidErrorBase, extending LoggingError */\nclass SimpleFluidError extends LoggingError implements IFluidErrorBase {\n readonly errorType: string;\n readonly fluidErrorCode: string;\n\n constructor(\n errorProps: Omit<IFluidErrorBase,\n | \"getTelemetryProperties\"\n | \"addTelemetryProperties\"\n | \"errorInstanceId\"\n | \"name\">,\n ) {\n super(errorProps.message);\n this.errorType = errorProps.errorType;\n this.fluidErrorCode = errorProps.fluidErrorCode;\n if (errorProps.stack !== undefined) {\n overwriteStack(this, errorProps.stack);\n }\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export * from "./logger";
|
|
|
11
11
|
export * from "./mockLogger";
|
|
12
12
|
export * from "./thresholdCounter";
|
|
13
13
|
export * from "./utils";
|
|
14
|
+
export { MonitoringContext, IConfigProviderBase, sessionStorageConfigProvider, mixinMonitoringContext, IConfigProvider, ConfigTypes, loggerToMonitoringContext, } from "./config";
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iCAAiC,CAAC;AAChD,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iCAAiC,CAAC;AAChD,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC;AACxB,OAAO,EACH,iBAAiB,EACjB,mBAAmB,EACnB,4BAA4B,EAC5B,sBAAsB,EACtB,eAAe,EACf,WAAW,EACX,yBAAyB,GAC5B,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
10
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.loggerToMonitoringContext = exports.mixinMonitoringContext = exports.sessionStorageConfigProvider = void 0;
|
|
13
14
|
/*!
|
|
14
15
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
15
16
|
* Licensed under the MIT License.
|
|
@@ -23,4 +24,8 @@ __exportStar(require("./logger"), exports);
|
|
|
23
24
|
__exportStar(require("./mockLogger"), exports);
|
|
24
25
|
__exportStar(require("./thresholdCounter"), exports);
|
|
25
26
|
__exportStar(require("./utils"), exports);
|
|
27
|
+
var config_1 = require("./config");
|
|
28
|
+
Object.defineProperty(exports, "sessionStorageConfigProvider", { enumerable: true, get: function () { return config_1.sessionStorageConfigProvider; } });
|
|
29
|
+
Object.defineProperty(exports, "mixinMonitoringContext", { enumerable: true, get: function () { return config_1.mixinMonitoringContext; } });
|
|
30
|
+
Object.defineProperty(exports, "loggerToMonitoringContext", { enumerable: true, get: function () { return config_1.loggerToMonitoringContext; } });
|
|
26
31
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA;;;GAGG;AACH,gDAA8B;AAC9B,iDAA+B;AAC/B,kEAAgD;AAChD,2CAAyB;AACzB,mDAAiC;AACjC,2CAAyB;AACzB,+CAA6B;AAC7B,qDAAmC;AACnC,0CAAwB;AACxB,mCAQkB;AALd,sHAAA,4BAA4B,OAAA;AAC5B,gHAAA,sBAAsB,OAAA;AAGtB,mHAAA,yBAAyB,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nexport * from \"./debugLogger\";\nexport * from \"./errorLogging\";\nexport * from \"./eventEmitterWithErrorHandling\";\nexport * from \"./events\";\nexport * from \"./fluidErrorBase\";\nexport * from \"./logger\";\nexport * from \"./mockLogger\";\nexport * from \"./thresholdCounter\";\nexport * from \"./utils\";\nexport {\n MonitoringContext,\n IConfigProviderBase,\n sessionStorageConfigProvider,\n mixinMonitoringContext,\n IConfigProvider,\n ConfigTypes,\n loggerToMonitoringContext,\n} from \"./config\";\n"]}
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,0BAA0B,EAC1B,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC5B,sBAAsB,EACzB,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|