@fluidframework/telemetry-utils 2.0.0-rc.1.0.6 → 2.0.0-rc.2.0.1

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 (149) hide show
  1. package/{.mocharc.js → .mocharc.cjs} +1 -1
  2. package/CHANGELOG.md +23 -0
  3. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -2
  4. package/api-extractor-lint.json +1 -1
  5. package/api-extractor.json +1 -1
  6. package/api-report/telemetry-utils.api.md +10 -33
  7. package/dist/config.d.ts +2 -2
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +3 -3
  10. package/dist/config.js.map +1 -1
  11. package/dist/error.d.ts +2 -2
  12. package/dist/error.d.ts.map +1 -1
  13. package/dist/error.js +9 -9
  14. package/dist/error.js.map +1 -1
  15. package/dist/errorLogging.d.ts +4 -4
  16. package/dist/errorLogging.d.ts.map +1 -1
  17. package/dist/errorLogging.js +19 -60
  18. package/dist/errorLogging.js.map +1 -1
  19. package/dist/eventEmitterWithErrorHandling.d.ts +1 -1
  20. package/dist/eventEmitterWithErrorHandling.js +1 -1
  21. package/dist/eventEmitterWithErrorHandling.js.map +1 -1
  22. package/dist/events.d.ts +2 -3
  23. package/dist/events.d.ts.map +1 -1
  24. package/dist/events.js.map +1 -1
  25. package/dist/fluidErrorBase.d.ts +4 -3
  26. package/dist/fluidErrorBase.d.ts.map +1 -1
  27. package/dist/fluidErrorBase.js.map +1 -1
  28. package/dist/index.d.ts +12 -12
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +58 -60
  31. package/dist/index.js.map +1 -1
  32. package/dist/logger.d.ts +7 -23
  33. package/dist/logger.d.ts.map +1 -1
  34. package/dist/logger.js +12 -29
  35. package/dist/logger.js.map +1 -1
  36. package/dist/mockLogger.d.ts +1 -1
  37. package/dist/mockLogger.d.ts.map +1 -1
  38. package/dist/mockLogger.js +2 -2
  39. package/dist/mockLogger.js.map +1 -1
  40. package/dist/package.json +3 -0
  41. package/dist/sampledTelemetryHelper.d.ts +4 -4
  42. package/dist/sampledTelemetryHelper.d.ts.map +1 -1
  43. package/dist/sampledTelemetryHelper.js +1 -1
  44. package/dist/sampledTelemetryHelper.js.map +1 -1
  45. package/dist/telemetry-utils-alpha.d.ts +4 -15
  46. package/dist/telemetry-utils-beta.d.ts +4 -32
  47. package/dist/telemetry-utils-public.d.ts +4 -32
  48. package/dist/telemetry-utils-untrimmed.d.ts +11 -50
  49. package/dist/thresholdCounter.d.ts +1 -1
  50. package/dist/thresholdCounter.d.ts.map +1 -1
  51. package/dist/thresholdCounter.js.map +1 -1
  52. package/dist/tsdoc-metadata.json +1 -1
  53. package/dist/utils.d.ts +1 -20
  54. package/dist/utils.d.ts.map +1 -1
  55. package/dist/utils.js +3 -27
  56. package/dist/utils.js.map +1 -1
  57. package/lib/config.d.ts +2 -2
  58. package/lib/config.d.ts.map +1 -1
  59. package/lib/config.js +1 -1
  60. package/lib/config.js.map +1 -1
  61. package/lib/error.d.ts +2 -2
  62. package/lib/error.d.ts.map +1 -1
  63. package/lib/error.js +1 -1
  64. package/lib/error.js.map +1 -1
  65. package/lib/errorLogging.d.ts +4 -4
  66. package/lib/errorLogging.d.ts.map +1 -1
  67. package/lib/errorLogging.js +15 -56
  68. package/lib/errorLogging.js.map +1 -1
  69. package/lib/eventEmitterWithErrorHandling.d.ts +1 -1
  70. package/lib/eventEmitterWithErrorHandling.js +1 -1
  71. package/lib/eventEmitterWithErrorHandling.js.map +1 -1
  72. package/lib/events.d.ts +2 -3
  73. package/lib/events.d.ts.map +1 -1
  74. package/lib/events.js.map +1 -1
  75. package/lib/fluidErrorBase.d.ts +4 -3
  76. package/lib/fluidErrorBase.d.ts.map +1 -1
  77. package/lib/fluidErrorBase.js.map +1 -1
  78. package/lib/index.d.ts +12 -12
  79. package/lib/index.d.ts.map +1 -1
  80. package/lib/index.js +11 -11
  81. package/lib/index.js.map +1 -1
  82. package/lib/logger.d.ts +7 -23
  83. package/lib/logger.d.ts.map +1 -1
  84. package/lib/logger.js +3 -19
  85. package/lib/logger.js.map +1 -1
  86. package/lib/mockLogger.d.ts +1 -1
  87. package/lib/mockLogger.d.ts.map +1 -1
  88. package/lib/mockLogger.js +1 -1
  89. package/lib/mockLogger.js.map +1 -1
  90. package/lib/sampledTelemetryHelper.d.ts +4 -4
  91. package/lib/sampledTelemetryHelper.d.ts.map +1 -1
  92. package/lib/sampledTelemetryHelper.js +1 -1
  93. package/lib/sampledTelemetryHelper.js.map +1 -1
  94. package/lib/{telemetry-utils-alpha.d.mts → telemetry-utils-alpha.d.ts} +4 -15
  95. package/lib/{telemetry-utils-beta.d.mts → telemetry-utils-beta.d.ts} +4 -32
  96. package/lib/{telemetry-utils-public.d.mts → telemetry-utils-public.d.ts} +4 -32
  97. package/lib/{telemetry-utils-untrimmed.d.mts → telemetry-utils-untrimmed.d.ts} +11 -50
  98. package/lib/test/EventEmitterWithErrorHandling.spec.js +86 -0
  99. package/lib/test/EventEmitterWithErrorHandling.spec.js.map +1 -0
  100. package/lib/test/childLogger.spec.js +233 -0
  101. package/lib/test/childLogger.spec.js.map +1 -0
  102. package/lib/test/config.spec.js +229 -0
  103. package/lib/test/config.spec.js.map +1 -0
  104. package/lib/test/error.spec.js +161 -0
  105. package/lib/test/error.spec.js.map +1 -0
  106. package/lib/test/errorLogging.spec.js +801 -0
  107. package/lib/test/errorLogging.spec.js.map +1 -0
  108. package/lib/test/errorTypeLoggingTest.spec.js +107 -0
  109. package/lib/test/errorTypeLoggingTest.spec.js.map +1 -0
  110. package/lib/test/mockLogger.spec.js +164 -0
  111. package/lib/test/mockLogger.spec.js.map +1 -0
  112. package/lib/test/multiSinkLogger.spec.js +84 -0
  113. package/lib/test/multiSinkLogger.spec.js.map +1 -0
  114. package/lib/test/performanceEvent.spec.js +86 -0
  115. package/lib/test/performanceEvent.spec.js.map +1 -0
  116. package/lib/test/sampledTelemetryHelper.spec.js +169 -0
  117. package/lib/test/sampledTelemetryHelper.spec.js.map +1 -0
  118. package/lib/test/telemetryLogger.spec.js +357 -0
  119. package/lib/test/telemetryLogger.spec.js.map +1 -0
  120. package/lib/test/thresholdCounter.spec.js +51 -0
  121. package/lib/test/thresholdCounter.spec.js.map +1 -0
  122. package/lib/test/types/validateTelemetryUtilsPrevious.generated.js +132 -0
  123. package/lib/test/types/validateTelemetryUtilsPrevious.generated.js.map +1 -0
  124. package/lib/test/utils.spec.js +284 -0
  125. package/lib/test/utils.spec.js.map +1 -0
  126. package/lib/thresholdCounter.d.ts +1 -1
  127. package/lib/thresholdCounter.d.ts.map +1 -1
  128. package/lib/thresholdCounter.js.map +1 -1
  129. package/lib/utils.d.ts +1 -20
  130. package/lib/utils.d.ts.map +1 -1
  131. package/lib/utils.js +1 -24
  132. package/lib/utils.js.map +1 -1
  133. package/package.json +75 -26
  134. package/src/config.ts +2 -2
  135. package/src/error.ts +2 -2
  136. package/src/errorLogging.ts +27 -68
  137. package/src/eventEmitterWithErrorHandling.ts +1 -1
  138. package/src/events.ts +2 -4
  139. package/src/fluidErrorBase.ts +4 -3
  140. package/src/index.ts +12 -13
  141. package/src/logger.ts +12 -28
  142. package/src/mockLogger.ts +2 -2
  143. package/src/sampledTelemetryHelper.ts +10 -11
  144. package/src/thresholdCounter.ts +1 -1
  145. package/src/utils.ts +3 -36
  146. package/tsconfig.cjs.json +7 -0
  147. package/tsconfig.json +2 -3
  148. package/tsconfig.esnext.json +0 -7
  149. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -2,8 +2,8 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ITelemetryGenericEvent, ITelemetryProperties, IDisposable } from "@fluidframework/core-interfaces";
