@fluidframework/telemetry-utils 2.0.0-internal.4.3.0 → 2.0.0-internal.5.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 (53) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/config.d.ts +6 -5
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js.map +1 -1
  5. package/dist/errorLogging.d.ts +3 -3
  6. package/dist/errorLogging.d.ts.map +1 -1
  7. package/dist/errorLogging.js.map +1 -1
  8. package/dist/events.d.ts +3 -3
  9. package/dist/events.d.ts.map +1 -1
  10. package/dist/events.js.map +1 -1
  11. package/dist/logger.d.ts +7 -7
  12. package/dist/logger.d.ts.map +1 -1
  13. package/dist/logger.js.map +1 -1
  14. package/dist/mockLogger.d.ts +13 -9
  15. package/dist/mockLogger.d.ts.map +1 -1
  16. package/dist/mockLogger.js +45 -19
  17. package/dist/mockLogger.js.map +1 -1
  18. package/dist/sampledTelemetryHelper.d.ts +3 -2
  19. package/dist/sampledTelemetryHelper.d.ts.map +1 -1
  20. package/dist/sampledTelemetryHelper.js.map +1 -1
  21. package/dist/thresholdCounter.d.ts +2 -2
  22. package/dist/thresholdCounter.d.ts.map +1 -1
  23. package/dist/thresholdCounter.js.map +1 -1
  24. package/lib/config.d.ts +6 -5
  25. package/lib/config.d.ts.map +1 -1
  26. package/lib/config.js.map +1 -1
  27. package/lib/errorLogging.d.ts +3 -3
  28. package/lib/errorLogging.d.ts.map +1 -1
  29. package/lib/errorLogging.js.map +1 -1
  30. package/lib/events.d.ts +3 -3
  31. package/lib/events.d.ts.map +1 -1
  32. package/lib/events.js.map +1 -1
  33. package/lib/logger.d.ts +7 -7
  34. package/lib/logger.d.ts.map +1 -1
  35. package/lib/logger.js.map +1 -1
  36. package/lib/mockLogger.d.ts +13 -9
  37. package/lib/mockLogger.d.ts.map +1 -1
  38. package/lib/mockLogger.js +45 -19
  39. package/lib/mockLogger.js.map +1 -1
  40. package/lib/sampledTelemetryHelper.d.ts +3 -2
  41. package/lib/sampledTelemetryHelper.d.ts.map +1 -1
  42. package/lib/sampledTelemetryHelper.js.map +1 -1
  43. package/lib/thresholdCounter.d.ts +2 -2
  44. package/lib/thresholdCounter.d.ts.map +1 -1
  45. package/lib/thresholdCounter.js.map +1 -1
  46. package/package.json +2 -2
  47. package/src/config.ts +6 -5
  48. package/src/errorLogging.ts +6 -3
  49. package/src/events.ts +3 -3
  50. package/src/logger.ts +6 -7
  51. package/src/mockLogger.ts +76 -20
  52. package/src/sampledTelemetryHelper.ts +2 -2
  53. package/src/thresholdCounter.ts +2 -2
package/src/mockLogger.ts CHANGED
@@ -3,14 +3,16 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryLogger, ITelemetryBaseEvent } from "@fluidframework/common-definitions";
6
+ import { ITelemetryBaseEvent } from "@fluidframework/common-definitions";
7
+ import { assert } from "@fluidframework/common-utils";
7
8
  import { TelemetryLogger } from "./logger";
9
+ import { ITelemetryLoggerExt } from "./telemetryTypes";
8
10
 
9
11
  /**
10
12
  * The MockLogger records events sent to it, and then can walk back over those events
11
13
  * searching for a set of expected events to match against the logged events.
12
14
  */
