@fluidframework/telemetry-utils 2.0.0-internal.5.3.2 → 2.0.0-internal.6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/config.d.ts +2 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +27 -34
  5. package/dist/config.js.map +1 -1
  6. package/dist/errorLogging.js +16 -10
  7. package/dist/errorLogging.js.map +1 -1
  8. package/dist/fluidErrorBase.js +7 -7
  9. package/dist/fluidErrorBase.js.map +1 -1
  10. package/dist/index.d.ts +2 -3
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +9 -9
  13. package/dist/index.js.map +1 -1
  14. package/dist/logger.d.ts +47 -48
  15. package/dist/logger.d.ts.map +1 -1
  16. package/dist/logger.js +111 -117
  17. package/dist/logger.js.map +1 -1
  18. package/dist/mockLogger.d.ts +3 -5
  19. package/dist/mockLogger.d.ts.map +1 -1
  20. package/dist/mockLogger.js +27 -19
  21. package/dist/mockLogger.js.map +1 -1
  22. package/dist/sampledTelemetryHelper.js +8 -5
  23. package/dist/sampledTelemetryHelper.js.map +1 -1
  24. package/dist/utils.js +1 -1
  25. package/dist/utils.js.map +1 -1
  26. package/lib/config.d.ts +2 -0
  27. package/lib/config.d.ts.map +1 -1
  28. package/lib/config.js +26 -34
  29. package/lib/config.js.map +1 -1
  30. package/lib/errorLogging.js +16 -10
  31. package/lib/errorLogging.js.map +1 -1
  32. package/lib/fluidErrorBase.js +7 -7
  33. package/lib/fluidErrorBase.js.map +1 -1
  34. package/lib/index.d.ts +2 -3
  35. package/lib/index.d.ts.map +1 -1
  36. package/lib/index.js +2 -3
  37. package/lib/index.js.map +1 -1
  38. package/lib/logger.d.ts +47 -48
  39. package/lib/logger.d.ts.map +1 -1
  40. package/lib/logger.js +104 -113
  41. package/lib/logger.js.map +1 -1
  42. package/lib/mockLogger.d.ts +3 -5
  43. package/lib/mockLogger.d.ts.map +1 -1
  44. package/lib/mockLogger.js +28 -20
  45. package/lib/mockLogger.js.map +1 -1
  46. package/lib/sampledTelemetryHelper.js +8 -5
  47. package/lib/sampledTelemetryHelper.js.map +1 -1
  48. package/lib/utils.js +1 -1
  49. package/lib/utils.js.map +1 -1
  50. package/package.json +41 -8
  51. package/src/config.ts +11 -6
  52. package/src/index.ts +8 -7
  53. package/src/logger.ts +125 -94
  54. package/src/mockLogger.ts +37 -13
  55. package/dist/debugLogger.d.ts +0 -39
  56. package/dist/debugLogger.d.ts.map +0 -1
  57. package/dist/debugLogger.js +0 -112
  58. package/dist/debugLogger.js.map +0 -1
  59. package/lib/debugLogger.d.ts +0 -39
  60. package/lib/debugLogger.d.ts.map +0 -1
  61. package/lib/debugLogger.js +0 -108
  62. package/lib/debugLogger.js.map +0 -1
  63. package/src/debugLogger.ts +0 -143
package/src/logger.ts CHANGED
@@ -59,31 +59,34 @@ export interface ITelemetryLoggerPropertyBags {
59
59
  error?: ITelemetryLoggerPropertyBag;
60
60
  }
61
61
 
62
+ /**
63
+ * Attempts to parse number from string.
64
+ * If fails,returns original string.
65
+ * Used to make telemetry data typed (and support math operations, like comparison),
66
+ * in places where we do expect numbers (like contentsize/duration property in http header)
67
+ */
68
+ export function numberFromString(str: string | null | undefined): string | number | undefined {
69
+ if (str === undefined || str === null) {
70
+ return undefined;
71
+ }
72
+ const num = Number(str);
73
+ return Number.isNaN(num) ? str : num;
74
+ }
75
+
76
+ export function formatTick(tick: number): number {
77
+ return Math.floor(tick);
78
+ }
79
+
80
+ export const eventNamespaceSeparator = ":" as const;
81
+
62
82
  /**
63
83
  * TelemetryLogger class contains various helper telemetry methods,
64
84
  * encoding in one place schemas for various types of Fluid telemetry events.
65
85
  * Creates sub-logger that appends properties to all events
86
+ *
66
87
  */