6
- import { ITelemetryLoggerExt } from "./telemetryTypes";
5
+ import type { ITelemetryBaseProperties, IDisposable } from "@fluidframework/core-interfaces";
6
+ import { ITelemetryLoggerExt, type ITelemetryGenericEventExt } from "./telemetryTypes.js";
7
7
  /**
8
8
  * Helper class that executes a specified code block and writes an
9
9
  * {@link @fluidframework/core-interfaces#ITelemetryPerformanceEvent} to a specified logger every time a specified
@@ -38,10 +38,10 @@ export declare class SampledTelemetryHelper implements IDisposable {
38
38
  * properties which should be added to the telemetry event for that bucket. If a bucket being measured does not
39
39
  * have an entry in this map, no additional properties will be added to its telemetry events. The following keys are
40
40
  * reserved for use by this class: "duration", "count", "totalDuration", "minDuration", "maxDuration". If any of
41
- * them is specified as a key in one of the ITelemetryProperties objects in this map, that key-value pair will be
41
+ * them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be
42
42
  * ignored.
43
43
  */
44
- constructor(eventBase: ITelemetryGenericEvent, logger: ITelemetryLoggerExt, sampleThreshold: number, includeAggregateMetrics?: boolean, perBucketProperties?: Map<string, ITelemetryProperties>);
44
+ constructor(eventBase: ITelemetryGenericEventExt, logger: ITelemetryLoggerExt, sampleThreshold: number, includeAggregateMetrics?: boolean, perBucketProperties?: Map<string, ITelemetryBaseProperties>);
45
45
  /**
46
46
  * Executes the specified code and keeps track of execution time statistics.
47
47
  * If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.
@@ -1 +1 @@
1
- {"version":3,"file":"sampledTelemetryHelper.d.ts","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,sBAAsB,EAEtB,oBAAoB,EACpB,WAAW,EACX,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAoCvD;;;;;;;;;;GAUG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IAwBxD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IA3BrC,QAAQ,EAAE,OAAO,CAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IAEnE;;;;;;;;;;;;;;;;;OAiBG;gBAEe,SAAS,EAAE,sBAAsB,EACjC,MAAM,EAAE,mBAAmB,EAC3B,eAAe,EAAE,MAAM,EACvB,uBAAuB,GAAE,OAAe,EACxC,mBAAmB,oCAA0C;IAG/E;;;;;;;;;OASG;IACI,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,GAAE,MAAW,GAAG,CAAC;IA0BjE,OAAO,CAAC,WAAW;IAoBZ,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI;CAG/C"}
1
+ {"version":3,"file":"sampledTelemetryHelper.d.ts","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE7F,OAAO,EACN,mBAAmB,EACnB,KAAK,yBAAyB,EAE9B,MAAM,qBAAqB,CAAC;AAoC7B;;;;;;;;;;GAUG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IAwBxD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IA3BrC,QAAQ,EAAE,OAAO,CAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IAEnE;;;;;;;;;;;;;;;;;OAiBG;gBAEe,SAAS,EAAE,yBAAyB,EACpC,MAAM,EAAE,mBAAmB,EAC3B,eAAe,EAAE,MAAM,EACvB,uBAAuB,GAAE,OAAe,EACxC,mBAAmB,wCAA8C;IAGnF;;;;;;;;;OASG;IACI,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,GAAE,MAAW,GAAG,CAAC;IA0BjE,OAAO,CAAC,WAAW;IAoBZ,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI;CAG/C"}
@@ -30,7 +30,7 @@ export class SampledTelemetryHelper {
30
30
  * properties which should be added to the telemetry event for that bucket. If a bucket being measured does not
31
31
  * have an entry in this map, no additional properties will be added to its telemetry events. The following keys are
32
32
  * reserved for use by this class: "duration", "count", "totalDuration", "minDuration", "maxDuration". If any of
33
- * them is specified as a key in one of the ITelemetryProperties objects in this map, that key-value pair will be
33
+ * them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be
34
34
  * ignored.
35
35
  */