13
- export class MockLogger extends TelemetryLogger implements ITelemetryLogger {
15
+ export class MockLogger extends TelemetryLogger implements ITelemetryLoggerExt {
14
16
  events: ITelemetryBaseEvent[] = [];
15
17
 
16
18
  constructor() {
@@ -29,20 +31,31 @@ export class MockLogger extends TelemetryLogger implements ITelemetryLogger {
29
31
  * Search events logged since the last time matchEvents was called, looking for the given expected
30
32
  * events in order.
31
33
  * @param expectedEvents - events in order that are expected to appear in the recorded log.
34
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
32
35
  * These event objects may be subsets of the logged events.
33
36
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
34
37
  */
35
- matchEvents(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean {
36
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
38
+ matchEvents(
39
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
40
+ inlineDetailsProp: boolean = false,
41
+ ): boolean {
42
+ const matchedExpectedEventCount = this.getMatchedEventsCount(
43
+ expectedEvents,
44
+ inlineDetailsProp,
45
+ );
37
46
  // How many expected events were left over? Hopefully none.
38
47
  const unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;
39
48
  return unmatchedExpectedEventCount === 0;
40
49
  }
41
50
 
42
51
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
43
- assertMatch(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
52
+ assertMatch(
53
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
54
+ message?: string,
55
+ inlineDetailsProp: boolean = false,
56
+ ) {
44
57
  const actualEvents = this.events;
45
- if (!this.matchEvents(expectedEvents)) {
58
+ if (!this.matchEvents(expectedEvents, inlineDetailsProp)) {
46
59
  throw new Error(`${message}
47
60
  expected:
48
61
  ${JSON.stringify(expectedEvents)}
@@ -56,19 +69,30 @@ ${JSON.stringify(actualEvents)}`);
56
69
  * Search events logged since the last time matchEvents was called, looking for any of the given
57
70
  * expected events.
58
71
  * @param expectedEvents - events that are expected to appear in the recorded log.
72
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
59
73
  * These event objects may be subsets of the logged events.
60
74
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
61
75
  * @returns if any of the expected events is found.
62
76
  */
63
- matchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean {
64
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
77
+ matchAnyEvent(
78
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
79
+ inlineDetailsProp: boolean = false,
80
+ ): boolean {
81
+ const matchedExpectedEventCount = this.getMatchedEventsCount(
82
+ expectedEvents,
83
+ inlineDetailsProp,
84
+ );
65
85
  return matchedExpectedEventCount > 0;
66
86
  }
67
87
 
68
88
  /** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */
69
- assertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
89
+ assertMatchAny(
90
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
91
+ message?: string,
92
+ inlineDetailsProp: boolean = false,
93
+ ) {
70
94
  const actualEvents = this.events;
71
- if (!this.matchAnyEvent(expectedEvents)) {
95
+ if (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {
72
96
  throw new Error(`${message}
73
97
  expected:
74
98
  ${JSON.stringify(expectedEvents)}
@@ -82,17 +106,28 @@ ${JSON.stringify(actualEvents)}`);
82
106
  * Search events logged since the last time matchEvents was called, looking only for the given expected
83
107
  * events in order.
84
108
  * @param expectedEvents - events in order that are expected to be the only events in the recorded log.
109
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
85
110
  * These event objects may be subsets of the logged events.
86
111
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
87
112
  */
88
- matchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean {
89
- return expectedEvents.length === this.events.length && this.matchEvents(expectedEvents);
113
+ matchEventStrict(
114
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
115
+ inlineDetailsProp: boolean = false,
116
+ ): boolean {
117
+ return (
118
+ expectedEvents.length === this.events.length &&
119
+ this.matchEvents(expectedEvents, inlineDetailsProp)
120
+ );
90
121
  }
91
122
 
92
123
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
93
- assertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
124
+ assertMatchStrict(
125
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
126
+ message?: string,
127
+ inlineDetailsProp: boolean = false,
128
+ ) {
94
129
  const actualEvents = this.events;
95
- if (!this.matchEventStrict(expectedEvents)) {
130
+ if (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {
96
131
  throw new Error(`${message}
97
132
  expected:
98
133
  ${JSON.stringify(expectedEvents)}
@@ -103,9 +138,13 @@ ${JSON.stringify(actualEvents)}`);
103
138
  }
104
139
 
105
140
  /** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */
106
- assertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
141
+ assertMatchNone(
142
+ disallowedEvents: Omit<ITelemetryBaseEvent, "category">[],
143
+ message?: string,
144
+ inlineDetailsProp: boolean = false,
145
+ ) {
107
146
  const actualEvents = this.events;
108
- if (this.matchAnyEvent(disallowedEvents)) {
147
+ if (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {
109
148
  throw new Error(`${message}
110
149
  disallowed events:
111
150
  ${JSON.stringify(disallowedEvents)}
@@ -115,12 +154,15 @@ ${JSON.stringify(actualEvents)}`);
115
154
  }
116
155
  }
117
156
 
118
- private getMatchedEventsCount(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): number {
157
+ private getMatchedEventsCount(
158
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
159
+ inlineDetailsProp: boolean,
160
+ ): number {
119
161
  let iExpectedEvent = 0;
120
162
  this.events.forEach((event) => {
121
163
  if (
122
164
  iExpectedEvent < expectedEvents.length &&
123
- MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent])
165
+ MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)
124
166
  ) {
125
167
  // We found the next expected event; increment
126
168
  ++iExpectedEvent;
@@ -140,8 +182,22 @@ ${JSON.stringify(actualEvents)}`);
140
182
  private static eventsMatch(
141
183
  actual: ITelemetryBaseEvent,
142
184
  expected: Omit<ITelemetryBaseEvent, "category">,
185
+ inlineDetailsProp: boolean,
143
186
  ): boolean {
144
- const masked = { ...actual, ...expected };
145
- return JSON.stringify(masked) === JSON.stringify(actual);
187
+ const { details, ...actualForMatching } = actual;
188
+ let detailsExpanded = { details };
189
+ // "details" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.
190
+ // Some of the properties in the expected event may be inside "details". So, if inlineDetailsProp is true,
191
+ // extract the properties from "details" in the actual event and inline them in the actual event.
192
+ if (inlineDetailsProp && details !== undefined) {
193
+ assert(
194
+ typeof details === "string",
195
+ 0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,
196
+ );
197
+ detailsExpanded = JSON.parse(details);
198
+ }
199
+ const actualExpanded: ITelemetryBaseEvent = { ...actualForMatching, ...detailsExpanded };
200
+ const masked = { ...actualExpanded, ...expected };
201
+ return JSON.stringify(masked) === JSON.stringify(actualExpanded);
146
202
  }
147
203
  }
@@ -6,11 +6,11 @@
6
6
  import {
7
7
  IDisposable,
8
8
  ITelemetryGenericEvent,
9
- ITelemetryLogger,
10
9
  ITelemetryPerformanceEvent,
11
10
  ITelemetryProperties,
12
11
  } from "@fluidframework/common-definitions";
13
12
  import { performance } from "@fluidframework/common-utils";
13
+ import { ITelemetryLoggerExt } from "./telemetryTypes";
14
14
 
15
15
  interface Measurements {
16
16
  // The names of the properties in this interface are the ones that will get stamped in the
@@ -75,7 +75,7 @@ export class SampledTelemetryHelper implements IDisposable {
75
75
  */
76
76
  public constructor(
77
77
  private readonly eventBase: ITelemetryGenericEvent,
78
- private readonly logger: ITelemetryLogger,
78
+ private readonly logger: ITelemetryLoggerExt,
79
79
  private readonly sampleThreshold: number,
80
80
  private readonly includeAggregateMetrics: boolean = false,
81
81
  private readonly perBucketProperties = new Map<string, ITelemetryProperties>(),
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryLogger } from "@fluidframework/common-definitions";
6
+ import { ITelemetryLoggerExt } from "./telemetryTypes";
7
7
 
8
8
  /**
9
9
  * Utility counter which will send event only if the provided value
@@ -12,7 +12,7 @@ import { ITelemetryLogger } from "@fluidframework/common-definitions";
12
12
  export class ThresholdCounter {
13
13
  public constructor(
14
14
  private readonly threshold: number,
15
- private readonly logger: ITelemetryLogger,
15
+ private readonly logger: ITelemetryLoggerExt,
16
16
  private thresholdMultiple = threshold,
17
17
  ) {}
18
18