67
88
  export abstract class TelemetryLogger implements ITelemetryLoggerExt {
68
- public static readonly eventNamespaceSeparator = ":";
69
-
70
- public static formatTick(tick: number): number {
71
- return Math.floor(tick);
72
- }
73
-
74
- /**
75
- * Attempts to parse number from string.
76
- * If fails,returns original string.
77
- * Used to make telemetry data typed (and support math operations, like comparison),
78
- * in places where we do expect numbers (like contentsize/duration property in http header)
79
- */
80
- public static numberFromString(str: string | null | undefined): string | number | undefined {
81
- if (str === undefined || str === null) {
82
- return undefined;
83
- }
84
- const num = Number(str);
85
- return Number.isNaN(num) ? str : num;
86
- }
89
+ public static readonly eventNamespaceSeparator = eventNamespaceSeparator;
87
90
 
88
91
  public static sanitizePkgName(name: string) {
89
92
  return name.replace("@", "").replace("/", "-");
@@ -163,7 +166,7 @@ export abstract class TelemetryLogger implements ITelemetryLoggerExt {
163
166
 
164
167
  // Will include Nan & Infinity, but probably we do not care
165
168
  if (typeof newEvent.duration === "number") {
166
- newEvent.duration = TelemetryLogger.formatTick(newEvent.duration);
169
+ newEvent.duration = formatTick(newEvent.duration);
167
170
  }
168
171
 
169
172
  this.send(newEvent);
@@ -211,6 +214,14 @@ export abstract class TelemetryLogger implements ITelemetryLoggerExt {
211
214
  if (this.namespace !== undefined) {
212
215
  newEvent.eventName = `${this.namespace}${TelemetryLogger.eventNamespaceSeparator}${newEvent.eventName}`;
213
216
  }
217
+ return this.extendProperties(newEvent, includeErrorProps);
218
+ }
219
+
220
+ private extendProperties<T extends ITelemetryLoggerPropertyBag = ITelemetryLoggerPropertyBag>(
221
+ toExtend: T,
222
+ includeErrorProps: boolean,
223
+ ) {
224
+ const eventLike: ITelemetryLoggerPropertyBag = toExtend;
214
225
  if (this.properties) {
215
226
  const properties: (undefined | ITelemetryLoggerPropertyBag)[] = [];
216
227
  properties.push(this.properties.all);
@@ -220,7 +231,7 @@ export abstract class TelemetryLogger implements ITelemetryLoggerExt {
220
231
  for (const props of properties) {
221
232
  if (props !== undefined) {
222
233
  for (const key of Object.keys(props)) {
223
- if (event[key] !== undefined) {
234
+ if (eventLike[key] !== undefined) {
224
235
  continue;
225
236
  }
226
237
  const getterOrValue = props[key];
@@ -228,13 +239,13 @@ export abstract class TelemetryLogger implements ITelemetryLoggerExt {
228
239
  const value =
229
240
  typeof getterOrValue === "function" ? getterOrValue() : getterOrValue;
230
241
  if (value !== undefined) {
231
- newEvent[key] = value;
242
+ eventLike[key] = value;
232
243
  }
233
244
  }
234
245
  }
235
246
  }
236
247
  }
237
- return newEvent;
248
+ return toExtend;
238
249
  }
239
250
  }
240
251
 
@@ -284,6 +295,21 @@ export class TaggedLoggerAdapter implements ITelemetryBaseLogger {
284
295
  }
285
296
  }
286
297
 
298
+ /**
299
+ * Create a child logger based on the provided props object
300
+ * @param props - logger is the base logger the child will log to after it's processing, namespace will be prefixed to all event names, properties are default properties that will be applied events.
301
+ *
302
+ * @remarks
303
+ * Passing in no props object (i.e. undefined) will return a logger that is effectively a no-op.
304
+ */
305
+ export function createChildLogger(props?: {
306
+ logger?: ITelemetryBaseLogger;
307
+ namespace?: string;
308
+ properties?: ITelemetryLoggerPropertyBags;
309
+ }): ITelemetryLoggerExt {
310
+ return ChildLogger.create(props?.logger, props?.namespace, props?.properties);
311
+ }
312
+
287
313
  /**
288
314
  * ChildLogger class contains various helper telemetry methods,
289
315
  * encoding in one place schemas for various types of Fluid telemetry events.
@@ -330,14 +356,19 @@ export class ChildLogger extends TelemetryLogger {
330
356
  ? baseLogger.namespace
331
357
  : `${baseLogger.namespace}${TelemetryLogger.eventNamespaceSeparator}${namespace}`;
332
358
 
333
- return new ChildLogger(baseLogger.baseLogger, combinedNamespace, combinedProperties);
359
+ const child = new ChildLogger(
360
+ baseLogger.baseLogger,
361
+ combinedNamespace,
362
+ combinedProperties,
363
+ );
364
+
365
+ if (!loggerIsMonitoringContext(child) && loggerIsMonitoringContext(baseLogger)) {
366
+ mixinMonitoringContext(child, baseLogger.config);
367
+ }
368
+ return child;
334
369
  }
335
370
 
336
- return new ChildLogger(
337
- baseLogger ? baseLogger : new BaseTelemetryNullLogger(),
338
- namespace,
339
- properties,
340
- );
371
+ return new ChildLogger(baseLogger ? baseLogger : { send() {} }, namespace, properties);
341
372
  }
342
373
 
343
374
  private constructor(
@@ -363,20 +394,59 @@ export class ChildLogger extends TelemetryLogger {
363
394
  }
364
395
  }
365
396
 
397
+ /**
398
+ * Create a logger which logs to multiple other loggers based on the provided props object
399
+ * @param props - loggers are the base loggers that will logged to after it's processing, namespace will be prefixed to all event names, properties are default properties that will be applied events.
400
+ * tryInheritProperties will attempted to copy those loggers properties to this loggers if they are of a known type e.g. one from this package
401
+ */
402
+ export function createMultiSinkLogger(props: {
403
+ namespace?: string;
404
+ properties?: ITelemetryLoggerPropertyBags;
405
+ loggers?: (ITelemetryBaseLogger | undefined)[];
406
+ tryInheritProperties?: true;
407
+ }): ITelemetryLoggerExt {
408
+ return new MultiSinkLogger(
409
+ props.namespace,
410
+ props.properties,
411
+ props.loggers?.filter((l): l is ITelemetryBaseLogger => l !== undefined),
412
+ props.tryInheritProperties,
413
+ );
414
+ }
415
+
366
416
  /**
367
417
  * Multi-sink logger
368
418
  * Takes multiple ITelemetryBaseLogger objects (sinks) and logs all events into each sink
369
419
  */
370
420
  export class MultiSinkLogger extends TelemetryLogger {
371
- protected loggers: ITelemetryBaseLogger[] = [];
372
-
421
+ protected loggers: ITelemetryBaseLogger[];
373
422
  /**
374
423
  * Create multiple sink logger (i.e. logger that sends events to multiple sinks)
375
424
  * @param namespace - Telemetry event name prefix to add to all events
376
425
  * @param properties - Base properties to add to all events
426
+ * @param loggers - The list of loggers to use as sinks
427
+ * @param tryInheritProperties - Will attempted to copy those loggers properties to this loggers if they are of a known type e.g. one from this package
377
428
  */
378
- constructor(namespace?: string, properties?: ITelemetryLoggerPropertyBags) {
379
- super(namespace, properties);
429
+ constructor(
430
+ namespace?: string,
431
+ properties?: ITelemetryLoggerPropertyBags,
432
+ loggers: ITelemetryBaseLogger[] = [],
433
+ tryInheritProperties?: true,
434
+ ) {
435
+ let realProperties = properties !== undefined ? { ...properties } : undefined;
436
+ if (tryInheritProperties === true) {
437
+ const merge = (realProperties ??= {});
438
+ loggers
439
+ .filter((l): l is this => l instanceof TelemetryLogger)
440
+ .map((l) => l.properties ?? {})
441
+ .forEach((cv) => {
442
+ Object.keys(cv).forEach((k) => {
443
+ merge[k] = { ...cv[k], ...merge?.[k] };
444
+ });
445
+ });
446
+ }
447
+
448
+ super(namespace, realProperties);
449
+ this.loggers = loggers;
380
450
  }
381
451
 
382
452
  /**
@@ -558,67 +628,6 @@ export class PerformanceEvent {
558
628
  }
559
629
  }
560
630
 
561
- /**
562
- * Logger that is useful for UT
563
- * It can be used in places where logger instance is required, but events should be not send over.
564
- */
565
- export class TelemetryUTLogger implements ITelemetryLoggerExt {
566
- public send(event: ITelemetryBaseEvent): void {}
567
- public sendTelemetryEvent(event: ITelemetryGenericEvent, error?: any) {}
568
- public sendErrorEvent(event: ITelemetryErrorEvent, error?: any) {
569
- this.reportError("errorEvent in UT logger!", event, error);
570
- }
571
- public sendPerformanceEvent(event: ITelemetryPerformanceEvent, error?: any): void {}
572
- public logGenericError(eventName: string, error: any) {
573
- this.reportError(`genericError in UT logger!`, { eventName }, error);
574
- }
575
- public logException(event: ITelemetryErrorEvent, exception: any): void {
576
- this.reportError("exception in UT logger!", event, exception);
577
- }
578
- public debugAssert(condition: boolean, event?: ITelemetryErrorEvent): void {
579
- this.reportError("debugAssert in UT logger!");
580
- }
581
- public shipAssert(condition: boolean, event?: ITelemetryErrorEvent): void {
582
- this.reportError("shipAssert in UT logger!");
583
- }
584
-
585
- private reportError(message: string, event?: ITelemetryErrorEvent, err?: any) {
586
- const error = new Error(message);
587
- (error as any).error = error;
588
- (error as any).event = event;
589
- // report to console as exception can be eaten
590
- console.error(message);
591
- console.error(error);
592
- throw error;
593
- }
594
- }
595
-
596
- /**
597
- * Null logger
598
- * It can be used in places where logger instance is required, but events should be not send over.
599
- */
600
- export class BaseTelemetryNullLogger implements ITelemetryBaseLogger {
601
- /**
602
- * Send an event with the logger
603
- *
604
- * @param event - the event to send
605
- */
606
- public send(event: ITelemetryBaseEvent): void {
607
- return;
608
- }
609
- }
610
-
611
- /**
612
- * Null logger
613
- * It can be used in places where logger instance is required, but events should be not send over.
614
- */
615
- export class TelemetryNullLogger implements ITelemetryLoggerExt {
616
- public send(event: ITelemetryBaseEvent): void {}
617
- public sendTelemetryEvent(event: ITelemetryGenericEvent, error?: any): void {}
618
- public sendErrorEvent(event: ITelemetryErrorEvent, error?: any): void {}
619
- public sendPerformanceEvent(event: ITelemetryPerformanceEvent, error?: any): void {}
620
- }
621
-
622
631
  /**
623
632
  * Takes in an event object, and converts all of its values to a basePropertyType.
624
633
  * In the case of an invalid property type, the value will be converted to an error string.
@@ -676,3 +685,25 @@ function convertToBasePropertyTypeUntagged(
676
685
  return `INVALID PROPERTY (typed as ${typeof x})`;
677
686
  }
678
687
  }
688
+
689
+ export const tagData = <
690
+ T extends TelemetryDataTag,
691
+ V extends Record<string, TelemetryEventPropertyTypeExt>,
692
+ >(
693
+ tag: T,
694
+ values: V,
695
+ ) =>
696
+ (Object.entries(values) as [keyof V, V[keyof V]][])
697
+ .filter((e): e is [keyof V, Exclude<V[keyof V], undefined>] => e[1] !== undefined)
698
+ .reduce<{
699
+ [P in keyof V]:
700
+ | (V[P] extends undefined ? undefined : never)
701
+ | { value: Exclude<V[P], undefined>; tag: T };
702
+ }>((pv, cv) => {
703
+ pv[cv[0]] = { tag, value: cv[1] };
704
+ return pv;
705
+ }, {} as any);
706
+
707
+ export const tagCodeArtifacts = <T extends Record<string, TelemetryEventPropertyTypeExt>>(
708
+ values: T,
709
+ ) => tagData(TelemetryDataTag.CodeArtifact, values);
package/src/mockLogger.ts CHANGED
@@ -3,26 +3,26 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryBaseEvent } from "@fluidframework/core-interfaces";
6
+ import { ITelemetryBaseEvent, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
7
  import { assert } from "@fluidframework/common-utils";
8
- import { TelemetryLogger } from "./logger";
9
- import { ITelemetryLoggerExt } from "./telemetryTypes";
8
+ import { ITelemetryPropertiesExt } from "./telemetryTypes";
9
+ import { createChildLogger } from "./logger";
10
10
 
11
11
  /**
12
12
  * The MockLogger records events sent to it, and then can walk back over those events
13
13
  * searching for a set of expected events to match against the logged events.
14
14
  */
15
- export class MockLogger extends TelemetryLogger implements ITelemetryLoggerExt {
15
+ export class MockLogger implements ITelemetryBaseLogger {
16
16
  events: ITelemetryBaseEvent[] = [];
17
17
 
18
- constructor() {
19
- super();
20
- }
21
-
22
18
  clear() {
23
19
  this.events = [];
24
20
  }
25
21
 
22
+ toTelemetryLogger() {
23
+ return createChildLogger({ logger: this });
24
+ }
25
+
26
26
  send(event: ITelemetryBaseEvent): void {
27
27
  this.events.push(event);
28
28
  }
@@ -185,7 +185,6 @@ ${JSON.stringify(actualEvents)}`);
185
185
  inlineDetailsProp: boolean,
186
186
  ): boolean {
187
187
  const { details, ...actualForMatching } = actual;
188
- let detailsExpanded = { details };
189
188
  // "details" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.
190
189
  // Some of the properties in the expected event may be inside "details". So, if inlineDetailsProp is true,
191
190
  // extract the properties from "details" in the actual event and inline them in the actual event.
@@ -194,10 +193,35 @@ ${JSON.stringify(actualEvents)}`);
194
193
  typeof details === "string",
195
194
  0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,
196
195
  );
197
- detailsExpanded = JSON.parse(details);
196
+ const detailsExpanded = JSON.parse(details);
197
+ return matchObjects({ ...actualForMatching, ...detailsExpanded }, expected);
198
+ }
199
+ return matchObjects(actual, expected);
200
+ }
201
+ }
202
+
203
+ function matchObjects(actual: ITelemetryPropertiesExt, expected: ITelemetryPropertiesExt) {
204
+ for (const [expectedKey, expectedValue] of Object.entries(expected)) {
205
+ const actualValue = actual[expectedKey];
206
+ if (
207
+ !Array.isArray(expectedValue) &&
208
+ expectedValue !== null &&
209
+ typeof expectedValue === "object"
210
+ ) {
211
+ if (
212
+ Array.isArray(actualValue) ||
213
+ actualValue === null ||
214
+ typeof actualValue !== "object" ||
215
+ !matchObjects(
216
+ actualValue as ITelemetryPropertiesExt,
217
+ expectedValue as ITelemetryPropertiesExt,
218
+ )
219
+ ) {
220
+ return false;
221
+ }
222
+ } else if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {
223
+ return false;
198
224
  }
199
- const actualExpanded: ITelemetryBaseEvent = { ...actualForMatching, ...detailsExpanded };
200
- const masked = { ...actualExpanded, ...expected };
201
- return JSON.stringify(masked) === JSON.stringify(actualExpanded);
202
225
  }
226
+ return true;
203
227
  }
@@ -1,39 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ITelemetryBaseEvent, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
6
- import { IDebugger } from "debug";
7
- import { TelemetryLogger, ITelemetryLoggerPropertyBags } from "./logger";
8
- /**
9
- * Implementation of debug logger
10
- */
11
- export declare class DebugLogger extends TelemetryLogger {
12
- private readonly debug;
13
- private readonly debugErr;
14
- /**
15
- * Create debug logger - all events are output to debug npm library
16
- * @param namespace - Telemetry event name prefix to add to all events
17
- * @param properties - Base properties to add to all events
18
- * @param propertyGetters - Getters to add additional properties to all events
19
- */
20
- static create(namespace: string, properties?: ITelemetryLoggerPropertyBags): TelemetryLogger;
21
- /**
22
- * Mix in debug logger with another logger.
23
- * Returned logger will output events to both newly created debug logger, as well as base logger
24
- * @param namespace - Telemetry event name prefix to add to all events
25
- * @param properties - Base properties to add to all events
26
- * @param propertyGetters - Getters to add additional properties to all events
27
- * @param baseLogger - Base logger to output events (in addition to debug logger being created). Can be undefined.
28
- */
29
- static mixinDebugLogger(namespace: string, baseLogger?: ITelemetryBaseLogger, properties?: ITelemetryLoggerPropertyBags): TelemetryLogger;
30
- private static tryGetBaseLoggerProps;
31
- constructor(debug: IDebugger, debugErr: IDebugger, properties?: ITelemetryLoggerPropertyBags);
32
- /**
33
- * Send an event to debug loggers
34
- *
35
- * @param event - the event to send
36
- */
37
- send(event: ITelemetryBaseEvent): void;
38
- }
39
- //# sourceMappingURL=debugLogger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"debugLogger.d.ts","sourceRoot":"","sources":["../src/debugLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,oBAAoB,EAEpB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAA0B,SAAS,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EACN,eAAe,EAGf,4BAA4B,EAC5B,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,qBAAa,WAAY,SAAQ,eAAe;IAiE9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAjE1B;;;;;OAKG;WACW,MAAM,CACnB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,4BAA4B,GACvC,eAAe;IAqBlB;;;;;;;OAOG;WACW,gBAAgB,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,oBAAoB,EACjC,UAAU,CAAC,EAAE,4BAA4B,GACvC,eAAe;IAclB,OAAO,CAAC,MAAM,CAAC,qBAAqB;gBAQlB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,SAAS,EACpC,UAAU,CAAC,EAAE,4BAA4B;IAK1C;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;CA2C7C"}
@@ -1,112 +0,0 @@
1
- "use strict";
2
- /*!
3
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
- * Licensed under the MIT License.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.DebugLogger = void 0;
8
- const common_utils_1 = require("@fluidframework/common-utils");
9
- const debug_1 = require("debug");
10
- const logger_1 = require("./logger");
11
- /**
12
- * Implementation of debug logger
13
- */
14
- class DebugLogger extends logger_1.TelemetryLogger {
15
- constructor(debug, debugErr, properties) {
16
- super(undefined, properties);
17
- this.debug = debug;
18
- this.debugErr = debugErr;
19
- }
20
- /**
21
- * Create debug logger - all events are output to debug npm library
22
- * @param namespace - Telemetry event name prefix to add to all events
23
- * @param properties - Base properties to add to all events
24
- * @param propertyGetters - Getters to add additional properties to all events
25
- */
26
- static create(namespace, properties) {
27
- // Setup base logger upfront, such that host can disable it (if needed)
28
- const debug = (0, debug_1.debug)(namespace);
29
- // Create one for errors that is always enabled
30
- // It can be silenced by replacing console.error if the debug namespace is not enabled.
31
- const debugErr = (0, debug_1.debug)(namespace);
32
- debugErr.log = function () {
33
- if (debug.enabled) {
34
- // if the namespace is enabled, just use the default logger
35
- debug_1.debug.log(...arguments);
36
- }
37
- else {
38
- // other wise, use the console logger (which could be replaced and silenced)
39
- console.error(...arguments);
40
- }
41
- };
42
- debugErr.enabled = true;
43
- return new DebugLogger(debug, debugErr, properties);
44
- }
45
- /**
46
- * Mix in debug logger with another logger.
47
- * Returned logger will output events to both newly created debug logger, as well as base logger
48
- * @param namespace - Telemetry event name prefix to add to all events
49
- * @param properties - Base properties to add to all events
50
- * @param propertyGetters - Getters to add additional properties to all events
51
- * @param baseLogger - Base logger to output events (in addition to debug logger being created). Can be undefined.
52
- */
53
- static mixinDebugLogger(namespace, baseLogger, properties) {
54
- if (!baseLogger) {
55
- return DebugLogger.create(namespace, properties);
56
- }
57
- const multiSinkLogger = new logger_1.MultiSinkLogger(undefined, properties);
58
- multiSinkLogger.addLogger(DebugLogger.create(namespace, this.tryGetBaseLoggerProps(baseLogger)));
59
- multiSinkLogger.addLogger(logger_1.ChildLogger.create(baseLogger, namespace));
60
- return multiSinkLogger;
61
- }
62
- static tryGetBaseLoggerProps(baseLogger) {
63
- if (baseLogger instanceof logger_1.TelemetryLogger) {
64
- return baseLogger.properties;
65
- }
66
- return undefined;
67
- }
68
- /**
69
- * Send an event to debug loggers
70
- *
71
- * @param event - the event to send
72
- */
73
- send(event) {
74
- const newEvent = this.prepareEvent(event);
75
- const isError = newEvent.category === "error";
76
- let logger = isError ? this.debugErr : this.debug;
77
- // Use debug's coloring schema for base of the event
78
- const index = event.eventName.lastIndexOf(logger_1.TelemetryLogger.eventNamespaceSeparator);
79
- const name = event.eventName.substring(index + 1);
80
- if (index > 0) {
81
- logger = logger.extend(event.eventName.substring(0, index));
82
- }
83
- newEvent.eventName = undefined;
84
- let tick = "";
85
- tick = `tick=${logger_1.TelemetryLogger.formatTick(common_utils_1.performance.now())}`;
86
- // Extract stack to put it last, but also to avoid escaping '\n' in it by JSON.stringify below
87
- const stack = newEvent.stack ? newEvent.stack : "";
88
- newEvent.stack = undefined;
89
- // Watch out for circular references - they can come from two sources
90
- // 1) error object - we do not control it and should remove it and retry
91
- // 2) properties supplied by telemetry caller - that's a bug that should be addressed!
92
- let payload;
93
- try {
94
- payload = JSON.stringify(newEvent);
95
- }
96
- catch (error) {
97
- newEvent.error = undefined;
98
- payload = JSON.stringify(newEvent);
99
- }
100
- if (payload === "{}") {
101
- payload = "";
102
- }
103
- // Force errors out, to help with diagnostics
104
- if (isError) {
105
- logger.enabled = true;
106
- }
107
- // Print multi-line.
108
- logger(`${name} ${payload} ${tick} ${stack}`);
109
- }
110
- }
111
- exports.DebugLogger = DebugLogger;
112
- //# sourceMappingURL=debugLogger.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"debugLogger.js","sourceRoot":"","sources":["../src/debugLogger.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\tITelemetryBaseEvent,\n\tITelemetryBaseLogger,\n\tITelemetryProperties,\n} from \"@fluidframework/core-interfaces\";\nimport { performance } from \"@fluidframework/common-utils\";\nimport { debug as registerDebug, IDebugger } from \"debug\";\nimport {\n\tTelemetryLogger,\n\tMultiSinkLogger,\n\tChildLogger,\n\tITelemetryLoggerPropertyBags,\n} from \"./logger\";\n\n/**\n * Implementation of debug logger\n */\nexport class DebugLogger extends TelemetryLogger {\n\t/**\n\t * Create debug logger - all events are output to debug npm library\n\t * @param namespace - Telemetry event name prefix to add to all events\n\t * @param properties - Base properties to add to all events\n\t * @param propertyGetters - Getters to add additional properties to all events\n\t */\n\tpublic static create(\n\t\tnamespace: string,\n\t\tproperties?: ITelemetryLoggerPropertyBags,\n\t): TelemetryLogger {\n\t\t// Setup base logger upfront, such that host can disable it (if needed)\n\t\tconst debug = registerDebug(namespace);\n\n\t\t// Create one for errors that is always enabled\n\t\t// It can be silenced by replacing console.error if the debug namespace is not enabled.\n\t\tconst debugErr = registerDebug(namespace);\n\t\tdebugErr.log = function () {\n\t\t\tif (debug.enabled) {\n\t\t\t\t// if the namespace is enabled, just use the default logger\n\t\t\t\tregisterDebug.log(...arguments);\n\t\t\t} else {\n\t\t\t\t// other wise, use the console logger (which could be replaced and silenced)\n\t\t\t\tconsole.error(...arguments);\n\t\t\t}\n\t\t};\n\t\tdebugErr.enabled = true;\n\n\t\treturn new DebugLogger(debug, debugErr, properties);\n\t}\n\n\t/**\n\t * Mix in debug logger with another logger.\n\t * Returned logger will output events to both newly created debug logger, as well as base logger\n\t * @param namespace - Telemetry event name prefix to add to all events\n\t * @param properties - Base properties to add to all events\n\t * @param propertyGetters - Getters to add additional properties to all events\n\t * @param baseLogger - Base logger to output events (in addition to debug logger being created). Can be undefined.\n\t */\n\tpublic static mixinDebugLogger(\n\t\tnamespace: string,\n\t\tbaseLogger?: ITelemetryBaseLogger,\n\t\tproperties?: ITelemetryLoggerPropertyBags,\n\t): TelemetryLogger {\n\t\tif (!baseLogger) {\n\t\t\treturn DebugLogger.create(namespace, properties);\n\t\t}\n\n\t\tconst multiSinkLogger = new MultiSinkLogger(undefined, properties);\n\t\tmultiSinkLogger.addLogger(\n\t\t\tDebugLogger.create(namespace, this.tryGetBaseLoggerProps(baseLogger)),\n\t\t);\n\t\tmultiSinkLogger.addLogger(ChildLogger.create(baseLogger, namespace));\n\n\t\treturn multiSinkLogger;\n\t}\n\n\tprivate static tryGetBaseLoggerProps(baseLogger?: ITelemetryBaseLogger) {\n\t\tif (baseLogger instanceof TelemetryLogger) {\n\t\t\treturn (baseLogger as any as { properties: ITelemetryLoggerPropertyBags }).properties;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tconstructor(\n\t\tprivate readonly debug: IDebugger,\n\t\tprivate readonly debugErr: IDebugger,\n\t\tproperties?: ITelemetryLoggerPropertyBags,\n\t) {\n\t\tsuper(undefined, properties);\n\t}\n\n\t/**\n\t * Send an event to debug loggers\n\t *\n\t * @param event - the event to send\n\t */\n\tpublic send(event: ITelemetryBaseEvent): void {\n\t\tconst newEvent: ITelemetryProperties = this.prepareEvent(event);\n\t\tconst isError = newEvent.category === \"error\";\n\t\tlet logger = isError ? this.debugErr : this.debug;\n\n\t\t// Use debug's coloring schema for base of the event\n\t\tconst index = event.eventName.lastIndexOf(TelemetryLogger.eventNamespaceSeparator);\n\t\tconst name = event.eventName.substring(index + 1);\n\t\tif (index > 0) {\n\t\t\tlogger = logger.extend(event.eventName.substring(0, index));\n\t\t}\n\t\tnewEvent.eventName = undefined;\n\n\t\tlet tick = \"\";\n\t\ttick = `tick=${TelemetryLogger.formatTick(performance.now())}`;\n\n\t\t// Extract stack to put it last, but also to avoid escaping '\\n' in it by JSON.stringify below\n\t\tconst stack = newEvent.stack ? newEvent.stack : \"\";\n\t\tnewEvent.stack = undefined;\n\n\t\t// Watch out for circular references - they can come from two sources\n\t\t// 1) error object - we do not control it and should remove it and retry\n\t\t// 2) properties supplied by telemetry caller - that's a bug that should be addressed!\n\t\tlet payload: string;\n\t\ttry {\n\t\t\tpayload = JSON.stringify(newEvent);\n\t\t} catch (error) {\n\t\t\tnewEvent.error = undefined;\n\t\t\tpayload = JSON.stringify(newEvent);\n\t\t}\n\n\t\tif (payload === \"{}\") {\n\t\t\tpayload = \"\";\n\t\t}\n\n\t\t// Force errors out, to help with diagnostics\n\t\tif (isError) {\n\t\t\tlogger.enabled = true;\n\t\t}\n\n\t\t// Print multi-line.\n\t\tlogger(`${name} ${payload} ${tick} ${stack}`);\n\t}\n}\n"]}
@@ -1,39 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ITelemetryBaseEvent, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
6
- import { IDebugger } from "debug";
7
- import { TelemetryLogger, ITelemetryLoggerPropertyBags } from "./logger";
8
- /**
9
- * Implementation of debug logger
10
- */
11
- export declare class DebugLogger extends TelemetryLogger {
12
- private readonly debug;
13
- private readonly debugErr;
14
- /**
15
- * Create debug logger - all events are output to debug npm library
16
- * @param namespace - Telemetry event name prefix to add to all events
17
- * @param properties - Base properties to add to all events
18
- * @param propertyGetters - Getters to add additional properties to all events
19
- */
20
- static create(namespace: string, properties?: ITelemetryLoggerPropertyBags): TelemetryLogger;
21
- /**
22
- * Mix in debug logger with another logger.
23
- * Returned logger will output events to both newly created debug logger, as well as base logger
24
- * @param namespace - Telemetry event name prefix to add to all events
25
- * @param properties - Base properties to add to all events
26
- * @param propertyGetters - Getters to add additional properties to all events
27
- * @param baseLogger - Base logger to output events (in addition to debug logger being created). Can be undefined.
28
- */
29
- static mixinDebugLogger(namespace: string, baseLogger?: ITelemetryBaseLogger, properties?: ITelemetryLoggerPropertyBags): TelemetryLogger;
30
- private static tryGetBaseLoggerProps;
31
- constructor(debug: IDebugger, debugErr: IDebugger, properties?: ITelemetryLoggerPropertyBags);
32
- /**
33
- * Send an event to debug loggers
34
- *
35
- * @param event - the event to send
36
- */
37
- send(event: ITelemetryBaseEvent): void;
38
- }
39
- //# sourceMappingURL=debugLogger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"debugLogger.d.ts","sourceRoot":"","sources":["../src/debugLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,oBAAoB,EAEpB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAA0B,SAAS,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EACN,eAAe,EAGf,4BAA4B,EAC5B,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,qBAAa,WAAY,SAAQ,eAAe;IAiE9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAjE1B;;;;;OAKG;WACW,MAAM,CACnB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,4BAA4B,GACvC,eAAe;IAqBlB;;;;;;;OAOG;WACW,gBAAgB,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,oBAAoB,EACjC,UAAU,CAAC,EAAE,4BAA4B,GACvC,eAAe;IAclB,OAAO,CAAC,MAAM,CAAC,qBAAqB;gBAQlB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,SAAS,EACpC,UAAU,CAAC,EAAE,4BAA4B;IAK1C;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;CA2C7C"}