36
36
  constructor(eventBase, logger, sampleThreshold, includeAggregateMetrics = false, perBucketProperties = new Map()) {
@@ -1 +1 @@
1
- {"version":3,"file":"sampledTelemetryHelper.js","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAqC3D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,sBAAsB;IAKlC;;;;;;;;;;;;;;;;;OAiBG;IACH,YACkB,SAAiC,EACjC,MAA2B,EAC3B,eAAuB,EACvB,0BAAmC,KAAK,EACxC,sBAAsB,IAAI,GAAG,EAAgC;QAJ7D,cAAS,GAAT,SAAS,CAAwB;QACjC,WAAM,GAAN,MAAM,CAAqB;QAC3B,oBAAe,GAAf,eAAe,CAAQ;QACvB,4BAAuB,GAAvB,uBAAuB,CAAiB;QACxC,wBAAmB,GAAnB,mBAAmB,CAA0C;QA3B/E,aAAQ,GAAY,KAAK,CAAC;QAET,oBAAe,GAAG,IAAI,GAAG,EAAwB,CAAC;IA0BhE,CAAC;IAEJ;;;;;;;;;OASG;IACI,OAAO,CAAI,aAAsB,EAAE,SAAiB,EAAE;QAC5D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAE3C,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,SAAS,EAAE;YACpB,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;SACpC;QACD,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEtB,IAAI,IAAI,CAAC,uBAAuB,EAAE;YACjC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC;YACpD,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC9D,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,EAAE;YACpC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;SACzB;QAED,OAAO,WAAW,CAAC;IACpB,CAAC;IAEO,WAAW,CAAC,MAAc;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,YAAY,KAAK,SAAS,EAAE;YAC/B,OAAO;SACP;QAED,IAAI,YAAY,CAAC,KAAK,KAAK,CAAC,EAAE;YAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE9D,MAAM,cAAc,GAA+B;gBAClD,GAAG,IAAI,CAAC,SAAS;gBACjB,GAAG,gBAAgB;gBACnB,GAAG,YAAY;aACf,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;YACjD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SACpC;IACF,CAAC;IAEM,OAAO,CAAC,KAAyB;QACvC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tITelemetryGenericEvent,\n\tITelemetryPerformanceEvent,\n\tITelemetryProperties,\n\tIDisposable,\n} from \"@fluidframework/core-interfaces\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport { ITelemetryLoggerExt } from \"./telemetryTypes\";\n\n/**\n * @privateRemarks\n *\n * The names of the properties in this interface are the ones that will get stamped in the\n * telemetry event, changes should be considered carefully. The optional properties should\n * only be populated if 'includeAggregateMetrics' is true.\n */\ninterface Measurements {\n\t/**\n\t * The duration of the latest execution.\n\t */\n\tduration: number;\n\n\t/**\n\t * The number of executions since the last time an event was generated.\n\t */\n\tcount: number;\n\n\t/**\n\t * Total duration across all the executions since the last event was generated.\n\t */\n\ttotalDuration?: number;\n\n\t/**\n\t * Min duration across all the executions since the last event was generated.\n\t */\n\tminDuration?: number;\n\n\t/**\n\t * Max duration across all the executions since the last event was generated.\n\t */\n\tmaxDuration?: number;\n}\n\n/**\n * Helper class that executes a specified code block and writes an\n * {@link @fluidframework/core-interfaces#ITelemetryPerformanceEvent} to a specified logger every time a specified\n * number of executions is reached (or when the class is disposed).\n *\n * The `duration` field in the telemetry event is the duration of the latest execution (sample) of the specified\n * function. See the documentation of the `includeAggregateMetrics` parameter for additional details that can be\n * included.\n *\n * @internal\n */\nexport class SampledTelemetryHelper implements IDisposable {\n\tdisposed: boolean = false;\n\n\tprivate readonly measurementsMap = new Map<string, Measurements>();\n\n\t/**\n\t * @param eventBase -\n\t * Custom properties to include in the telemetry performance event when it is written.\n\t * @param logger -\n\t * The logger to use to write the telemetry performance event.\n\t * @param sampleThreshold -\n\t * Telemetry performance events will be generated every time we hit this many executions of the code block.\n\t * @param includeAggregateMetrics -\n\t * If set to `true`, the telemetry performance event will include aggregated metrics (total duration, min duration,\n\t * max duration) for all the executions in between generated events.\n\t * @param perBucketProperties -\n\t * Map of strings that represent different buckets (which can be specified when calling the 'measure' method), to\n\t * properties which should be added to the telemetry event for that bucket. If a bucket being measured does not\n\t * have an entry in this map, no additional properties will be added to its telemetry events. The following keys are\n\t * reserved for use by this class: \"duration\", \"count\", \"totalDuration\", \"minDuration\", \"maxDuration\". If any of\n\t * them is specified as a key in one of the ITelemetryProperties objects in this map, that key-value pair will be\n\t * ignored.\n\t */\n\tpublic constructor(\n\t\tprivate readonly eventBase: ITelemetryGenericEvent,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate readonly sampleThreshold: number,\n\t\tprivate readonly includeAggregateMetrics: boolean = false,\n\t\tprivate readonly perBucketProperties = new Map<string, ITelemetryProperties>(),\n\t) {}\n\n\t/**\n\t * Executes the specified code and keeps track of execution time statistics.\n\t * If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.\n\t *\n\t * @param codeToMeasure - The code to be executed and measured.\n\t * @param bucket - A key to track executions of the code block separately.\n\t * Each different value of this parameter has a separate set of executions and metrics tracked by the class.\n\t * If no such distinction needs to be made, do not provide a value.\n\t * @returns Whatever the passed-in code block returns.\n\t */\n\tpublic measure<T>(codeToMeasure: () => T, bucket: string = \"\"): T {\n\t\tconst start = performance.now();\n\t\tconst returnValue = codeToMeasure();\n\t\tconst duration = performance.now() - start;\n\n\t\tlet m = this.measurementsMap.get(bucket);\n\t\tif (m === undefined) {\n\t\t\tm = { count: 0, duration: -1 };\n\t\t\tthis.measurementsMap.set(bucket, m);\n\t\t}\n\t\tm.count++;\n\t\tm.duration = duration;\n\n\t\tif (this.includeAggregateMetrics) {\n\t\t\tm.totalDuration = (m.totalDuration ?? 0) + duration;\n\t\t\tm.minDuration = Math.min(m.minDuration ?? duration, duration);\n\t\t\tm.maxDuration = Math.max(m.maxDuration ?? 0, duration);\n\t\t}\n\n\t\tif (m.count >= this.sampleThreshold) {\n\t\t\tthis.flushBucket(bucket);\n\t\t}\n\n\t\treturn returnValue;\n\t}\n\n\tprivate flushBucket(bucket: string): void {\n\t\tconst measurements = this.measurementsMap.get(bucket);\n\t\tif (measurements === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (measurements.count !== 0) {\n\t\t\tconst bucketProperties = this.perBucketProperties.get(bucket);\n\n\t\t\tconst telemetryEvent: ITelemetryPerformanceEvent = {\n\t\t\t\t...this.eventBase,\n\t\t\t\t...bucketProperties, // If the bucket doesn't exist and this is undefined, things work as expected\n\t\t\t\t...measurements,\n\t\t\t};\n\n\t\t\tthis.logger.sendPerformanceEvent(telemetryEvent);\n\t\t\tthis.measurementsMap.delete(bucket);\n\t\t}\n\t}\n\n\tpublic dispose(error?: Error | undefined): void {\n\t\tfor (const [k] of this.measurementsMap.entries()) this.flushBucket(k);\n\t}\n}\n"]}
1
+ {"version":3,"file":"sampledTelemetryHelper.js","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAyC3D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,sBAAsB;IAKlC;;;;;;;;;;;;;;;;;OAiBG;IACH,YACkB,SAAoC,EACpC,MAA2B,EAC3B,eAAuB,EACvB,0BAAmC,KAAK,EACxC,sBAAsB,IAAI,GAAG,EAAoC;QAJjE,cAAS,GAAT,SAAS,CAA2B;QACpC,WAAM,GAAN,MAAM,CAAqB;QAC3B,oBAAe,GAAf,eAAe,CAAQ;QACvB,4BAAuB,GAAvB,uBAAuB,CAAiB;QACxC,wBAAmB,GAAnB,mBAAmB,CAA8C;QA3BnF,aAAQ,GAAY,KAAK,CAAC;QAET,oBAAe,GAAG,IAAI,GAAG,EAAwB,CAAC;IA0BhE,CAAC;IAEJ;;;;;;;;;OASG;IACI,OAAO,CAAI,aAAsB,EAAE,SAAiB,EAAE;QAC5D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAE3C,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,SAAS,EAAE;YACpB,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;SACpC;QACD,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEtB,IAAI,IAAI,CAAC,uBAAuB,EAAE;YACjC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC;YACpD,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC9D,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,EAAE;YACpC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;SACzB;QAED,OAAO,WAAW,CAAC;IACpB,CAAC;IAEO,WAAW,CAAC,MAAc;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,YAAY,KAAK,SAAS,EAAE;YAC/B,OAAO;SACP;QAED,IAAI,YAAY,CAAC,KAAK,KAAK,CAAC,EAAE;YAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE9D,MAAM,cAAc,GAAkC;gBACrD,GAAG,IAAI,CAAC,SAAS;gBACjB,GAAG,gBAAgB;gBACnB,GAAG,YAAY;aACf,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;YACjD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SACpC;IACF,CAAC;IAEM,OAAO,CAAC,KAAyB;QACvC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBaseProperties, IDisposable } from \"@fluidframework/core-interfaces\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport {\n\tITelemetryLoggerExt,\n\ttype ITelemetryGenericEventExt,\n\ttype ITelemetryPerformanceEventExt,\n} from \"./telemetryTypes.js\";\n\n/**\n * @privateRemarks\n *\n * The names of the properties in this interface are the ones that will get stamped in the\n * telemetry event, changes should be considered carefully. The optional properties should\n * only be populated if 'includeAggregateMetrics' is true.\n */\ninterface Measurements {\n\t/**\n\t * The duration of the latest execution.\n\t */\n\tduration: number;\n\n\t/**\n\t * The number of executions since the last time an event was generated.\n\t */\n\tcount: number;\n\n\t/**\n\t * Total duration across all the executions since the last event was generated.\n\t */\n\ttotalDuration?: number;\n\n\t/**\n\t * Min duration across all the executions since the last event was generated.\n\t */\n\tminDuration?: number;\n\n\t/**\n\t * Max duration across all the executions since the last event was generated.\n\t */\n\tmaxDuration?: number;\n}\n\n/**\n * Helper class that executes a specified code block and writes an\n * {@link @fluidframework/core-interfaces#ITelemetryPerformanceEvent} to a specified logger every time a specified\n * number of executions is reached (or when the class is disposed).\n *\n * The `duration` field in the telemetry event is the duration of the latest execution (sample) of the specified\n * function. See the documentation of the `includeAggregateMetrics` parameter for additional details that can be\n * included.\n *\n * @internal\n */\nexport class SampledTelemetryHelper implements IDisposable {\n\tdisposed: boolean = false;\n\n\tprivate readonly measurementsMap = new Map<string, Measurements>();\n\n\t/**\n\t * @param eventBase -\n\t * Custom properties to include in the telemetry performance event when it is written.\n\t * @param logger -\n\t * The logger to use to write the telemetry performance event.\n\t * @param sampleThreshold -\n\t * Telemetry performance events will be generated every time we hit this many executions of the code block.\n\t * @param includeAggregateMetrics -\n\t * If set to `true`, the telemetry performance event will include aggregated metrics (total duration, min duration,\n\t * max duration) for all the executions in between generated events.\n\t * @param perBucketProperties -\n\t * Map of strings that represent different buckets (which can be specified when calling the 'measure' method), to\n\t * properties which should be added to the telemetry event for that bucket. If a bucket being measured does not\n\t * have an entry in this map, no additional properties will be added to its telemetry events. The following keys are\n\t * reserved for use by this class: \"duration\", \"count\", \"totalDuration\", \"minDuration\", \"maxDuration\". If any of\n\t * them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be\n\t * ignored.\n\t */\n\tpublic constructor(\n\t\tprivate readonly eventBase: ITelemetryGenericEventExt,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate readonly sampleThreshold: number,\n\t\tprivate readonly includeAggregateMetrics: boolean = false,\n\t\tprivate readonly perBucketProperties = new Map<string, ITelemetryBaseProperties>(),\n\t) {}\n\n\t/**\n\t * Executes the specified code and keeps track of execution time statistics.\n\t * If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.\n\t *\n\t * @param codeToMeasure - The code to be executed and measured.\n\t * @param bucket - A key to track executions of the code block separately.\n\t * Each different value of this parameter has a separate set of executions and metrics tracked by the class.\n\t * If no such distinction needs to be made, do not provide a value.\n\t * @returns Whatever the passed-in code block returns.\n\t */\n\tpublic measure<T>(codeToMeasure: () => T, bucket: string = \"\"): T {\n\t\tconst start = performance.now();\n\t\tconst returnValue = codeToMeasure();\n\t\tconst duration = performance.now() - start;\n\n\t\tlet m = this.measurementsMap.get(bucket);\n\t\tif (m === undefined) {\n\t\t\tm = { count: 0, duration: -1 };\n\t\t\tthis.measurementsMap.set(bucket, m);\n\t\t}\n\t\tm.count++;\n\t\tm.duration = duration;\n\n\t\tif (this.includeAggregateMetrics) {\n\t\t\tm.totalDuration = (m.totalDuration ?? 0) + duration;\n\t\t\tm.minDuration = Math.min(m.minDuration ?? duration, duration);\n\t\t\tm.maxDuration = Math.max(m.maxDuration ?? 0, duration);\n\t\t}\n\n\t\tif (m.count >= this.sampleThreshold) {\n\t\t\tthis.flushBucket(bucket);\n\t\t}\n\n\t\treturn returnValue;\n\t}\n\n\tprivate flushBucket(bucket: string): void {\n\t\tconst measurements = this.measurementsMap.get(bucket);\n\t\tif (measurements === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (measurements.count !== 0) {\n\t\t\tconst bucketProperties = this.perBucketProperties.get(bucket);\n\n\t\t\tconst telemetryEvent: ITelemetryPerformanceEventExt = {\n\t\t\t\t...this.eventBase,\n\t\t\t\t...bucketProperties, // If the bucket doesn't exist and this is undefined, things work as expected\n\t\t\t\t...measurements,\n\t\t\t};\n\n\t\t\tthis.logger.sendPerformanceEvent(telemetryEvent);\n\t\t\tthis.measurementsMap.delete(bucket);\n\t\t}\n\t}\n\n\tpublic dispose(error?: Error | undefined): void {\n\t\tfor (const [k] of this.measurementsMap.entries()) this.flushBucket(k);\n\t}\n}\n"]}
@@ -1,28 +1,21 @@
1
- /// <reference types="node" />
2
-
3
1
  import { ConfigTypes } from '@fluidframework/core-interfaces';
4
- import { EventEmitter } from 'events';
2
+ import type { EventEmitter } from '@fluid-internal/client-utils';
5
3
  import { EventEmitterEventType } from '@fluid-internal/client-utils';
6
4
  import { IConfigProviderBase } from '@fluidframework/core-interfaces';
7
- import { IDisposable } from '@fluidframework/core-interfaces';
5
+ import type { IDisposable } from '@fluidframework/core-interfaces';
8
6
  import { IErrorBase } from '@fluidframework/core-interfaces';
9
7
  import { IEvent } from '@fluidframework/core-interfaces';
10
8
  import { IGenericError } from '@fluidframework/core-interfaces';
11
- import { ILoggingError } from '@fluidframework/core-interfaces';
9
+ import type { ILoggingError } from '@fluidframework/core-interfaces';
12
10
  import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
13
11
  import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
14
12
  import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
15
13
  import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
16
- import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
17
- import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
18
- import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
19
- import { ITelemetryProperties } from '@fluidframework/core-interfaces';
20
14
  import { IUsageError } from '@fluidframework/core-interfaces';
21
15
  import { Lazy } from '@fluidframework/core-utils';
22
16
  import { LogLevel } from '@fluidframework/core-interfaces';
23
17
  import { Tagged } from '@fluidframework/core-interfaces';
24
18
  import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
25
- import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
26
19
  import { TypedEventEmitter } from '@fluid-internal/client-utils';
27
20
 
28
21
  /* Excluded from this release type: connectedEventName */
@@ -64,7 +57,7 @@ export declare function createChildLogger(props?: {
64
57
  * @privateRemarks
65
58
  * This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
66
59
  * We should consider moving it to the `core-utils` package.
67
- * @public
60
+ * @alpha
68
61
  */
69
62
  export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
70
63
  private readonly errorHandler;
@@ -210,8 +203,6 @@ export declare interface ITelemetryPropertiesExt {
210
203
 
211
204
  /* Excluded from this release type: LoggingError */
212
205
 
213
- /* Excluded from this release type: logIfFalse */
214
-
215
206
  /* Excluded from this release type: mixinMonitoringContext */
216
207
 
217
208
  /* Excluded from this release type: MockLogger */
@@ -276,8 +267,6 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
276
267
  */
277
268
  export declare type TelemetryEventPropertyTypes = ITelemetryBaseProperties[string];
278
269
 
279
- /* Excluded from this release type: TelemetryNullLogger */
280
-
281
270
  /* Excluded from this release type: ThresholdCounter */
282
271
 
283
272
  /* Excluded from this release type: UsageError */
@@ -1,28 +1,21 @@
1
- /// <reference types="node" />
2
-
3
1
  import { ConfigTypes } from '@fluidframework/core-interfaces';
4
- import { EventEmitter } from 'events';
2
+ import type { EventEmitter } from '@fluid-internal/client-utils';
5
3
  import { EventEmitterEventType } from '@fluid-internal/client-utils';
6
4
  import { IConfigProviderBase } from '@fluidframework/core-interfaces';
7
- import { IDisposable } from '@fluidframework/core-interfaces';
5
+ import type { IDisposable } from '@fluidframework/core-interfaces';
8
6
  import { IErrorBase } from '@fluidframework/core-interfaces';
9
7
  import { IEvent } from '@fluidframework/core-interfaces';
10
8
  import { IGenericError } from '@fluidframework/core-interfaces';
11
- import { ILoggingError } from '@fluidframework/core-interfaces';
9
+ import type { ILoggingError } from '@fluidframework/core-interfaces';
12
10
  import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
13
11
  import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
14
12
  import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
15
13
  import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
16
- import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
17
- import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
18
- import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
19
- import { ITelemetryProperties } from '@fluidframework/core-interfaces';
20
14
  import { IUsageError } from '@fluidframework/core-interfaces';
21
15
  import { Lazy } from '@fluidframework/core-utils';
22
16
  import { LogLevel } from '@fluidframework/core-interfaces';
23
17
  import { Tagged } from '@fluidframework/core-interfaces';
24
18
  import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
25
- import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
26
19
  import { TypedEventEmitter } from '@fluid-internal/client-utils';
27
20
 
28
21
  /* Excluded from this release type: connectedEventName */
@@ -41,22 +34,7 @@ import { TypedEventEmitter } from '@fluid-internal/client-utils';
41
34
 
42
35
  /* Excluded from this release type: disconnectedEventName */
43
36
 
44
- /**
45
- * Event Emitter helper class
46
- *
47
- * @remarks
48
- * Any exceptions thrown by listeners will be caught and raised through "error" event.
49
- * Any exception thrown by "error" listeners will propagate to the caller.
50
- * @privateRemarks
51
- * This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
52
- * We should consider moving it to the `core-utils` package.
53
- * @public
54
- */
55
- export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
56
- private readonly errorHandler;
57
- constructor(errorHandler: (eventName: EventEmitterEventType, error: any) => void);
58
- emit(event: EventEmitterEventType, ...args: unknown[]): boolean;
59
- }
37
+ /* Excluded from this release type: EventEmitterWithErrorHandling */
60
38
 
61
39
  /* Excluded from this release type: eventNamespaceSeparator */
62
40
 
@@ -185,8 +163,6 @@ export declare interface ITelemetryPropertiesExt {
185
163
 
186
164
  /* Excluded from this release type: LoggingError */
187
165
 
188
- /* Excluded from this release type: logIfFalse */
189
-
190
166
  /* Excluded from this release type: mixinMonitoringContext */
191
167
 
192
168
  /* Excluded from this release type: MockLogger */
@@ -219,8 +195,6 @@ export declare interface ITelemetryPropertiesExt {
219
195
 
220
196
  /* Excluded from this release type: TaggedLoggerAdapter */
221
197
 
222
- /* Excluded from this release type: TelemetryBaseEventPropertyType */
223
-
224
198
  /* Excluded from this release type: TelemetryDataTag */
225
199
 
226
200
  /**
@@ -250,8 +224,6 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
250
224
 
251
225
  /* Excluded from this release type: TelemetryEventPropertyTypes */
252
226
 
253
- /* Excluded from this release type: TelemetryNullLogger */
254
-
255
227
  /* Excluded from this release type: ThresholdCounter */
256
228
 
257
229
  /* Excluded from this release type: UsageError */
@@ -1,28 +1,21 @@
1
- /// <reference types="node" />
2
-
3
1
  import { ConfigTypes } from '@fluidframework/core-interfaces';
4
- import { EventEmitter } from 'events';
2
+ import type { EventEmitter } from '@fluid-internal/client-utils';
5
3
  import { EventEmitterEventType } from '@fluid-internal/client-utils';
6
4
  import { IConfigProviderBase } from '@fluidframework/core-interfaces';
7
- import { IDisposable } from '@fluidframework/core-interfaces';
5
+ import type { IDisposable } from '@fluidframework/core-interfaces';
8
6
  import { IErrorBase } from '@fluidframework/core-interfaces';
9
7
  import { IEvent } from '@fluidframework/core-interfaces';
10
8
  import { IGenericError } from '@fluidframework/core-interfaces';
11
- import { ILoggingError } from '@fluidframework/core-interfaces';
9
+ import type { ILoggingError } from '@fluidframework/core-interfaces';
12
10
  import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
13
11
  import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
14
12
  import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
15
13
  import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
16
- import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
17
- import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
18
- import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
19
- import { ITelemetryProperties } from '@fluidframework/core-interfaces';
20
14
  import { IUsageError } from '@fluidframework/core-interfaces';
21
15
  import { Lazy } from '@fluidframework/core-utils';
22
16
  import { LogLevel } from '@fluidframework/core-interfaces';
23
17
  import { Tagged } from '@fluidframework/core-interfaces';
24
18
  import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
25
- import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
26
19
  import { TypedEventEmitter } from '@fluid-internal/client-utils';
27
20
 
28
21
  /* Excluded from this release type: connectedEventName */
@@ -41,22 +34,7 @@ import { TypedEventEmitter } from '@fluid-internal/client-utils';
41
34
 
42
35
  /* Excluded from this release type: disconnectedEventName */
43
36
 
44
- /**
45
- * Event Emitter helper class
46
- *
47
- * @remarks
48
- * Any exceptions thrown by listeners will be caught and raised through "error" event.
49
- * Any exception thrown by "error" listeners will propagate to the caller.
50
- * @privateRemarks
51
- * This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
52
- * We should consider moving it to the `core-utils` package.
53
- * @public
54
- */
55
- export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
56
- private readonly errorHandler;
57
- constructor(errorHandler: (eventName: EventEmitterEventType, error: any) => void);
58
- emit(event: EventEmitterEventType, ...args: unknown[]): boolean;
59
- }
37
+ /* Excluded from this release type: EventEmitterWithErrorHandling */
60
38
 
61
39
  /* Excluded from this release type: eventNamespaceSeparator */
62
40
 
@@ -185,8 +163,6 @@ export declare interface ITelemetryPropertiesExt {
185
163
 
186
164
  /* Excluded from this release type: LoggingError */
187
165
 
188
- /* Excluded from this release type: logIfFalse */
189
-
190
166
  /* Excluded from this release type: mixinMonitoringContext */
191
167
 
192
168
  /* Excluded from this release type: MockLogger */
@@ -219,8 +195,6 @@ export declare interface ITelemetryPropertiesExt {
219
195
 
220
196
  /* Excluded from this release type: TaggedLoggerAdapter */
221
197
 
222
- /* Excluded from this release type: TelemetryBaseEventPropertyType */
223
-
224
198
  /* Excluded from this release type: TelemetryDataTag */
225
199
 
226
200
  /**
@@ -250,8 +224,6 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
250
224
 
251
225
  /* Excluded from this release type: TelemetryEventPropertyTypes */
252
226
 
253
- /* Excluded from this release type: TelemetryNullLogger */
254
-
255
227
  /* Excluded from this release type: ThresholdCounter */
256
228
 
257
229
  /* Excluded from this release type: UsageError */
@@ -1,28 +1,21 @@
1
- /// <reference types="node" />
2
-
3
1
  import { ConfigTypes } from '@fluidframework/core-interfaces';
4
- import { EventEmitter } from 'events';
2
+ import type { EventEmitter } from '@fluid-internal/client-utils';
5
3
  import { EventEmitterEventType } from '@fluid-internal/client-utils';
6
4
  import { IConfigProviderBase } from '@fluidframework/core-interfaces';
7
- import { IDisposable } from '@fluidframework/core-interfaces';
5
+ import type { IDisposable } from '@fluidframework/core-interfaces';
8
6
  import { IErrorBase } from '@fluidframework/core-interfaces';
9
7
  import { IEvent } from '@fluidframework/core-interfaces';
10
8
  import { IGenericError } from '@fluidframework/core-interfaces';
11
- import { ILoggingError } from '@fluidframework/core-interfaces';
9
+ import type { ILoggingError } from '@fluidframework/core-interfaces';
12
10
  import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
13
11
  import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
14
12
  import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
15
13
  import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
16
- import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
17
- import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
18
- import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
19
- import { ITelemetryProperties } from '@fluidframework/core-interfaces';
20
14
  import { IUsageError } from '@fluidframework/core-interfaces';
21
15
  import { Lazy } from '@fluidframework/core-utils';
22
16
  import { LogLevel } from '@fluidframework/core-interfaces';
23
17
  import { Tagged } from '@fluidframework/core-interfaces';
24
18
  import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
25
- import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
26
19
  import { TypedEventEmitter } from '@fluid-internal/client-utils';
27
20
 
28
21
  /**
@@ -148,7 +141,7 @@ export declare const disconnectedEventName = "disconnected";
148
141
  * @privateRemarks
149
142
  * This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
150
143
  * We should consider moving it to the `core-utils` package.
151
- * @public
144
+ * @alpha
152
145
  */
153
146
  export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
154
147
  private readonly errorHandler;
@@ -341,11 +334,11 @@ export declare interface IFluidErrorBase extends Error {
341
334
  /**
342
335
  * Get the telemetry properties stashed on this error for logging.
343
336
  */
344
- getTelemetryProperties(): ITelemetryProperties;
337
+ getTelemetryProperties(): ITelemetryBaseProperties;
345
338
  /**
346
339
  * Add telemetry properties to this error which will be logged with the error
347
340
  */
348
- addTelemetryProperties: (props: ITelemetryProperties) => void;
341
+ addTelemetryProperties: (props: ITelemetryPropertiesExt) => void;
349
342
  }
350
343
 
351
344
  /**
@@ -569,28 +562,13 @@ export declare class LoggingError extends Error implements ILoggingError, Omit<I
569
562
  /**
570
563
  * Add additional properties to be logged
571
564
  */
572
- addTelemetryProperties(props: ITelemetryBaseProperties): void;
565
+ addTelemetryProperties(props: ITelemetryPropertiesExt): void;
573
566
  /**
574
567
  * Get all properties fit to be logged to telemetry for this error
575
568
  */
576
569
  getTelemetryProperties(): ITelemetryBaseProperties;
577
570
  }
578
571
 
579
- /**
580
- * Like assert, but logs only if the condition is false, rather than throwing
581
- * @param condition - The condition to attest too
582
- * @param logger - The logger to log with
583
- * @param event - The string or event to log
584
- * @returns The outcome of the condition
585
- *
586
- * @internal
587
- *
588
- * @deprecated
589
- * This API will be removed in a future release.
590
- * No replacement API is intended, but reproducing its behavior should be trivial for anyone who needs it.
591
- */
592
- export declare function logIfFalse(condition: unknown, logger: ITelemetryBaseLogger, event: string | ITelemetryGenericEvent): condition is true;
593
-
594
572
  /**
595
573
  * Creates a {@link MonitoringContext} from the provided logger.
596
574
  *
@@ -865,10 +843,10 @@ export declare class SampledTelemetryHelper implements IDisposable {
865
843
  * properties which should be added to the telemetry event for that bucket. If a bucket being measured does not
866
844
  * have an entry in this map, no additional properties will be added to its telemetry events. The following keys are
867
845
  * reserved for use by this class: "duration", "count", "totalDuration", "minDuration", "maxDuration". If any of
868
- * them is specified as a key in one of the ITelemetryProperties objects in this map, that key-value pair will be
846
+ * them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be
869
847
  * ignored.
870
848
  */
871
- constructor(eventBase: ITelemetryGenericEvent, logger: ITelemetryLoggerExt, sampleThreshold: number, includeAggregateMetrics?: boolean, perBucketProperties?: Map<string, ITelemetryProperties>);
849
+ constructor(eventBase: ITelemetryGenericEventExt, logger: ITelemetryLoggerExt, sampleThreshold: number, includeAggregateMetrics?: boolean, perBucketProperties?: Map<string, ITelemetryBaseProperties>);
872
850
  /**
873
851
  * Executes the specified code and keeps track of execution time statistics.
874
852
  * If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.
@@ -916,7 +894,7 @@ export declare const sessionStorageConfigProvider: Lazy<IConfigProviderBase>;
916
894
  *
917
895
  * @internal
918
896
  */
919
- export declare const tagCodeArtifacts: <T extends Record<string, TelemetryEventPropertyType | (() => TelemetryBaseEventPropertyType)>>(values: T) => { [P in keyof T]: (T[P] extends () => TelemetryBaseEventPropertyType ? () => {
897
+ export declare const tagCodeArtifacts: <T extends Record<string, TelemetryBaseEventPropertyType | (() => TelemetryBaseEventPropertyType)>>(values: T) => { [P in keyof T]: (T[P] extends () => TelemetryBaseEventPropertyType ? () => {
920
898
  value: ReturnType<T[P]>;
921
899
  tag: TelemetryDataTag.CodeArtifact;
922
900
  } : {
@@ -946,7 +924,7 @@ export declare const tagCodeArtifacts: <T extends Record<string, TelemetryEventP
946
924
  *
947
925
  * @internal
948
926
  */
949
- export declare const tagData: <T extends TelemetryDataTag, V extends Record<string, TelemetryEventPropertyType | (() => TelemetryBaseEventPropertyType)>>(tag: T, values: V) => { [P in keyof V]: (V[P] extends () => TelemetryBaseEventPropertyType ? () => {
927
+ export declare const tagData: <T extends TelemetryDataTag, V extends Record<string, TelemetryBaseEventPropertyType | (() => TelemetryBaseEventPropertyType)>>(tag: T, values: V) => { [P in keyof V]: (V[P] extends () => TelemetryBaseEventPropertyType ? () => {
950
928
  value: ReturnType<V[P]>;
951
929
  tag: T;
952
930
  } : {
@@ -1018,23 +996,6 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
1018
996
  */
1019
997
  export declare type TelemetryEventPropertyTypes = ITelemetryBaseProperties[string];
1020
998
 
1021
- /**
1022
- * Null logger that no-ops for all telemetry events passed to it.
1023
- *
1024
- * @deprecated This will be removed in a future release.
1025
- * For internal use within the FluidFramework codebase, use {@link createChildLogger} with no arguments instead.
1026
- * For external consumers we recommend writing a trivial implementation of {@link @fluidframework/core-interfaces#ITelemetryBaseLogger}
1027
- * where the send() method does nothing and using that.
1028
- *
1029
- * @internal
1030
- */
1031
- export declare class TelemetryNullLogger implements ITelemetryLoggerExt {
1032
- send(event: ITelemetryBaseEvent): void;
1033
- sendTelemetryEvent(event: ITelemetryGenericEvent, error?: unknown): void;
1034
- sendErrorEvent(event: ITelemetryErrorEvent, error?: unknown): void;
1035
- sendPerformanceEvent(event: ITelemetryPerformanceEvent, error?: unknown): void;
1036
- }
1037
-
1038
999
  /**
1039
1000
  * Utility counter which will send event only if the provided value is above a configured threshold.
1040
1001
  *
@@ -0,0 +1,86 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "node:assert";
6
+ import { EventEmitterWithErrorHandling } from "../eventEmitterWithErrorHandling.js";
7
+ describe("EventEmitterWithErrorHandling", () => {
8
+ let errorHandlerCalled = false;
9
+ function defaultErrorHandler(event, error) {
10
+ errorHandlerCalled = true;
11
+ throw error;
12
+ }
13
+ beforeEach(() => {
14
+ errorHandlerCalled = false;
15
+ });
16
+ it("forwards events", () => {
17
+ const emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);
18
+ let passedArg;
19
+ emitter.on("foo", (arg) => {
20
+ passedArg = arg;
21
+ });
22
+ emitter.emit("foo", 3);
23
+ assert.strictEqual(passedArg, 3);
24
+ assert.strictEqual(errorHandlerCalled, false);
25
+ });
26
+ it("forwards error event", () => {
27
+ const emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);
28
+ let passedArg;
29
+ emitter.on("error", (arg) => {
30
+ passedArg = arg;
31
+ });
32
+ emitter.emit("error", 3);
33
+ assert.strictEqual(passedArg, 3);
34
+ assert.strictEqual(errorHandlerCalled, false);
35
+ });
36
+ it("error thrown from listener is handled, some other listeners succeed", () => {
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const emitter = new EventEmitterWithErrorHandling((event, error) => {
39
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
40
+ passedErrorMsg = error.message;
41
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
42
+ passedEventArg = error.eventArg;
43
+ });
44
+ let passedErrorMsg;
45
+ let passedEventArg;
46
+ let earlyListenerCallCount = 0;
47
+ let lateListenerCallCount = 0;
48
+ // Innocent bystander - early (registered before throwing one)
49
+ emitter.on("foo", (_arg) => {
50
+ ++earlyListenerCallCount;
51
+ });
52
+ // The delinquent
53
+ emitter.on("foo", (arg) => {
54
+ const error = new Error("foo listener throws");
55
+ Object.assign(error, { eventArg: arg });
56
+ throw error;
57
+ });
58
+ // Innocent bystander - late (registered after throwing one)
59
+ emitter.on("foo", (_arg) => {
60
+ ++lateListenerCallCount;
61
+ });
62
+ emitter.emit("foo", 3); // listener above will throw. Expect error listener to be invoked
63
+ assert.strictEqual(passedErrorMsg, "foo listener throws");
64
+ assert.strictEqual(passedEventArg, 3);
65
+ assert.strictEqual(earlyListenerCallCount, 1);
66
+ assert.strictEqual(lateListenerCallCount, 0);
67
+ });
68
+ it("emitting error event when unhandled will invoke handler", () => {
69
+ const emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);
70
+ try {
71
+ const error = new Error("No one is listening");
72
+ Object.assign(error, { prop: 4 });
73
+ emitter.emit("error", error, 3); // the extra args (e.g. 3 here) are dropped
74
+ assert.fail("previous line should throw");
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ }
77
+ catch (error) {
78
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
79
+ assert.strictEqual(error.message, "No one is listening");
80
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
81
+ assert.strictEqual(error.prop, 4);
82
+ assert.strictEqual(errorHandlerCalled, true);
83
+ }
84
+ });
85
+ });
86
+ //# sourceMappingURL=EventEmitterWithErrorHandling.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventEmitterWithErrorHandling.spec.js","sourceRoot":"","sources":["../../src/test/EventEmitterWithErrorHandling.spec.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 { strict as assert } from \"node:assert\";\nimport { EventEmitterWithErrorHandling } from \"../eventEmitterWithErrorHandling.js\";\n\ndescribe(\"EventEmitterWithErrorHandling\", () => {\n\tlet errorHandlerCalled = false;\n\tfunction defaultErrorHandler(event, error): void {\n\t\terrorHandlerCalled = true;\n\t\tthrow error;\n\t}\n\n\tbeforeEach(() => {\n\t\terrorHandlerCalled = false;\n\t});\n\n\tit(\"forwards events\", () => {\n\t\tconst emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);\n\t\tlet passedArg: number | undefined;\n\t\temitter.on(\"foo\", (arg: number) => {\n\t\t\tpassedArg = arg;\n\t\t});\n\n\t\temitter.emit(\"foo\", 3);\n\t\tassert.strictEqual(passedArg, 3);\n\t\tassert.strictEqual(errorHandlerCalled, false);\n\t});\n\tit(\"forwards error event\", () => {\n\t\tconst emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);\n\t\tlet passedArg: number | undefined;\n\t\temitter.on(\"error\", (arg: number) => {\n\t\t\tpassedArg = arg;\n\t\t});\n\n\t\temitter.emit(\"error\", 3);\n\t\tassert.strictEqual(passedArg, 3);\n\t\tassert.strictEqual(errorHandlerCalled, false);\n\t});\n\tit(\"error thrown from listener is handled, some other listeners succeed\", () => {\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\tconst emitter = new EventEmitterWithErrorHandling((event, error: any) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n\t\t\tpassedErrorMsg = error.message;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n\t\t\tpassedEventArg = error.eventArg;\n\t\t});\n\t\tlet passedErrorMsg: string | undefined;\n\t\tlet passedEventArg: number | undefined;\n\t\tlet earlyListenerCallCount: number = 0;\n\t\tlet lateListenerCallCount: number = 0;\n\t\t// Innocent bystander - early (registered before throwing one)\n\t\temitter.on(\"foo\", (_arg: unknown) => {\n\t\t\t++earlyListenerCallCount;\n\t\t});\n\t\t// The delinquent\n\t\temitter.on(\"foo\", (arg: unknown) => {\n\t\t\tconst error = new Error(\"foo listener throws\");\n\t\t\tObject.assign(error, { eventArg: arg });\n\t\t\tthrow error;\n\t\t});\n\t\t// Innocent bystander - late (registered after throwing one)\n\t\temitter.on(\"foo\", (_arg) => {\n\t\t\t++lateListenerCallCount;\n\t\t});\n\n\t\temitter.emit(\"foo\", 3); // listener above will throw. Expect error listener to be invoked\n\t\tassert.strictEqual(passedErrorMsg, \"foo listener throws\");\n\t\tassert.strictEqual(passedEventArg, 3);\n\t\tassert.strictEqual(earlyListenerCallCount, 1);\n\t\tassert.strictEqual(lateListenerCallCount, 0);\n\t});\n\tit(\"emitting error event when unhandled will invoke handler\", () => {\n\t\tconst emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);\n\t\ttry {\n\t\t\tconst error = new Error(\"No one is listening\");\n\t\t\tObject.assign(error, { prop: 4 });\n\t\t\temitter.emit(\"error\", error, 3); // the extra args (e.g. 3 here) are dropped\n\t\t\tassert.fail(\"previous line should throw\");\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tassert.strictEqual(error.message, \"No one is listening\");\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tassert.strictEqual(error.prop, 4);\n\t\t\tassert.strictEqual(errorHandlerCalled, true);\n\t\t}\n\t});\n});\n"]}