@fluidframework/telemetry-utils 2.0.0-internal.7.2.2 → 2.0.0-internal.7.4.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 (130) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -2
  3. package/api-extractor-lint.json +13 -0
  4. package/api-extractor.json +3 -3
  5. package/api-report/telemetry-utils.api.md +66 -57
  6. package/dist/config.d.ts +37 -10
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +30 -0
  9. package/dist/config.js.map +1 -1
  10. package/dist/error.d.ts +12 -0
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/error.js +18 -1
  13. package/dist/error.js.map +1 -1
  14. package/dist/errorLogging.d.ts +7 -2
  15. package/dist/errorLogging.d.ts.map +1 -1
  16. package/dist/errorLogging.js +7 -2
  17. package/dist/errorLogging.js.map +1 -1
  18. package/dist/eventEmitterWithErrorHandling.d.ts +6 -0
  19. package/dist/eventEmitterWithErrorHandling.d.ts.map +1 -1
  20. package/dist/eventEmitterWithErrorHandling.js +6 -0
  21. package/dist/eventEmitterWithErrorHandling.js.map +1 -1
  22. package/dist/events.d.ts +16 -0
  23. package/dist/events.d.ts.map +1 -1
  24. package/dist/events.js +16 -0
  25. package/dist/events.js.map +1 -1
  26. package/dist/fluidErrorBase.d.ts +8 -0
  27. package/dist/fluidErrorBase.d.ts.map +1 -1
  28. package/dist/fluidErrorBase.js +6 -0
  29. package/dist/fluidErrorBase.js.map +1 -1
  30. package/dist/index.d.ts +20 -3
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/logger.d.ts +117 -17
  35. package/dist/logger.d.ts.map +1 -1
  36. package/dist/logger.js +82 -12
  37. package/dist/logger.js.map +1 -1
  38. package/dist/mockLogger.d.ts +2 -0
  39. package/dist/mockLogger.d.ts.map +1 -1
  40. package/dist/mockLogger.js +2 -0
  41. package/dist/mockLogger.js.map +1 -1
  42. package/dist/sampledTelemetryHelper.d.ts +7 -3
  43. package/dist/sampledTelemetryHelper.d.ts.map +1 -1
  44. package/dist/sampledTelemetryHelper.js +7 -3
  45. package/dist/sampledTelemetryHelper.js.map +1 -1
  46. package/dist/telemetry-utils-alpha.d.ts +270 -0
  47. package/dist/telemetry-utils-beta.d.ts +205 -0
  48. package/dist/telemetry-utils-public.d.ts +205 -0
  49. package/dist/telemetry-utils-untrimmed.d.ts +1123 -0
  50. package/dist/telemetryTypes.d.ts +27 -8
  51. package/dist/telemetryTypes.d.ts.map +1 -1
  52. package/dist/telemetryTypes.js.map +1 -1
  53. package/dist/thresholdCounter.d.ts +3 -2
  54. package/dist/thresholdCounter.d.ts.map +1 -1
  55. package/dist/thresholdCounter.js +3 -2
  56. package/dist/thresholdCounter.js.map +1 -1
  57. package/dist/tsdoc-metadata.json +1 -1
  58. package/dist/utils.d.ts +6 -0
  59. package/dist/utils.d.ts.map +1 -1
  60. package/dist/utils.js +6 -0
  61. package/dist/utils.js.map +1 -1
  62. package/lib/config.d.ts +37 -10
  63. package/lib/config.d.ts.map +1 -1
  64. package/lib/config.js +30 -0
  65. package/lib/config.js.map +1 -1
  66. package/lib/error.d.ts +12 -0
  67. package/lib/error.d.ts.map +1 -1
  68. package/lib/error.js +16 -0
  69. package/lib/error.js.map +1 -1
  70. package/lib/errorLogging.d.ts +7 -2
  71. package/lib/errorLogging.d.ts.map +1 -1
  72. package/lib/errorLogging.js +7 -2
  73. package/lib/errorLogging.js.map +1 -1
  74. package/lib/eventEmitterWithErrorHandling.d.ts +6 -0
  75. package/lib/eventEmitterWithErrorHandling.d.ts.map +1 -1
  76. package/lib/eventEmitterWithErrorHandling.js +6 -0
  77. package/lib/eventEmitterWithErrorHandling.js.map +1 -1
  78. package/lib/events.d.ts +16 -0
  79. package/lib/events.d.ts.map +1 -1
  80. package/lib/events.js +16 -0
  81. package/lib/events.js.map +1 -1
  82. package/lib/fluidErrorBase.d.ts +8 -0
  83. package/lib/fluidErrorBase.d.ts.map +1 -1
  84. package/lib/fluidErrorBase.js +6 -0
  85. package/lib/fluidErrorBase.js.map +1 -1
  86. package/lib/index.d.ts +20 -3
  87. package/lib/index.d.ts.map +1 -1
  88. package/lib/index.js +1 -1
  89. package/lib/index.js.map +1 -1
  90. package/lib/logger.d.ts +117 -17
  91. package/lib/logger.d.ts.map +1 -1
  92. package/lib/logger.js +82 -12
  93. package/lib/logger.js.map +1 -1
  94. package/lib/mockLogger.d.ts +2 -0
  95. package/lib/mockLogger.d.ts.map +1 -1
  96. package/lib/mockLogger.js +2 -0
  97. package/lib/mockLogger.js.map +1 -1
  98. package/lib/sampledTelemetryHelper.d.ts +7 -3
  99. package/lib/sampledTelemetryHelper.d.ts.map +1 -1
  100. package/lib/sampledTelemetryHelper.js +7 -3
  101. package/lib/sampledTelemetryHelper.js.map +1 -1
  102. package/lib/telemetry-utils-alpha.d.ts +270 -0
  103. package/lib/telemetry-utils-beta.d.ts +205 -0
  104. package/lib/telemetry-utils-public.d.ts +205 -0
  105. package/lib/telemetry-utils-untrimmed.d.ts +1123 -0
  106. package/lib/telemetryTypes.d.ts +27 -8
  107. package/lib/telemetryTypes.d.ts.map +1 -1
  108. package/lib/telemetryTypes.js.map +1 -1
  109. package/lib/thresholdCounter.d.ts +3 -2
  110. package/lib/thresholdCounter.d.ts.map +1 -1
  111. package/lib/thresholdCounter.js +3 -2
  112. package/lib/thresholdCounter.js.map +1 -1
  113. package/lib/utils.d.ts +6 -0
  114. package/lib/utils.d.ts.map +1 -1
  115. package/lib/utils.js +6 -0
  116. package/lib/utils.js.map +1 -1
  117. package/package.json +36 -17
  118. package/src/config.ts +41 -12
  119. package/src/error.ts +21 -0
  120. package/src/errorLogging.ts +7 -2
  121. package/src/eventEmitterWithErrorHandling.ts +6 -0
  122. package/src/events.ts +18 -0
  123. package/src/fluidErrorBase.ts +8 -0
  124. package/src/index.ts +21 -2
  125. package/src/logger.ts +125 -17
  126. package/src/mockLogger.ts +2 -0
  127. package/src/sampledTelemetryHelper.ts +7 -3
  128. package/src/telemetryTypes.ts +27 -8
  129. package/src/thresholdCounter.ts +3 -2
  130. package/src/utils.ts +6 -0
@@ -7,13 +7,21 @@ import { ITelemetryBaseLogger, LogLevel, Tagged } from "@fluidframework/core-int
7
7
  * The categories FF uses when instrumenting the code.
8
8
  *
9
9
  * generic - Informational log event
10
+ *
10
11
  * error - Error log event, ideally 0 of these are logged during a session
12
+ *
11
13
  * performance - Includes duration, and often has _start, _end, or _cancel suffixes for activity tracking
14
+ * @alpha
12
15
  */
13
16
  export type TelemetryEventCategory = "generic" | "error" | "performance";
14
17
  /**
15
18
  * Property types that can be logged.
16
- * Includes extra types beyond TelemetryBaseEventPropertyType, which must be converted before sending to a base logger
19
+ *
20
+ * @remarks
21
+ * Includes extra types beyond {@link @fluidframework/core-interfaces#TelemetryBaseEventPropertyType}, which must be
22
+ * converted before sending to a base logger.
23
+ *
24
+ * @alpha
17
25
  */
18
26
  export type TelemetryEventPropertyTypeExt = string | number | boolean | undefined | (string | number | boolean)[] | {
19
27
  [key: string]: // Flat objects can have the same properties as the event itself
@@ -24,7 +32,8 @@ export type TelemetryEventPropertyTypeExt = string | number | boolean | undefine
24
32
  * to mark pieces of information that should be organized or handled differently by loggers in various first or third
25
33
  * party scenarios. For example, tags are used to mark personal information that should not be stored in logs.
26
34
  *
27
- * @deprecated Use Tagged<TelemetryEventPropertyTypeExt>
35
+ * @deprecated Use {@link @fluidframework/core-interfaces#Tagged}\<{@link TelemetryEventPropertyTypeExt}\>
36
+ * @internal
28
37
  */
29
38
  export interface ITaggedTelemetryPropertyTypeExt {
30
39
  value: TelemetryEventPropertyTypeExt;
@@ -32,15 +41,19 @@ export interface ITaggedTelemetryPropertyTypeExt {
32
41
  }
33
42
  /**
34
43
  * JSON-serializable properties, which will be logged with telemetry.
44
+ *
45
+ * @alpha
35
46
  */
36
47
  export interface ITelemetryPropertiesExt {
37
48
  [index: string]: TelemetryEventPropertyTypeExt | Tagged<TelemetryEventPropertyTypeExt>;
38
49
  }
39
50
  /**
40
51
  * Interface for logging telemetry statements.
41
- * Can contain any number of properties that get serialized as json payload.
52
+ * @remarks May contain any number of properties that get serialized as json payload.
42
53
  * @param category - category of the event, like "error", "performance", "generic", etc.
43
54
  * @param eventName - name of the event.
55
+ *
56
+ * @internal
44
57
  */
45
58
  export interface ITelemetryEventExt extends ITelemetryPropertiesExt {
46
59
  category: string;
@@ -48,7 +61,8 @@ export interface ITelemetryEventExt extends ITelemetryPropertiesExt {
48
61
  }
49
62
  /**
50
63
  * Informational (non-error) telemetry event
51
- * Maps to category = "generic"
64
+ * @remarks Maps to category = "generic"
65
+ * @alpha
52
66
  */
53
67
  export interface ITelemetryGenericEventExt extends ITelemetryPropertiesExt {
54
68
  eventName: string;
@@ -56,22 +70,27 @@ export interface ITelemetryGenericEventExt extends ITelemetryPropertiesExt {
56
70
  }
57
71
  /**
58
72
  * Error telemetry event.
59
- * Maps to category = "error"
73
+ * @remarks Maps to category = "error"
74
+ * @alpha
60
75
  */
61
76
  export interface ITelemetryErrorEventExt extends ITelemetryPropertiesExt {
62
77
  eventName: string;
63
78
  }
64
79
  /**
65
80
  * Performance telemetry event.
66
- * Maps to category = "performance"
81
+ * @remarks Maps to category = "performance"
82
+ * @alpha
67
83
  */
68
84
  export interface ITelemetryPerformanceEventExt extends ITelemetryGenericEventExt {
69
85
  duration?: number;
70
86
  }
71
87
  /**
72
- * An extended TelemetryLogger interface which allows for more lenient event types.
88
+ * An extended {@link @fluidframework/core-interfaces#ITelemetryBaseLogger} which allows for more lenient event types.
89
+ *
90
+ * @remarks
73
91
  * This interface is meant to be used internally within the Fluid Framework,
74
- * and ITelemetryBaseLogger should be used when loggers are passed between layers.
92
+ * and `ITelemetryBaseLogger` should be used when loggers are passed between layers.
93
+ * @alpha
75
94
  */
76
95
  export interface ITelemetryLoggerExt extends ITelemetryBaseLogger {
77
96
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"telemetryTypes.d.ts","sourceRoot":"","sources":["../src/telemetryTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAEzF;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEzE;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GACtC,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,GAC7B;IACA,CAAC,GAAG,EAAE,MAAM,GACZ,AADe,gEAAgE;IAC/E,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CACrE,CAAC;AAEL;;;;;;GAMG;AACH,MAAM,WAAW,+BAA+B;IAC/C,KAAK,EAAE,6BAA6B,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC,CAAC,KAAK,EAAE,MAAM,GAAG,6BAA6B,GAAG,MAAM,CAAC,6BAA6B,CAAC,CAAC;CACvF;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACvE,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,6BAA8B,SAAQ,yBAAyB;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAChE;;;;;OAKG;IACH,kBAAkB,CACjB,KAAK,EAAE,yBAAyB,EAChC,KAAK,CAAC,EAAE,OAAO,EACf,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,OAAO,GAAG,OAAO,QAAQ,CAAC,OAAO,GAC1D,IAAI,CAAC;IAER;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,uBAAuB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAEtE;;;;;OAKG;IACH,oBAAoB,CACnB,KAAK,EAAE,6BAA6B,EACpC,KAAK,CAAC,EAAE,OAAO,EACf,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,OAAO,GAAG,OAAO,QAAQ,CAAC,OAAO,GAC1D,IAAI,CAAC;CACR"}
1
+ {"version":3,"file":"telemetryTypes.d.ts","sourceRoot":"","sources":["../src/telemetryTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAEzF;;;;;;;;;GASG;AACH,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEzE;;;;;;;;GAQG;AACH,MAAM,MAAM,6BAA6B,GACtC,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,GAC7B;IACA,CAAC,GAAG,EAAE,MAAM,GACZ,AADe,gEAAgE;IAC/E,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CACrE,CAAC;AAEL;;;;;;;GAOG;AACH,MAAM,WAAW,+BAA+B;IAC/C,KAAK,EAAE,6BAA6B,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACvC,CAAC,KAAK,EAAE,MAAM,GAAG,6BAA6B,GAAG,MAAM,CAAC,6BAA6B,CAAC,CAAC;CACvF;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACvE,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,6BAA8B,SAAQ,yBAAyB;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAChE;;;;;OAKG;IACH,kBAAkB,CACjB,KAAK,EAAE,yBAAyB,EAChC,KAAK,CAAC,EAAE,OAAO,EACf,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,OAAO,GAAG,OAAO,QAAQ,CAAC,OAAO,GAC1D,IAAI,CAAC;IAER;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,uBAAuB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAEtE;;;;;OAKG;IACH,oBAAoB,CACnB,KAAK,EAAE,6BAA6B,EACpC,KAAK,CAAC,EAAE,OAAO,EACf,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,OAAO,GAAG,OAAO,QAAQ,CAAC,OAAO,GAC1D,IAAI,CAAC;CACR"}
@@ -1 +1 @@
1
- {"version":3,"file":"telemetryTypes.js","sourceRoot":"","sources":["../src/telemetryTypes.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger, LogLevel, Tagged } from \"@fluidframework/core-interfaces\";\n\n/**\n * The categories FF uses when instrumenting the code.\n *\n * generic - Informational log event\n * error - Error log event, ideally 0 of these are logged during a session\n * performance - Includes duration, and often has _start, _end, or _cancel suffixes for activity tracking\n */\nexport type TelemetryEventCategory = \"generic\" | \"error\" | \"performance\";\n\n/**\n * Property types that can be logged.\n * Includes extra types beyond TelemetryBaseEventPropertyType, which must be converted before sending to a base logger\n */\nexport type TelemetryEventPropertyTypeExt =\n\t| string\n\t| number\n\t| boolean\n\t| undefined\n\t| (string | number | boolean)[]\n\t| {\n\t\t\t[key: string]: // Flat objects can have the same properties as the event itself\n\t\t\tstring | number | boolean | undefined | (string | number | boolean)[];\n\t };\n\n/**\n * A property to be logged to telemetry containing both the value and a tag. Tags are generic strings that can be used\n * to mark pieces of information that should be organized or handled differently by loggers in various first or third\n * party scenarios. For example, tags are used to mark personal information that should not be stored in logs.\n *\n * @deprecated Use Tagged<TelemetryEventPropertyTypeExt>\n */\nexport interface ITaggedTelemetryPropertyTypeExt {\n\tvalue: TelemetryEventPropertyTypeExt;\n\ttag: string;\n}\n\n/**\n * JSON-serializable properties, which will be logged with telemetry.\n */\nexport interface ITelemetryPropertiesExt {\n\t[index: string]: TelemetryEventPropertyTypeExt | Tagged<TelemetryEventPropertyTypeExt>;\n}\n\n/**\n * Interface for logging telemetry statements.\n * Can contain any number of properties that get serialized as json payload.\n * @param category - category of the event, like \"error\", \"performance\", \"generic\", etc.\n * @param eventName - name of the event.\n */\nexport interface ITelemetryEventExt extends ITelemetryPropertiesExt {\n\tcategory: string;\n\teventName: string;\n}\n\n/**\n * Informational (non-error) telemetry event\n * Maps to category = \"generic\"\n */\nexport interface ITelemetryGenericEventExt extends ITelemetryPropertiesExt {\n\teventName: string;\n\tcategory?: TelemetryEventCategory;\n}\n\n/**\n * Error telemetry event.\n * Maps to category = \"error\"\n */\nexport interface ITelemetryErrorEventExt extends ITelemetryPropertiesExt {\n\teventName: string;\n}\n\n/**\n * Performance telemetry event.\n * Maps to category = \"performance\"\n */\nexport interface ITelemetryPerformanceEventExt extends ITelemetryGenericEventExt {\n\tduration?: number; // Duration of event (optional)\n}\n\n/**\n * An extended TelemetryLogger interface which allows for more lenient event types.\n * This interface is meant to be used internally within the Fluid Framework,\n * and ITelemetryBaseLogger should be used when loggers are passed between layers.\n */\nexport interface ITelemetryLoggerExt extends ITelemetryBaseLogger {\n\t/**\n\t * Send information telemetry event\n\t * @param event - Event to send\n\t * @param error - optional error object to log\n\t * @param logLevel - optional level of the log.\n\t */\n\tsendTelemetryEvent(\n\t\tevent: ITelemetryGenericEventExt,\n\t\terror?: unknown,\n\t\tlogLevel?: typeof LogLevel.verbose | typeof LogLevel.default,\n\t): void;\n\n\t/**\n\t * Send error telemetry event\n\t * @param event - Event to send\n\t * @param error - optional error object to log\n\t */\n\tsendErrorEvent(event: ITelemetryErrorEventExt, error?: unknown): void;\n\n\t/**\n\t * Send performance telemetry event\n\t * @param event - Event to send\n\t * @param error - optional error object to log\n\t * @param logLevel - optional level of the log.\n\t */\n\tsendPerformanceEvent(\n\t\tevent: ITelemetryPerformanceEventExt,\n\t\terror?: unknown,\n\t\tlogLevel?: typeof LogLevel.verbose | typeof LogLevel.default,\n\t): void;\n}\n"]}
1
+ {"version":3,"file":"telemetryTypes.js","sourceRoot":"","sources":["../src/telemetryTypes.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger, LogLevel, Tagged } from \"@fluidframework/core-interfaces\";\n\n/**\n * The categories FF uses when instrumenting the code.\n *\n * generic - Informational log event\n *\n * error - Error log event, ideally 0 of these are logged during a session\n *\n * performance - Includes duration, and often has _start, _end, or _cancel suffixes for activity tracking\n * @alpha\n */\nexport type TelemetryEventCategory = \"generic\" | \"error\" | \"performance\";\n\n/**\n * Property types that can be logged.\n *\n * @remarks\n * Includes extra types beyond {@link @fluidframework/core-interfaces#TelemetryBaseEventPropertyType}, which must be\n * converted before sending to a base logger.\n *\n * @alpha\n */\nexport type TelemetryEventPropertyTypeExt =\n\t| string\n\t| number\n\t| boolean\n\t| undefined\n\t| (string | number | boolean)[]\n\t| {\n\t\t\t[key: string]: // Flat objects can have the same properties as the event itself\n\t\t\tstring | number | boolean | undefined | (string | number | boolean)[];\n\t };\n\n/**\n * A property to be logged to telemetry containing both the value and a tag. Tags are generic strings that can be used\n * to mark pieces of information that should be organized or handled differently by loggers in various first or third\n * party scenarios. For example, tags are used to mark personal information that should not be stored in logs.\n *\n * @deprecated Use {@link @fluidframework/core-interfaces#Tagged}\\<{@link TelemetryEventPropertyTypeExt}\\>\n * @internal\n */\nexport interface ITaggedTelemetryPropertyTypeExt {\n\tvalue: TelemetryEventPropertyTypeExt;\n\ttag: string;\n}\n\n/**\n * JSON-serializable properties, which will be logged with telemetry.\n *\n * @alpha\n */\nexport interface ITelemetryPropertiesExt {\n\t[index: string]: TelemetryEventPropertyTypeExt | Tagged<TelemetryEventPropertyTypeExt>;\n}\n\n/**\n * Interface for logging telemetry statements.\n * @remarks May contain any number of properties that get serialized as json payload.\n * @param category - category of the event, like \"error\", \"performance\", \"generic\", etc.\n * @param eventName - name of the event.\n *\n * @internal\n */\nexport interface ITelemetryEventExt extends ITelemetryPropertiesExt {\n\tcategory: string;\n\teventName: string;\n}\n\n/**\n * Informational (non-error) telemetry event\n * @remarks Maps to category = \"generic\"\n * @alpha\n */\nexport interface ITelemetryGenericEventExt extends ITelemetryPropertiesExt {\n\teventName: string;\n\tcategory?: TelemetryEventCategory;\n}\n\n/**\n * Error telemetry event.\n * @remarks Maps to category = \"error\"\n * @alpha\n */\nexport interface ITelemetryErrorEventExt extends ITelemetryPropertiesExt {\n\teventName: string;\n}\n\n/**\n * Performance telemetry event.\n * @remarks Maps to category = \"performance\"\n * @alpha\n */\nexport interface ITelemetryPerformanceEventExt extends ITelemetryGenericEventExt {\n\tduration?: number; // Duration of event (optional)\n}\n\n/**\n * An extended {@link @fluidframework/core-interfaces#ITelemetryBaseLogger} which allows for more lenient event types.\n *\n * @remarks\n * This interface is meant to be used internally within the Fluid Framework,\n * and `ITelemetryBaseLogger` should be used when loggers are passed between layers.\n * @alpha\n */\nexport interface ITelemetryLoggerExt extends ITelemetryBaseLogger {\n\t/**\n\t * Send information telemetry event\n\t * @param event - Event to send\n\t * @param error - optional error object to log\n\t * @param logLevel - optional level of the log.\n\t */\n\tsendTelemetryEvent(\n\t\tevent: ITelemetryGenericEventExt,\n\t\terror?: unknown,\n\t\tlogLevel?: typeof LogLevel.verbose | typeof LogLevel.default,\n\t): void;\n\n\t/**\n\t * Send error telemetry event\n\t * @param event - Event to send\n\t * @param error - optional error object to log\n\t */\n\tsendErrorEvent(event: ITelemetryErrorEventExt, error?: unknown): void;\n\n\t/**\n\t * Send performance telemetry event\n\t * @param event - Event to send\n\t * @param error - optional error object to log\n\t * @param logLevel - optional level of the log.\n\t */\n\tsendPerformanceEvent(\n\t\tevent: ITelemetryPerformanceEventExt,\n\t\terror?: unknown,\n\t\tlogLevel?: typeof LogLevel.verbose | typeof LogLevel.default,\n\t): void;\n}\n"]}
@@ -4,8 +4,9 @@
4
4
  */
5
5
  import { ITelemetryLoggerExt } from "./telemetryTypes";
6
6
  /**
7
- * Utility counter which will send event only if the provided value
8
- * is above a configured threshold
7
+ * Utility counter which will send event only if the provided value is above a configured threshold.
8
+ *
9
+ * @internal
9
10
  */
10
11
  export declare class ThresholdCounter {
11
12
  private readonly threshold;
@@ -1 +1 @@
1
- {"version":3,"file":"thresholdCounter.d.ts","sourceRoot":"","sources":["../src/thresholdCounter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;GAGG;AACH,qBAAa,gBAAgB;IAE3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,iBAAiB;gBAFR,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,mBAAmB,EACpC,iBAAiB,SAAY;IAGtC;;OAEG;IACI,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAUnD;;;;;;OAMG;IACI,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAU7D"}
1
+ {"version":3,"file":"thresholdCounter.d.ts","sourceRoot":"","sources":["../src/thresholdCounter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;GAIG;AACH,qBAAa,gBAAgB;IAE3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,iBAAiB;gBAFR,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,mBAAmB,EACpC,iBAAiB,SAAY;IAGtC;;OAEG;IACI,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAUnD;;;;;;OAMG;IACI,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAU7D"}
@@ -6,8 +6,9 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.ThresholdCounter = void 0;
8
8
  /**
9
- * Utility counter which will send event only if the provided value
10
- * is above a configured threshold
9
+ * Utility counter which will send event only if the provided value is above a configured threshold.
10
+ *
11
+ * @internal
11
12
  */
12
13
  class ThresholdCounter {
13
14
  constructor(threshold, logger, thresholdMultiple = threshold) {
@@ -1 +1 @@
1
- {"version":3,"file":"thresholdCounter.js","sourceRoot":"","sources":["../src/thresholdCounter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH;;;GAGG;AACH,MAAa,gBAAgB;IAC5B,YACkB,SAAiB,EACjB,MAA2B,EACpC,oBAAoB,SAAS;QAFpB,cAAS,GAAT,SAAS,CAAQ;QACjB,WAAM,GAAN,MAAM,CAAqB;QACpC,sBAAiB,GAAjB,iBAAiB,CAAY;IACnC,CAAC;IAEJ;;OAEG;IACI,IAAI,CAAC,SAAiB,EAAE,KAAa;QAC3C,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;YAC3B,OAAO;SACP;QACD,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;YAChC,SAAS;YACT,KAAK;SACL,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACI,cAAc,CAAC,SAAiB,EAAE,KAAa;QACrD,IAAI,KAAK,KAAK,IAAI,CAAC,iBAAiB,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;gBAChC,SAAS;gBACT,KAAK;aACL,CAAC,CAAC;YACH,sCAAsC;YACtC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;SACpD;IACF,CAAC;CACD;AArCD,4CAqCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLoggerExt } from \"./telemetryTypes\";\n\n/**\n * Utility counter which will send event only if the provided value\n * is above a configured threshold\n */\nexport class ThresholdCounter {\n\tpublic constructor(\n\t\tprivate readonly threshold: number,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate thresholdMultiple = threshold,\n\t) {}\n\n\t/**\n\t * Sends the value if it's above the treshold.\n\t */\n\tpublic send(eventName: string, value: number): void {\n\t\tif (value < this.threshold) {\n\t\t\treturn;\n\t\t}\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName,\n\t\t\tvalue,\n\t\t});\n\t}\n\n\t/**\n\t * Sends the value if it's above the threshold\n\t * and a multiple of the threshold.\n\t *\n\t * To be used in scenarios where we'd like to record a\n\t * threshold violation while reducing telemetry noise.\n\t */\n\tpublic sendIfMultiple(eventName: string, value: number): void {\n\t\tif (value === this.thresholdMultiple) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName,\n\t\t\t\tvalue,\n\t\t\t});\n\t\t\t// reduce number of \"multiple\" events.\n\t\t\tthis.thresholdMultiple = this.thresholdMultiple * 2;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"thresholdCounter.js","sourceRoot":"","sources":["../src/thresholdCounter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH;;;;GAIG;AACH,MAAa,gBAAgB;IAC5B,YACkB,SAAiB,EACjB,MAA2B,EACpC,oBAAoB,SAAS;QAFpB,cAAS,GAAT,SAAS,CAAQ;QACjB,WAAM,GAAN,MAAM,CAAqB;QACpC,sBAAiB,GAAjB,iBAAiB,CAAY;IACnC,CAAC;IAEJ;;OAEG;IACI,IAAI,CAAC,SAAiB,EAAE,KAAa;QAC3C,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;YAC3B,OAAO;SACP;QACD,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;YAChC,SAAS;YACT,KAAK;SACL,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACI,cAAc,CAAC,SAAiB,EAAE,KAAa;QACrD,IAAI,KAAK,KAAK,IAAI,CAAC,iBAAiB,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;gBAChC,SAAS;gBACT,KAAK;aACL,CAAC,CAAC;YACH,sCAAsC;YACtC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;SACpD;IACF,CAAC;CACD;AArCD,4CAqCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLoggerExt } from \"./telemetryTypes\";\n\n/**\n * Utility counter which will send event only if the provided value is above a configured threshold.\n *\n * @internal\n */\nexport class ThresholdCounter {\n\tpublic constructor(\n\t\tprivate readonly threshold: number,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate thresholdMultiple = threshold,\n\t) {}\n\n\t/**\n\t * Sends the value if it's above the treshold.\n\t */\n\tpublic send(eventName: string, value: number): void {\n\t\tif (value < this.threshold) {\n\t\t\treturn;\n\t\t}\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName,\n\t\t\tvalue,\n\t\t});\n\t}\n\n\t/**\n\t * Sends the value if it's above the threshold\n\t * and a multiple of the threshold.\n\t *\n\t * To be used in scenarios where we'd like to record a\n\t * threshold violation while reducing telemetry noise.\n\t */\n\tpublic sendIfMultiple(eventName: string, value: number): void {\n\t\tif (value === this.thresholdMultiple) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName,\n\t\t\t\tvalue,\n\t\t\t});\n\t\t\t// reduce number of \"multiple\" events.\n\t\t\tthis.thresholdMultiple = this.thresholdMultiple * 2;\n\t\t}\n\t}\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.38.0"
8
+ "packageVersion": "7.38.3"
9
9
  }
10
10
  ]
11
11
  }
package/dist/utils.d.ts CHANGED
@@ -10,6 +10,12 @@ import { ITelemetryLoggerExt } from "./telemetryTypes";
10
10
  * @param logger - The logger to log with
11
11
  * @param event - The string or event to log
12
12
  * @returns The outcome of the condition
13
+ *
14
+ * @internal
15
+ *
16
+ * @deprecated
17
+ * This API will be removed in a future release.
18
+ * No replacement API is intended, but reproducing its behavior should be trivial for anyone who needs it.
13
19
  */
14
20
  export declare function logIfFalse(condition: unknown, logger: ITelemetryBaseLogger, event: string | ITelemetryGenericEvent): condition is true;
15
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAEN,oBAAoB,EACpB,sBAAsB,EACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAA6B,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAElF;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,MAAM,GAAG,sBAAsB,GACpC,SAAS,IAAI,IAAI,CAUnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,MAAM,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IACnE;;;;;;;OAOG;IACH,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,mBAAmB,EAC3B,YAAY,CAAC,EAAE,aAAa,GAC1B,uBAAuB,CAiCzB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAEN,oBAAoB,EACpB,sBAAsB,EACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAA6B,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAElF;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACzB,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,MAAM,GAAG,sBAAsB,GACpC,SAAS,IAAI,IAAI,CAUnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,MAAM,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IACnE;;;;;;;OAOG;IACH,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,mBAAmB,EAC3B,YAAY,CAAC,EAAE,aAAa,GAC1B,uBAAuB,CAiCzB"}
package/dist/utils.js CHANGED
@@ -8,6 +8,12 @@ const config_1 = require("./config");
8
8
  * @param logger - The logger to log with
9
9
  * @param event - The string or event to log
10
10
  * @returns The outcome of the condition
11
+ *
12
+ * @internal
13
+ *
14
+ * @deprecated
15
+ * This API will be removed in a future release.
16
+ * No replacement API is intended, but reproducing its behavior should be trivial for anyone who needs it.
11
17
  */
12
18
  function logIfFalse(condition, logger, event) {
13
19
  if (condition) {
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AASA,qCAAqD;AAGrD;;;;;;GAMG;AACH,SAAgB,UAAU,CACzB,SAAkB,EAClB,MAA4B,EAC5B,KAAsC;IAEtC,IAAI,SAAS,EAAE;QACd,OAAO,IAAI,CAAC;KACZ;IACD,MAAM,QAAQ,GACb,OAAO,KAAK,KAAK,QAAQ;QACxB,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE;QACzC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;IACpC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,KAAK,CAAC;AACd,CAAC;AAdD,gCAcC;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,mBAAmB,CAClC,MAA2B,EAC3B,YAA4B;IAE5B,MAAM,iBAAiB,GAAG,IAAA,kCAAyB,EAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,kBAAkB,GACvB,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,iCAAiC,CAAC,IAAI,KAAK,CAAC;IAEjF,MAAM,aAAa,GAAG;QACrB,IAAI,EAAE,CAAC,KAA0B,EAAQ,EAAE;YAC1C,2DAA2D;YAC3D,gIAAgI;YAChI,2LAA2L;YAC3L,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACnB;QACF,CAAC;QACD,kBAAkB,EAAE,CAAC,KAAgC,EAAQ,EAAE;YAC9D,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;aACjC;QACF,CAAC;QACD,cAAc,EAAE,CAAC,KAAgC,EAAQ,EAAE;YAC1D,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;aAC7B;QACF,CAAC;QACD,oBAAoB,EAAE,CAAC,KAAgC,EAAQ,EAAE;YAChE,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;aACnC;QACF,CAAC;QACD,kBAAkB;KAClB,CAAC;IAEF,OAAO,aAAa,CAAC;AACtB,CAAC;AApCD,kDAoCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport {\n\tITelemetryBaseEvent,\n\tITelemetryBaseLogger,\n\tITelemetryGenericEvent,\n} from \"@fluidframework/core-interfaces\";\nimport { loggerToMonitoringContext } from \"./config\";\nimport { ITelemetryGenericEventExt, ITelemetryLoggerExt } from \"./telemetryTypes\";\n\n/**\n * Like assert, but logs only if the condition is false, rather than throwing\n * @param condition - The condition to attest too\n * @param logger - The logger to log with\n * @param event - The string or event to log\n * @returns The outcome of the condition\n */\nexport function logIfFalse(\n\tcondition: unknown,\n\tlogger: ITelemetryBaseLogger,\n\tevent: string | ITelemetryGenericEvent,\n): condition is true {\n\tif (condition) {\n\t\treturn true;\n\t}\n\tconst newEvent: ITelemetryBaseEvent =\n\t\ttypeof event === \"string\"\n\t\t\t? { eventName: event, category: \"error\" }\n\t\t\t: { category: \"error\", ...event };\n\tlogger.send(newEvent);\n\treturn false;\n}\n\n/**\n * An object that contains a callback used in conjunction with the {@link createSampledLogger} utility function to provide custom logic for sampling events.\n *\n * @internal\n */\nexport interface IEventSampler {\n\t/**\n\t * @returns true if the event should be sampled or false if not\n\t */\n\tsample: () => boolean | undefined;\n}\n\n/**\n * A telemetry logger that has sampling capabilities\n *\n * @internal\n */\nexport interface ISampledTelemetryLogger extends ITelemetryLoggerExt {\n\t/**\n\t * Indicates if the feature flag to disable sampling is set.\n\t *\n\t * @remarks Exposed to enable some advanced scenarios where the code using the sampled logger\n\t * could take advantage of skipping the execution of some logic when it can determine\n\t * it won't be necessary because the telemetry event that needs it wouldn't be\n\t * emitted anyway.\n\t */\n\tisSamplingDisabled: boolean;\n}\n\n/**\n * Wraps around an existing logger matching the {@link ITelemetryLoggerExt} interface and provides the ability to only log a subset of events using a sampling strategy provided by an ${@link IEventSampler}.\n * You can chose to not provide an event sampler which is effectively a no-op, meaning that it will be treated as if the sampler always returns true.\n *\n * @remarks\n * The sampling functionality uses the Fluid telemetry logging configuration along with the optionally provided event sampling callback to determine whether an event should\n * be logged or not.\n *\n * Configuration object parameters:\n * 'Fluid.Telemetry.DisableSampling': if this config value is set to true, all events will be unsampled and therefore logged.\n * Otherwise only a sample will be logged according to the provided event sampler callback.\n *\n * Note that the same sampler is used for all APIs of the returned logger. If you want separate events flowing through the returned logger to be sampled separately, the {@link IEventSampler} you provide should track them separately.\n *\n * @internal\n */\nexport function createSampledLogger(\n\tlogger: ITelemetryLoggerExt,\n\teventSampler?: IEventSampler,\n): ISampledTelemetryLogger {\n\tconst monitoringContext = loggerToMonitoringContext(logger);\n\tconst isSamplingDisabled =\n\t\tmonitoringContext.config.getBoolean(\"Fluid.Telemetry.DisableSampling\") ?? false;\n\n\tconst sampledLogger = {\n\t\tsend: (event: ITelemetryBaseEvent): void => {\n\t\t\t// The sampler uses the following logic for sending events:\n\t\t\t// 1. If isSamplingDisabled is true, then this means events should be unsampled. Therefore we send the event without any checks.\n\t\t\t// 2. If isSamplingDisabled is false, then event should be sampled using the event sampler, if the sampler is not defined just send all events, other use the eventSampler.sample() method.\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.send(event);\n\t\t\t}\n\t\t},\n\t\tsendTelemetryEvent: (event: ITelemetryGenericEventExt): void => {\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.sendTelemetryEvent(event);\n\t\t\t}\n\t\t},\n\t\tsendErrorEvent: (event: ITelemetryGenericEventExt): void => {\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.sendErrorEvent(event);\n\t\t\t}\n\t\t},\n\t\tsendPerformanceEvent: (event: ITelemetryGenericEventExt): void => {\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.sendPerformanceEvent(event);\n\t\t\t}\n\t\t},\n\t\tisSamplingDisabled,\n\t};\n\n\treturn sampledLogger;\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AASA,qCAAqD;AAGrD;;;;;;;;;;;;GAYG;AACH,SAAgB,UAAU,CACzB,SAAkB,EAClB,MAA4B,EAC5B,KAAsC;IAEtC,IAAI,SAAS,EAAE;QACd,OAAO,IAAI,CAAC;KACZ;IACD,MAAM,QAAQ,GACb,OAAO,KAAK,KAAK,QAAQ;QACxB,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE;QACzC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;IACpC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,KAAK,CAAC;AACd,CAAC;AAdD,gCAcC;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,mBAAmB,CAClC,MAA2B,EAC3B,YAA4B;IAE5B,MAAM,iBAAiB,GAAG,IAAA,kCAAyB,EAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,kBAAkB,GACvB,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,iCAAiC,CAAC,IAAI,KAAK,CAAC;IAEjF,MAAM,aAAa,GAAG;QACrB,IAAI,EAAE,CAAC,KAA0B,EAAQ,EAAE;YAC1C,2DAA2D;YAC3D,gIAAgI;YAChI,2LAA2L;YAC3L,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACnB;QACF,CAAC;QACD,kBAAkB,EAAE,CAAC,KAAgC,EAAQ,EAAE;YAC9D,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;aACjC;QACF,CAAC;QACD,cAAc,EAAE,CAAC,KAAgC,EAAQ,EAAE;YAC1D,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;aAC7B;QACF,CAAC;QACD,oBAAoB,EAAE,CAAC,KAAgC,EAAQ,EAAE;YAChE,IAAI,kBAAkB,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE;gBAC9E,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;aACnC;QACF,CAAC;QACD,kBAAkB;KAClB,CAAC;IAEF,OAAO,aAAa,CAAC;AACtB,CAAC;AApCD,kDAoCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport {\n\tITelemetryBaseEvent,\n\tITelemetryBaseLogger,\n\tITelemetryGenericEvent,\n} from \"@fluidframework/core-interfaces\";\nimport { loggerToMonitoringContext } from \"./config\";\nimport { ITelemetryGenericEventExt, ITelemetryLoggerExt } from \"./telemetryTypes\";\n\n/**\n * Like assert, but logs only if the condition is false, rather than throwing\n * @param condition - The condition to attest too\n * @param logger - The logger to log with\n * @param event - The string or event to log\n * @returns The outcome of the condition\n *\n * @internal\n *\n * @deprecated\n * This API will be removed in a future release.\n * No replacement API is intended, but reproducing its behavior should be trivial for anyone who needs it.\n */\nexport function logIfFalse(\n\tcondition: unknown,\n\tlogger: ITelemetryBaseLogger,\n\tevent: string | ITelemetryGenericEvent,\n): condition is true {\n\tif (condition) {\n\t\treturn true;\n\t}\n\tconst newEvent: ITelemetryBaseEvent =\n\t\ttypeof event === \"string\"\n\t\t\t? { eventName: event, category: \"error\" }\n\t\t\t: { category: \"error\", ...event };\n\tlogger.send(newEvent);\n\treturn false;\n}\n\n/**\n * An object that contains a callback used in conjunction with the {@link createSampledLogger} utility function to provide custom logic for sampling events.\n *\n * @internal\n */\nexport interface IEventSampler {\n\t/**\n\t * @returns true if the event should be sampled or false if not\n\t */\n\tsample: () => boolean | undefined;\n}\n\n/**\n * A telemetry logger that has sampling capabilities\n *\n * @internal\n */\nexport interface ISampledTelemetryLogger extends ITelemetryLoggerExt {\n\t/**\n\t * Indicates if the feature flag to disable sampling is set.\n\t *\n\t * @remarks Exposed to enable some advanced scenarios where the code using the sampled logger\n\t * could take advantage of skipping the execution of some logic when it can determine\n\t * it won't be necessary because the telemetry event that needs it wouldn't be\n\t * emitted anyway.\n\t */\n\tisSamplingDisabled: boolean;\n}\n\n/**\n * Wraps around an existing logger matching the {@link ITelemetryLoggerExt} interface and provides the ability to only log a subset of events using a sampling strategy provided by an ${@link IEventSampler}.\n * You can chose to not provide an event sampler which is effectively a no-op, meaning that it will be treated as if the sampler always returns true.\n *\n * @remarks\n * The sampling functionality uses the Fluid telemetry logging configuration along with the optionally provided event sampling callback to determine whether an event should\n * be logged or not.\n *\n * Configuration object parameters:\n * 'Fluid.Telemetry.DisableSampling': if this config value is set to true, all events will be unsampled and therefore logged.\n * Otherwise only a sample will be logged according to the provided event sampler callback.\n *\n * Note that the same sampler is used for all APIs of the returned logger. If you want separate events flowing through the returned logger to be sampled separately, the {@link IEventSampler} you provide should track them separately.\n *\n * @internal\n */\nexport function createSampledLogger(\n\tlogger: ITelemetryLoggerExt,\n\teventSampler?: IEventSampler,\n): ISampledTelemetryLogger {\n\tconst monitoringContext = loggerToMonitoringContext(logger);\n\tconst isSamplingDisabled =\n\t\tmonitoringContext.config.getBoolean(\"Fluid.Telemetry.DisableSampling\") ?? false;\n\n\tconst sampledLogger = {\n\t\tsend: (event: ITelemetryBaseEvent): void => {\n\t\t\t// The sampler uses the following logic for sending events:\n\t\t\t// 1. If isSamplingDisabled is true, then this means events should be unsampled. Therefore we send the event without any checks.\n\t\t\t// 2. If isSamplingDisabled is false, then event should be sampled using the event sampler, if the sampler is not defined just send all events, other use the eventSampler.sample() method.\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.send(event);\n\t\t\t}\n\t\t},\n\t\tsendTelemetryEvent: (event: ITelemetryGenericEventExt): void => {\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.sendTelemetryEvent(event);\n\t\t\t}\n\t\t},\n\t\tsendErrorEvent: (event: ITelemetryGenericEventExt): void => {\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.sendErrorEvent(event);\n\t\t\t}\n\t\t},\n\t\tsendPerformanceEvent: (event: ITelemetryGenericEventExt): void => {\n\t\t\tif (isSamplingDisabled || eventSampler === undefined || eventSampler.sample()) {\n\t\t\t\tlogger.sendPerformanceEvent(event);\n\t\t\t}\n\t\t},\n\t\tisSamplingDisabled,\n\t};\n\n\treturn sampledLogger;\n}\n"]}
package/lib/config.d.ts CHANGED
@@ -2,19 +2,14 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
5
+ import { ITelemetryBaseLogger, IConfigProviderBase, ConfigTypes } from "@fluidframework/core-interfaces";
6
6
  import { Lazy } from "@fluidframework/core-utils";
7
7
  import { createChildLogger } from "./logger";
8
8
  import { ITelemetryLoggerExt } from "./telemetryTypes";
9
- export type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;
10
9
  /**
11
- * Base interface for providing configurations to enable/disable/control features
12
- */
13
- export interface IConfigProviderBase {
14
- getRawConfig(name: string): ConfigTypes;
15
- }
16
- /**
17
- * Explicitly typed interface for reading configurations
10
+ * Explicitly typed interface for reading configurations.
11
+ *
12
+ * @internal
18
13
  */
19
14
  export interface IConfigProvider extends IConfigProviderBase {
20
15
  getBoolean(name: string): boolean | undefined;
@@ -28,6 +23,8 @@ export interface IConfigProvider extends IConfigProviderBase {
28
23
  * Creates a base configuration provider based on `sessionStorage`
29
24
  *
30
25
  * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store
26
+ *
27
+ * @internal
31
28
  */
32
29
  export declare const sessionStorageConfigProvider: Lazy<IConfigProviderBase>;
33
30
  /**
@@ -56,14 +53,44 @@ export declare class CachedConfigProvider implements IConfigProvider {
56
53
  private getCacheEntry;
57
54
  }
58
55
  /**
59
- * A type containing both a telemetry logger and a configuration provider
56
+ * A type containing both a telemetry logger and a configuration provider.
57
+ *
58
+ * @internal
60
59
  */
61
60
  export interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt> {
62
61
  config: IConfigProvider;
63
62
  logger: L;
64
63
  }
64
+ /**
65
+ * Determines whether or not the provided object is a {@link MonitoringContext}.
66
+ * @remarks Can be used for type-narrowing.
67
+ *
68
+ * @internal
69
+ */
65
70
  export declare function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(obj: L): obj is L & MonitoringContext<L>;
71
+ /**
72
+ * Creates a {@link MonitoringContext} from the provided logger, if it isn't already one.
73
+ *
74
+ * @internal
75
+ */
66
76
  export declare function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(logger: L): MonitoringContext<L>;
77
+ /**
78
+ * Creates a {@link MonitoringContext} from the provided logger.
79
+ *
80
+ * @remarks
81
+ * Assumes that the provided logger is not itself already a {@link MonitoringContext}, and will throw an error if it is.
82
+ * If you are unsure, use {@link loggerToMonitoringContext} instead.
83
+ *
84
+ * @throws If the provided logger is already a {@link MonitoringContext}.
85
+ *
86
+ * @internal
87
+ */
67
88
  export declare function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(logger: L, ...configs: (IConfigProviderBase | undefined)[]): MonitoringContext<L>;
89
+ /**
90
+ * Creates a child logger with a {@link MonitoringContext}.
91
+ *
92
+ * @see {@link loggerToMonitoringContext}
93
+ * @internal
94
+ */
68
95
  export declare function createChildMonitoringContext(props: Parameters<typeof createChildLogger>[0]): MonitoringContext;
69
96
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/lib/config.js CHANGED
@@ -4,6 +4,8 @@ import { createChildLogger, tagCodeArtifacts } from "./logger";
4
4
  * Creates a base configuration provider based on `sessionStorage`
5
5
  *
6
6
  * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store
7
+ *
8
+ * @internal
7
9
  */
8
10
  export const sessionStorageConfigProvider = new Lazy(() => inMemoryConfigProvider(safeSessionStorage()));
9
11
  const NullConfigProvider = {
@@ -186,16 +188,38 @@ export class CachedConfigProvider {
186
188
  return this.configCache.get(name);
187
189
  }
188
190
  }
191
+ /**
192
+ * Determines whether or not the provided object is a {@link MonitoringContext}.
193
+ * @remarks Can be used for type-narrowing.
194
+ *
195
+ * @internal
196
+ */
189
197
  export function loggerIsMonitoringContext(obj) {
190
198
  const maybeConfig = obj;
191
199
  return isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;
192
200
  }
201
+ /**
202
+ * Creates a {@link MonitoringContext} from the provided logger, if it isn't already one.
203
+ *
204
+ * @internal
205
+ */
193
206
  export function loggerToMonitoringContext(logger) {
194
207
  if (loggerIsMonitoringContext(logger)) {
195
208
  return logger;
196
209
  }
197
210
  return mixinMonitoringContext(logger, sessionStorageConfigProvider.value);
198
211
  }
212
+ /**
213
+ * Creates a {@link MonitoringContext} from the provided logger.
214
+ *
215
+ * @remarks
216
+ * Assumes that the provided logger is not itself already a {@link MonitoringContext}, and will throw an error if it is.
217
+ * If you are unsure, use {@link loggerToMonitoringContext} instead.
218
+ *
219
+ * @throws If the provided logger is already a {@link MonitoringContext}.
220
+ *
221
+ * @internal
222
+ */
199
223
  export function mixinMonitoringContext(logger, ...configs) {
200
224
  if (loggerIsMonitoringContext(logger)) {
201
225
  throw new Error("Logger is already a monitoring context");
@@ -217,6 +241,12 @@ function isConfigProviderBase(obj) {
217
241
  const maybeConfig = obj;
218
242
  return typeof maybeConfig?.getRawConfig === "function";
219
243
  }
244
+ /**
245
+ * Creates a child logger with a {@link MonitoringContext}.
246
+ *
247
+ * @see {@link loggerToMonitoringContext}
248
+ * @internal
249
+ */
220
250
  export function createChildMonitoringContext(props) {
221
251
  return loggerToMonitoringContext(createChildLogger(props));
222
252
  }
package/lib/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { Lazy } from \"@fluidframework/core-utils\";\nimport { createChildLogger, tagCodeArtifacts } from \"./logger\";\nimport { ITelemetryLoggerExt } from \"./telemetryTypes\";\n\nexport type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;\n\n/**\n * Base interface for providing configurations to enable/disable/control features\n */\nexport interface IConfigProviderBase {\n\tgetRawConfig(name: string): ConfigTypes;\n}\n\n/**\n * Explicitly typed interface for reading configurations\n */\nexport interface IConfigProvider extends IConfigProviderBase {\n\tgetBoolean(name: string): boolean | undefined;\n\tgetNumber(name: string): number | undefined;\n\tgetString(name: string): string | undefined;\n\tgetBooleanArray(name: string): boolean[] | undefined;\n\tgetNumberArray(name: string): number[] | undefined;\n\tgetStringArray(name: string): string[] | undefined;\n}\n/**\n * Creates a base configuration provider based on `sessionStorage`\n *\n * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store\n */\nexport const sessionStorageConfigProvider = new Lazy<IConfigProviderBase>(() =>\n\tinMemoryConfigProvider(safeSessionStorage()),\n);\n\nconst NullConfigProvider: IConfigProviderBase = {\n\tgetRawConfig: () => undefined,\n};\n\n/**\n * Creates a base configuration provider based on the supplied `Storage` instance\n *\n * @param storage - instance of `Storage` to be used as storage media for the config\n * @returns A base configuration provider with\n * the supplied `Storage` instance as the underlying config store\n */\nexport const inMemoryConfigProvider = (storage: Storage | undefined): IConfigProviderBase => {\n\tif (storage !== undefined && storage !== null) {\n\t\treturn new CachedConfigProvider(undefined, {\n\t\t\tgetRawConfig: (name: string): ConfigTypes | undefined => {\n\t\t\t\ttry {\n\t\t\t\t\treturn stronglyTypedParse(storage.getItem(name) ?? undefined)?.raw;\n\t\t\t\t} catch {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\treturn NullConfigProvider;\n};\n\ninterface ConfigTypeStringToType {\n\tnumber: number;\n\tstring: string;\n\tboolean: boolean;\n\t[\"number[]\"]: number[];\n\t[\"string[]\"]: string[];\n\t[\"boolean[]\"]: boolean[];\n}\n\ntype PrimitiveTypeStrings = \"number\" | \"string\" | \"boolean\";\n\nfunction isPrimitiveType(type: string): type is PrimitiveTypeStrings {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\tcase \"number\":\n\t\tcase \"string\": {\n\t\t\treturn true;\n\t\t}\n\t\tdefault: {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\ninterface StronglyTypedValue extends Partial<ConfigTypeStringToType> {\n\traw: ConfigTypes;\n}\n/**\n * Takes any supported config type, and returns the value with a strong type. If the type of\n * the config is not a supported type undefined will be returned.\n * The user of this function should cache the result to avoid duplicated work.\n *\n * Strings will be attempted to be parsed and coerced into a strong config type.\n * if it is not possible to parsed and coerce a string to a strong config type the original string\n * will be return with a string type for the consumer to handle further if necessary.\n */\nfunction stronglyTypedParse(input: ConfigTypes): StronglyTypedValue | undefined {\n\tlet output: ConfigTypes = input;\n\tlet defaultReturn: Pick<StronglyTypedValue, \"raw\" | \"string\"> | undefined;\n\t// we do special handling for strings to try and coerce\n\t// them into a config type if we can. This makes it easy\n\t// for config sources like sessionStorage which only\n\t// holds strings\n\tif (typeof input === \"string\") {\n\t\ttry {\n\t\t\toutput = JSON.parse(input) as ConfigTypes;\n\t\t\t// we succeeded in parsing, but we don't support parsing\n\t\t\t// for any object as we can't do it type safely\n\t\t\t// so in this case, the default return will be string\n\t\t\t// rather than undefined, and the consumer\n\t\t\t// can parse, as we don't want to provide\n\t\t\t// a false sense of security by just\n\t\t\t// casting.\n\t\t\tdefaultReturn = { raw: input, string: input };\n\t\t} catch {\n\t\t\t// No-op\n\t\t}\n\t}\n\n\tif (output === undefined) {\n\t\treturn defaultReturn;\n\t}\n\n\tconst outputType = typeof output;\n\tif (isPrimitiveType(outputType)) {\n\t\treturn { ...defaultReturn, raw: input, [outputType]: output };\n\t}\n\n\tif (Array.isArray(output)) {\n\t\tconst firstType = typeof output[0];\n\t\t// ensure the first elements is a primitive type\n\t\tif (!isPrimitiveType(firstType)) {\n\t\t\treturn defaultReturn;\n\t\t}\n\t\t// ensue all the elements types are homogeneous\n\t\t// aka they all have the same type as the first\n\t\tfor (const v of output) {\n\t\t\tif (typeof v !== firstType) {\n\t\t\t\treturn defaultReturn;\n\t\t\t}\n\t\t}\n\t\treturn { ...defaultReturn, raw: input, [`${firstType}[]`]: output };\n\t}\n\n\treturn defaultReturn;\n}\n\n/**\n * `sessionStorage` is undefined in some environments such as Node and web pages with session storage disabled.\n */\nconst safeSessionStorage = (): Storage | undefined => {\n\t// For some configurations accessing \"globalThis.sessionStorage\" throws\n\t// \"'sessionStorage' property from 'Window': Access is denied for this document\" rather than returning undefined.\n\t// Therefor check for it before accessing.\n\ttry {\n\t\t// Using globalThis and checking for undefined is preferred over just accessing global sessionStorage\n\t\t// since it avoids an exception when running in node.\n\t\t// In some cases this has returned null when disabled in the browser, so ensure its undefined in that case:\n\t\treturn globalThis.sessionStorage ?? undefined;\n\t} catch {\n\t\t// For browsers which error on the above when session storage is disabled:\n\t\treturn undefined;\n\t}\n};\n\n/**\n * Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances\n */\nexport class CachedConfigProvider implements IConfigProvider {\n\tprivate readonly configCache = new Map<string, StronglyTypedValue>();\n\tprivate readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];\n\n\tconstructor(\n\t\tprivate readonly logger?: ITelemetryBaseLogger,\n\t\t...orderedBaseProviders: (IConfigProviderBase | undefined)[]\n\t) {\n\t\tthis.orderedBaseProviders = [];\n\t\tconst knownProviders = new Set<IConfigProviderBase>();\n\t\tconst candidateProviders = [...orderedBaseProviders];\n\t\twhile (candidateProviders.length > 0) {\n\t\t\tconst baseProvider = candidateProviders.shift()!;\n\t\t\tif (\n\t\t\t\tbaseProvider !== undefined &&\n\t\t\t\tisConfigProviderBase(baseProvider) &&\n\t\t\t\t!knownProviders.has(baseProvider)\n\t\t\t) {\n\t\t\t\tknownProviders.add(baseProvider);\n\t\t\t\tif (baseProvider instanceof CachedConfigProvider) {\n\t\t\t\t\tcandidateProviders.push(...baseProvider.orderedBaseProviders);\n\t\t\t\t} else {\n\t\t\t\t\tthis.orderedBaseProviders.push(baseProvider);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tgetBoolean(name: string): boolean | undefined {\n\t\treturn this.getCacheEntry(name)?.boolean;\n\t}\n\tgetNumber(name: string): number | undefined {\n\t\treturn this.getCacheEntry(name)?.number;\n\t}\n\tgetString(name: string): string | undefined {\n\t\treturn this.getCacheEntry(name)?.string;\n\t}\n\tgetBooleanArray(name: string): boolean[] | undefined {\n\t\treturn this.getCacheEntry(name)?.[\"boolean[]\"];\n\t}\n\tgetNumberArray(name: string): number[] | undefined {\n\t\treturn this.getCacheEntry(name)?.[\"number[]\"];\n\t}\n\tgetStringArray(name: string): string[] | undefined {\n\t\treturn this.getCacheEntry(name)?.[\"string[]\"];\n\t}\n\n\tgetRawConfig(name: string): ConfigTypes {\n\t\treturn this.getCacheEntry(name)?.raw;\n\t}\n\n\tprivate getCacheEntry(name: string): StronglyTypedValue | undefined {\n\t\tif (!this.configCache.has(name)) {\n\t\t\tfor (const provider of this.orderedBaseProviders) {\n\t\t\t\tconst parsed = stronglyTypedParse(provider?.getRawConfig(name));\n\t\t\t\tif (parsed !== undefined) {\n\t\t\t\t\tthis.configCache.set(name, parsed);\n\t\t\t\t\tthis.logger?.send({\n\t\t\t\t\t\tcategory: \"generic\",\n\t\t\t\t\t\teventName: \"ConfigRead\",\n\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\tconfigName: name,\n\t\t\t\t\t\t\tconfigValue: JSON.stringify(parsed),\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// configs are immutable, if the first lookup returned no results, all lookups should\n\t\t\tthis.configCache.set(name, { raw: undefined });\n\t\t}\n\t\treturn this.configCache.get(name);\n\t}\n}\n\n/**\n * A type containing both a telemetry logger and a configuration provider\n */\nexport interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt> {\n\tconfig: IConfigProvider;\n\tlogger: L;\n}\n\nexport function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(\n\tobj: L,\n): obj is L & MonitoringContext<L> {\n\tconst maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;\n\treturn isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;\n}\n\nexport function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(\n\tlogger: L,\n): MonitoringContext<L> {\n\tif (loggerIsMonitoringContext<L>(logger)) {\n\t\treturn logger;\n\t}\n\treturn mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);\n}\n\nexport function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(\n\tlogger: L,\n\t...configs: (IConfigProviderBase | undefined)[]\n): MonitoringContext<L> {\n\tif (loggerIsMonitoringContext<L>(logger)) {\n\t\tthrow new Error(\"Logger is already a monitoring context\");\n\t}\n\t/**\n\t * this is the tricky bit we use for now to smuggle monitoring context around.\n\t * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.\n\t * We then expose it as a Monitoring context, so via types we hide the outer logger methods.\n\t * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext\n\t * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties\n\t * of the MonitoringContext and get the config provider.\n\t */\n\tconst mc: L & Partial<MonitoringContext<L>> = logger;\n\tmc.config = new CachedConfigProvider(logger, ...configs);\n\tmc.logger = logger;\n\treturn mc as MonitoringContext<L>;\n}\n\nfunction isConfigProviderBase(obj: unknown): obj is IConfigProviderBase {\n\tconst maybeConfig = obj as Partial<IConfigProviderBase> | undefined;\n\treturn typeof maybeConfig?.getRawConfig === \"function\";\n}\n\nexport function createChildMonitoringContext(\n\tprops: Parameters<typeof createChildLogger>[0],\n): MonitoringContext {\n\treturn loggerToMonitoringContext(createChildLogger(props));\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport {\n\tITelemetryBaseLogger,\n\tIConfigProviderBase,\n\tConfigTypes,\n} from \"@fluidframework/core-interfaces\";\nimport { Lazy } from \"@fluidframework/core-utils\";\nimport { createChildLogger, tagCodeArtifacts } from \"./logger\";\nimport { ITelemetryLoggerExt } from \"./telemetryTypes\";\n\n/**\n * Explicitly typed interface for reading configurations.\n *\n * @internal\n */\nexport interface IConfigProvider extends IConfigProviderBase {\n\tgetBoolean(name: string): boolean | undefined;\n\tgetNumber(name: string): number | undefined;\n\tgetString(name: string): string | undefined;\n\tgetBooleanArray(name: string): boolean[] | undefined;\n\tgetNumberArray(name: string): number[] | undefined;\n\tgetStringArray(name: string): string[] | undefined;\n}\n/**\n * Creates a base configuration provider based on `sessionStorage`\n *\n * @returns A lazy initialized base configuration provider with `sessionStorage` as the underlying config store\n *\n * @internal\n */\nexport const sessionStorageConfigProvider = new Lazy<IConfigProviderBase>(() =>\n\tinMemoryConfigProvider(safeSessionStorage()),\n);\n\nconst NullConfigProvider: IConfigProviderBase = {\n\tgetRawConfig: () => undefined,\n};\n\n/**\n * Creates a base configuration provider based on the supplied `Storage` instance\n *\n * @param storage - instance of `Storage` to be used as storage media for the config\n * @returns A base configuration provider with\n * the supplied `Storage` instance as the underlying config store\n */\nexport const inMemoryConfigProvider = (storage: Storage | undefined): IConfigProviderBase => {\n\tif (storage !== undefined && storage !== null) {\n\t\treturn new CachedConfigProvider(undefined, {\n\t\t\tgetRawConfig: (name: string): ConfigTypes | undefined => {\n\t\t\t\ttry {\n\t\t\t\t\treturn stronglyTypedParse(storage.getItem(name) ?? undefined)?.raw;\n\t\t\t\t} catch {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\treturn NullConfigProvider;\n};\n\ninterface ConfigTypeStringToType {\n\tnumber: number;\n\tstring: string;\n\tboolean: boolean;\n\t[\"number[]\"]: number[];\n\t[\"string[]\"]: string[];\n\t[\"boolean[]\"]: boolean[];\n}\n\ntype PrimitiveTypeStrings = \"number\" | \"string\" | \"boolean\";\n\nfunction isPrimitiveType(type: string): type is PrimitiveTypeStrings {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\tcase \"number\":\n\t\tcase \"string\": {\n\t\t\treturn true;\n\t\t}\n\t\tdefault: {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\ninterface StronglyTypedValue extends Partial<ConfigTypeStringToType> {\n\traw: ConfigTypes;\n}\n/**\n * Takes any supported config type, and returns the value with a strong type. If the type of\n * the config is not a supported type undefined will be returned.\n * The user of this function should cache the result to avoid duplicated work.\n *\n * Strings will be attempted to be parsed and coerced into a strong config type.\n * if it is not possible to parsed and coerce a string to a strong config type the original string\n * will be return with a string type for the consumer to handle further if necessary.\n */\nfunction stronglyTypedParse(input: ConfigTypes): StronglyTypedValue | undefined {\n\tlet output: ConfigTypes = input;\n\tlet defaultReturn: Pick<StronglyTypedValue, \"raw\" | \"string\"> | undefined;\n\t// we do special handling for strings to try and coerce\n\t// them into a config type if we can. This makes it easy\n\t// for config sources like sessionStorage which only\n\t// holds strings\n\tif (typeof input === \"string\") {\n\t\ttry {\n\t\t\toutput = JSON.parse(input) as ConfigTypes;\n\t\t\t// we succeeded in parsing, but we don't support parsing\n\t\t\t// for any object as we can't do it type safely\n\t\t\t// so in this case, the default return will be string\n\t\t\t// rather than undefined, and the consumer\n\t\t\t// can parse, as we don't want to provide\n\t\t\t// a false sense of security by just\n\t\t\t// casting.\n\t\t\tdefaultReturn = { raw: input, string: input };\n\t\t} catch {\n\t\t\t// No-op\n\t\t}\n\t}\n\n\tif (output === undefined) {\n\t\treturn defaultReturn;\n\t}\n\n\tconst outputType = typeof output;\n\tif (isPrimitiveType(outputType)) {\n\t\treturn { ...defaultReturn, raw: input, [outputType]: output };\n\t}\n\n\tif (Array.isArray(output)) {\n\t\tconst firstType = typeof output[0];\n\t\t// ensure the first elements is a primitive type\n\t\tif (!isPrimitiveType(firstType)) {\n\t\t\treturn defaultReturn;\n\t\t}\n\t\t// ensue all the elements types are homogeneous\n\t\t// aka they all have the same type as the first\n\t\tfor (const v of output) {\n\t\t\tif (typeof v !== firstType) {\n\t\t\t\treturn defaultReturn;\n\t\t\t}\n\t\t}\n\t\treturn { ...defaultReturn, raw: input, [`${firstType}[]`]: output };\n\t}\n\n\treturn defaultReturn;\n}\n\n/**\n * `sessionStorage` is undefined in some environments such as Node and web pages with session storage disabled.\n */\nconst safeSessionStorage = (): Storage | undefined => {\n\t// For some configurations accessing \"globalThis.sessionStorage\" throws\n\t// \"'sessionStorage' property from 'Window': Access is denied for this document\" rather than returning undefined.\n\t// Therefor check for it before accessing.\n\ttry {\n\t\t// Using globalThis and checking for undefined is preferred over just accessing global sessionStorage\n\t\t// since it avoids an exception when running in node.\n\t\t// In some cases this has returned null when disabled in the browser, so ensure its undefined in that case:\n\t\treturn globalThis.sessionStorage ?? undefined;\n\t} catch {\n\t\t// For browsers which error on the above when session storage is disabled:\n\t\treturn undefined;\n\t}\n};\n\n/**\n * Implementation of {@link IConfigProvider} which contains nested {@link IConfigProviderBase} instances\n */\nexport class CachedConfigProvider implements IConfigProvider {\n\tprivate readonly configCache = new Map<string, StronglyTypedValue>();\n\tprivate readonly orderedBaseProviders: (IConfigProviderBase | undefined)[];\n\n\tconstructor(\n\t\tprivate readonly logger?: ITelemetryBaseLogger,\n\t\t...orderedBaseProviders: (IConfigProviderBase | undefined)[]\n\t) {\n\t\tthis.orderedBaseProviders = [];\n\t\tconst knownProviders = new Set<IConfigProviderBase>();\n\t\tconst candidateProviders = [...orderedBaseProviders];\n\t\twhile (candidateProviders.length > 0) {\n\t\t\tconst baseProvider = candidateProviders.shift()!;\n\t\t\tif (\n\t\t\t\tbaseProvider !== undefined &&\n\t\t\t\tisConfigProviderBase(baseProvider) &&\n\t\t\t\t!knownProviders.has(baseProvider)\n\t\t\t) {\n\t\t\t\tknownProviders.add(baseProvider);\n\t\t\t\tif (baseProvider instanceof CachedConfigProvider) {\n\t\t\t\t\tcandidateProviders.push(...baseProvider.orderedBaseProviders);\n\t\t\t\t} else {\n\t\t\t\t\tthis.orderedBaseProviders.push(baseProvider);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tgetBoolean(name: string): boolean | undefined {\n\t\treturn this.getCacheEntry(name)?.boolean;\n\t}\n\tgetNumber(name: string): number | undefined {\n\t\treturn this.getCacheEntry(name)?.number;\n\t}\n\tgetString(name: string): string | undefined {\n\t\treturn this.getCacheEntry(name)?.string;\n\t}\n\tgetBooleanArray(name: string): boolean[] | undefined {\n\t\treturn this.getCacheEntry(name)?.[\"boolean[]\"];\n\t}\n\tgetNumberArray(name: string): number[] | undefined {\n\t\treturn this.getCacheEntry(name)?.[\"number[]\"];\n\t}\n\tgetStringArray(name: string): string[] | undefined {\n\t\treturn this.getCacheEntry(name)?.[\"string[]\"];\n\t}\n\n\tgetRawConfig(name: string): ConfigTypes {\n\t\treturn this.getCacheEntry(name)?.raw;\n\t}\n\n\tprivate getCacheEntry(name: string): StronglyTypedValue | undefined {\n\t\tif (!this.configCache.has(name)) {\n\t\t\tfor (const provider of this.orderedBaseProviders) {\n\t\t\t\tconst parsed = stronglyTypedParse(provider?.getRawConfig(name));\n\t\t\t\tif (parsed !== undefined) {\n\t\t\t\t\tthis.configCache.set(name, parsed);\n\t\t\t\t\tthis.logger?.send({\n\t\t\t\t\t\tcategory: \"generic\",\n\t\t\t\t\t\teventName: \"ConfigRead\",\n\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\tconfigName: name,\n\t\t\t\t\t\t\tconfigValue: JSON.stringify(parsed),\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// configs are immutable, if the first lookup returned no results, all lookups should\n\t\t\tthis.configCache.set(name, { raw: undefined });\n\t\t}\n\t\treturn this.configCache.get(name);\n\t}\n}\n\n/**\n * A type containing both a telemetry logger and a configuration provider.\n *\n * @internal\n */\nexport interface MonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt> {\n\tconfig: IConfigProvider;\n\tlogger: L;\n}\n\n/**\n * Determines whether or not the provided object is a {@link MonitoringContext}.\n * @remarks Can be used for type-narrowing.\n *\n * @internal\n */\nexport function loggerIsMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(\n\tobj: L,\n): obj is L & MonitoringContext<L> {\n\tconst maybeConfig = obj as Partial<MonitoringContext<L>> | undefined;\n\treturn isConfigProviderBase(maybeConfig?.config) && maybeConfig?.logger !== undefined;\n}\n\n/**\n * Creates a {@link MonitoringContext} from the provided logger, if it isn't already one.\n *\n * @internal\n */\nexport function loggerToMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(\n\tlogger: L,\n): MonitoringContext<L> {\n\tif (loggerIsMonitoringContext<L>(logger)) {\n\t\treturn logger;\n\t}\n\treturn mixinMonitoringContext<L>(logger, sessionStorageConfigProvider.value);\n}\n\n/**\n * Creates a {@link MonitoringContext} from the provided logger.\n *\n * @remarks\n * Assumes that the provided logger is not itself already a {@link MonitoringContext}, and will throw an error if it is.\n * If you are unsure, use {@link loggerToMonitoringContext} instead.\n *\n * @throws If the provided logger is already a {@link MonitoringContext}.\n *\n * @internal\n */\nexport function mixinMonitoringContext<L extends ITelemetryBaseLogger = ITelemetryLoggerExt>(\n\tlogger: L,\n\t...configs: (IConfigProviderBase | undefined)[]\n): MonitoringContext<L> {\n\tif (loggerIsMonitoringContext<L>(logger)) {\n\t\tthrow new Error(\"Logger is already a monitoring context\");\n\t}\n\t/**\n\t * this is the tricky bit we use for now to smuggle monitoring context around.\n\t * To the logger we mixin both config and itself, so mc.logger === logger as it is self-referential.\n\t * We then expose it as a Monitoring context, so via types we hide the outer logger methods.\n\t * To layers that expect just a logger we can pass mc.logger, but this is still a MonitoringContext\n\t * so if a deeper layer then converts that logger to a monitoring context it can find the smuggled properties\n\t * of the MonitoringContext and get the config provider.\n\t */\n\tconst mc: L & Partial<MonitoringContext<L>> = logger;\n\tmc.config = new CachedConfigProvider(logger, ...configs);\n\tmc.logger = logger;\n\treturn mc as MonitoringContext<L>;\n}\n\nfunction isConfigProviderBase(obj: unknown): obj is IConfigProviderBase {\n\tconst maybeConfig = obj as Partial<IConfigProviderBase> | undefined;\n\treturn typeof maybeConfig?.getRawConfig === \"function\";\n}\n\n/**\n * Creates a child logger with a {@link MonitoringContext}.\n *\n * @see {@link loggerToMonitoringContext}\n * @internal\n */\nexport function createChildMonitoringContext(\n\tprops: Parameters<typeof createChildLogger>[0],\n): MonitoringContext {\n\treturn loggerToMonitoringContext(createChildLogger(props));\n}\n"]}
package/lib/error.d.ts CHANGED
@@ -6,6 +6,16 @@ import { IGenericError, IErrorBase, ITelemetryBaseProperties, IUsageError } from
6
6
  import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
7
7
  import { LoggingError } from "./errorLogging";
8
8
  import { IFluidErrorBase } from "./fluidErrorBase";
9
+ /**
10
+ * Throws a UsageError with the given message if the condition is not met.
11
+ * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).
12
+ *
13
+ * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.
14
+ * @param message - The message to include in the error when the condition does not hold.
15
+ * @param props - Telemetry props to include on the error when the condition does not hold.
16
+ * @internal
17
+ */
18
+ export declare function validatePrecondition(condition: boolean, message: string, props?: ITelemetryBaseProperties): asserts condition;
9
19
  /**
10
20
  * Generic wrapper for an unrecognized/uncategorized error object
11
21
  *
@@ -88,6 +98,8 @@ export declare class DataProcessingError extends LoggingError implements IErrorB
88
98
  * Extracts specific properties from the provided message that we know are safe to log.
89
99
  *
90
100
  * @param messageLike - Message to include info about via telemetry props.
101
+ *
102
+ * @internal
91
103
  */
92
104
  export declare const extractSafePropertiesFromMessage: (messageLike: Partial<Pick<ISequencedDocumentMessage, "clientId" | "sequenceNumber" | "clientSequenceNumber" | "referenceSequenceNumber" | "minimumSequenceNumber" | "timestamp">>) => {
93
105
  messageClientId: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEN,aAAa,EACb,UAAU,EACV,wBAAwB,EACxB,WAAW,EACX,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,OAAO,EACN,YAAY,EAKZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,YAAa,YAAW,aAAa,EAAE,eAAe;aAatE,KAAK,CAAC;IAZvB,QAAQ,CAAC,SAAS,iBAAgC;IAElD;;;;;OAKG;gBAEF,OAAO,EAAE,MAAM,EAGC,KAAK,CAAC,KAAK,EAC3B,KAAK,CAAC,EAAE,wBAAwB;CAKjC;AAED;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,YAAa,YAAW,WAAW,EAAE,eAAe;IACnF,QAAQ,CAAC,SAAS,eAA8B;gBAEpC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,wBAAwB;CAG7D;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,YAAa,YAAW,UAAU,EAAE,eAAe;IAC3F,QAAQ,CAAC,SAAS,wBAAuC;IACzD,QAAQ,CAAC,QAAQ,SAAS;gBAEd,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB;CAG5D;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,SAAQ,YAAa,YAAW,UAAU,EAAE,eAAe;IAC3F;;OAEG;IACH,SAAgB,SAAS,wBAAuC;IAEhE,SAAgB,QAAQ,SAAS;IAEjC,OAAO;IAIP;;OAEG;WACW,MAAM,CACnB,YAAY,EAAE,MAAM,EACpB,sBAAsB,EAAE,MAAM,EAC9B,gBAAgB,CAAC,EAAE,yBAAyB,EAC5C,KAAK,GAAE,wBAA6B,GAClC,eAAe;IAWlB;;;;;;;;;;;;;;;;;OAiBG;WACW,kBAAkB,CAC/B,aAAa,EAAE,OAAO,EACtB,sBAAsB,EAAE,MAAM,EAC9B,WAAW,CAAC,EAAE,OAAO,CACpB,IAAI,CACH,yBAAyB,EACvB,UAAU,GACV,gBAAgB,GAChB,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,WAAW,CACb,CACD,GACC,eAAe;CA6BlB;AAED;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,gBAC/B,QACZ,KACC,yBAAyB,EACvB,UAAU,GACV,gBAAgB,GAChB,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,WAAW,CACb,CACD,KACC;IACF,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,2BAA2B,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,8BAA8B,EAAE,MAAM,GAAG,SAAS,CAAC;IACnD,4BAA4B,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CAQpC,CAAC"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEN,aAAa,EACb,UAAU,EACV,wBAAwB,EACxB,WAAW,EACX,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,OAAO,EACN,YAAY,EAKZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,wBAAwB,GAC9B,OAAO,CAAC,SAAS,CAInB;AAED;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,YAAa,YAAW,aAAa,EAAE,eAAe;aAatE,KAAK,CAAC;IAZvB,QAAQ,CAAC,SAAS,iBAAgC;IAElD;;;;;OAKG;gBAEF,OAAO,EAAE,MAAM,EAGC,KAAK,CAAC,KAAK,EAC3B,KAAK,CAAC,EAAE,wBAAwB;CAKjC;AAED;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,YAAa,YAAW,WAAW,EAAE,eAAe;IACnF,QAAQ,CAAC,SAAS,eAA8B;gBAEpC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,wBAAwB;CAG7D;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,YAAa,YAAW,UAAU,EAAE,eAAe;IAC3F,QAAQ,CAAC,SAAS,wBAAuC;IACzD,QAAQ,CAAC,QAAQ,SAAS;gBAEd,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB;CAG5D;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,SAAQ,YAAa,YAAW,UAAU,EAAE,eAAe;IAC3F;;OAEG;IACH,SAAgB,SAAS,wBAAuC;IAEhE,SAAgB,QAAQ,SAAS;IAEjC,OAAO;IAIP;;OAEG;WACW,MAAM,CACnB,YAAY,EAAE,MAAM,EACpB,sBAAsB,EAAE,MAAM,EAC9B,gBAAgB,CAAC,EAAE,yBAAyB,EAC5C,KAAK,GAAE,wBAA6B,GAClC,eAAe;IAWlB;;;;;;;;;;;;;;;;;OAiBG;WACW,kBAAkB,CAC/B,aAAa,EAAE,OAAO,EACtB,sBAAsB,EAAE,MAAM,EAC9B,WAAW,CAAC,EAAE,OAAO,CACpB,IAAI,CACH,yBAAyB,EACvB,UAAU,GACV,gBAAgB,GAChB,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,WAAW,CACb,CACD,GACC,eAAe;CA6BlB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,gBAC/B,QACZ,KACC,yBAAyB,EACvB,UAAU,GACV,gBAAgB,GAChB,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,WAAW,CACb,CACD,KACC;IACF,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,2BAA2B,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,8BAA8B,EAAE,MAAM,GAAG,SAAS,CAAC;IACnD,4BAA4B,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CAQpC,CAAC"}
package/lib/error.js CHANGED
@@ -4,6 +4,20 @@
4
4
  */
5
5
  import { FluidErrorTypes, } from "@fluidframework/core-interfaces";
6
6
  import { LoggingError, NORMALIZED_ERROR_TYPE, isExternalError, normalizeError, wrapError, } from "./errorLogging";
7
+ /**
8
+ * Throws a UsageError with the given message if the condition is not met.
9
+ * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).
10
+ *
11
+ * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.
12
+ * @param message - The message to include in the error when the condition does not hold.
13
+ * @param props - Telemetry props to include on the error when the condition does not hold.
14
+ * @internal
15
+ */
16
+ export function validatePrecondition(condition, message, props) {
17
+ if (!condition) {
18
+ throw new UsageError(message, props);
19
+ }
20
+ }
7
21
  /**
8
22
  * Generic wrapper for an unrecognized/uncategorized error object
9
23
  *
@@ -122,6 +136,8 @@ export class DataProcessingError extends LoggingError {
122
136
  * Extracts specific properties from the provided message that we know are safe to log.
123
137
  *
124
138
  * @param messageLike - Message to include info about via telemetry props.
139
+ *
140
+ * @internal
125
141
  */
126
142
  export const extractSafePropertiesFromMessage = (messageLike) => ({
127
143
  messageClientId: messageLike.clientId === null ? "null" : messageLike.clientId,
package/lib/error.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.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\tFluidErrorTypes,\n\tIGenericError,\n\tIErrorBase,\n\tITelemetryBaseProperties,\n\tIUsageError,\n} from \"@fluidframework/core-interfaces\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\n\nimport {\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tisExternalError,\n\tnormalizeError,\n\twrapError,\n} from \"./errorLogging\";\nimport { IFluidErrorBase } from \"./fluidErrorBase\";\n\n/**\n * Generic wrapper for an unrecognized/uncategorized error object\n *\n * @internal\n */\nexport class GenericError extends LoggingError implements IGenericError, IFluidErrorBase {\n\treadonly errorType = FluidErrorTypes.genericError;\n\n\t/**\n\t * Create a new GenericError\n\t * @param message - Error message\n\t * @param error - inner error object\n\t * @param props - Telemetry props to include when the error is logged\n\t */\n\tconstructor(\n\t\tmessage: string,\n\t\t// TODO: Use `unknown` instead (API breaking change because error is not just an input parameter, but a public member of the class)\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\tpublic readonly error?: any,\n\t\tprops?: ITelemetryBaseProperties,\n\t) {\n\t\t// Don't try to log the inner error\n\t\tsuper(message, props, new Set([\"error\"]));\n\t}\n}\n\n/**\n * Error indicating an API is being used improperly resulting in an invalid operation.\n *\n * @internal\n */\nexport class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {\n\treadonly errorType = FluidErrorTypes.usageError;\n\n\tconstructor(message: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, usageError: true });\n\t}\n}\n\n/**\n * DataCorruptionError indicates that we encountered definitive evidence that the data at rest\n * backing this container is corrupted, and this container would never be expected to load properly again\n *\n * @internal\n */\nexport class DataCorruptionError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\treadonly errorType = FluidErrorTypes.dataCorruptionError;\n\treadonly canRetry = false;\n\n\tconstructor(message: string, props: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, dataProcessingError: 1 });\n\t}\n}\n\n/**\n * Indicates we hit a fatal error while processing incoming data from the Fluid Service.\n *\n * @remarks\n *\n * The error will often originate in the dataStore or DDS implementation that is responding to incoming changes.\n * This differs from {@link DataCorruptionError} in that this may be a transient error that will not repro in another\n * client or session.\n *\n * @internal\n */\nexport class DataProcessingError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\t/**\n\t * {@inheritDoc IFluidErrorBase.errorType}\n\t */\n\tpublic readonly errorType = FluidErrorTypes.dataProcessingError;\n\n\tpublic readonly canRetry = false;\n\n\tprivate constructor(errorMessage: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(errorMessage, props);\n\t}\n\n\t/**\n\t * Create a new `DataProcessingError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataProcessingCodepath: string,\n\t\tsequencedMessage?: ISequencedDocumentMessage,\n\t\tprops: ITelemetryBaseProperties = {},\n\t): IFluidErrorBase {\n\t\tconst dataProcessingError = DataProcessingError.wrapIfUnrecognized(\n\t\t\terrorMessage,\n\t\t\tdataProcessingCodepath,\n\t\t\tsequencedMessage,\n\t\t);\n\t\tdataProcessingError.addTelemetryProperties(props);\n\n\t\treturn dataProcessingError;\n\t}\n\n\t/**\n\t * Wrap the given error in a `DataProcessingError`, unless the error is already of a known type\n\t * with the exception of a normalized {@link LoggingError}, which will still be wrapped.\n\t *\n\t * In either case, the error will have some relevant properties added for telemetry.\n\t *\n\t * @remarks\n\t *\n\t * We wrap conditionally since known error types represent well-understood failure modes, and ideally\n\t * one day we will move away from throwing these errors but rather we'll return them.\n\t * But an unrecognized error needs to be classified as `DataProcessingError`.\n\t *\n\t * @param originalError - The error to be converted.\n\t * @param dataProcessingCodepath - Which code-path failed while processing data.\n\t * @param messageLike - Message to include info about via telemetry props.\n\t *\n\t * @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.\n\t */\n\tpublic static wrapIfUnrecognized(\n\t\toriginalError: unknown,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: Partial<\n\t\t\tPick<\n\t\t\t\tISequencedDocumentMessage,\n\t\t\t\t| \"clientId\"\n\t\t\t\t| \"sequenceNumber\"\n\t\t\t\t| \"clientSequenceNumber\"\n\t\t\t\t| \"referenceSequenceNumber\"\n\t\t\t\t| \"minimumSequenceNumber\"\n\t\t\t\t| \"timestamp\"\n\t\t\t>\n\t\t>,\n\t): IFluidErrorBase {\n\t\tconst props = {\n\t\t\tdataProcessingError: 1,\n\t\t\tdataProcessingCodepath,\n\t\t\t...(messageLike === undefined\n\t\t\t\t? undefined\n\t\t\t\t: extractSafePropertiesFromMessage(messageLike)),\n\t\t};\n\n\t\tconst normalizedError = normalizeError(originalError, { props });\n\t\t// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,\n\t\t// but if so they are still suitable to be wrapped as DataProcessingError.\n\t\tif (\n\t\t\tisExternalError(normalizedError) ||\n\t\t\tnormalizedError.errorType === NORMALIZED_ERROR_TYPE\n\t\t) {\n\t\t\t// Create a new DataProcessingError to wrap this external error\n\t\t\tconst dataProcessingError = wrapError(\n\t\t\t\tnormalizedError,\n\t\t\t\t(message: string) => new DataProcessingError(message),\n\t\t\t);\n\n\t\t\t// Copy over the props above and any others added to this error since first being normalized\n\t\t\tdataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());\n\n\t\t\treturn dataProcessingError;\n\t\t}\n\t\treturn normalizedError;\n\t}\n}\n\n/**\n * Extracts specific properties from the provided message that we know are safe to log.\n *\n * @param messageLike - Message to include info about via telemetry props.\n */\nexport const extractSafePropertiesFromMessage = (\n\tmessageLike: Partial<\n\t\tPick<\n\t\t\tISequencedDocumentMessage,\n\t\t\t| \"clientId\"\n\t\t\t| \"sequenceNumber\"\n\t\t\t| \"clientSequenceNumber\"\n\t\t\t| \"referenceSequenceNumber\"\n\t\t\t| \"minimumSequenceNumber\"\n\t\t\t| \"timestamp\"\n\t\t>\n\t>,\n): {\n\tmessageClientId: string | undefined;\n\tmessageSequenceNumber: number | undefined;\n\tmessageClientSequenceNumber: number | undefined;\n\tmessageReferenceSequenceNumber: number | undefined;\n\tmessageMinimumSequenceNumber: number | undefined;\n\tmessageTimestamp: number | undefined;\n} => ({\n\tmessageClientId: messageLike.clientId === null ? \"null\" : messageLike.clientId,\n\tmessageSequenceNumber: messageLike.sequenceNumber,\n\tmessageClientSequenceNumber: messageLike.clientSequenceNumber,\n\tmessageReferenceSequenceNumber: messageLike.referenceSequenceNumber,\n\tmessageMinimumSequenceNumber: messageLike.minimumSequenceNumber,\n\tmessageTimestamp: messageLike.timestamp,\n});\n"]}
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.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\tFluidErrorTypes,\n\tIGenericError,\n\tIErrorBase,\n\tITelemetryBaseProperties,\n\tIUsageError,\n} from \"@fluidframework/core-interfaces\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\n\nimport {\n\tLoggingError,\n\tNORMALIZED_ERROR_TYPE,\n\tisExternalError,\n\tnormalizeError,\n\twrapError,\n} from \"./errorLogging\";\nimport { IFluidErrorBase } from \"./fluidErrorBase\";\n\n/**\n * Throws a UsageError with the given message if the condition is not met.\n * Use this API when `false` indicates a precondition is not met on a public API (for any FF layer).\n *\n * @param condition - The condition that should be true, if the condition is false a UsageError will be thrown.\n * @param message - The message to include in the error when the condition does not hold.\n * @param props - Telemetry props to include on the error when the condition does not hold.\n * @internal\n */\nexport function validatePrecondition(\n\tcondition: boolean,\n\tmessage: string,\n\tprops?: ITelemetryBaseProperties,\n): asserts condition {\n\tif (!condition) {\n\t\tthrow new UsageError(message, props);\n\t}\n}\n\n/**\n * Generic wrapper for an unrecognized/uncategorized error object\n *\n * @internal\n */\nexport class GenericError extends LoggingError implements IGenericError, IFluidErrorBase {\n\treadonly errorType = FluidErrorTypes.genericError;\n\n\t/**\n\t * Create a new GenericError\n\t * @param message - Error message\n\t * @param error - inner error object\n\t * @param props - Telemetry props to include when the error is logged\n\t */\n\tconstructor(\n\t\tmessage: string,\n\t\t// TODO: Use `unknown` instead (API breaking change because error is not just an input parameter, but a public member of the class)\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\tpublic readonly error?: any,\n\t\tprops?: ITelemetryBaseProperties,\n\t) {\n\t\t// Don't try to log the inner error\n\t\tsuper(message, props, new Set([\"error\"]));\n\t}\n}\n\n/**\n * Error indicating an API is being used improperly resulting in an invalid operation.\n *\n * @internal\n */\nexport class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {\n\treadonly errorType = FluidErrorTypes.usageError;\n\n\tconstructor(message: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, usageError: true });\n\t}\n}\n\n/**\n * DataCorruptionError indicates that we encountered definitive evidence that the data at rest\n * backing this container is corrupted, and this container would never be expected to load properly again\n *\n * @internal\n */\nexport class DataCorruptionError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\treadonly errorType = FluidErrorTypes.dataCorruptionError;\n\treadonly canRetry = false;\n\n\tconstructor(message: string, props: ITelemetryBaseProperties) {\n\t\tsuper(message, { ...props, dataProcessingError: 1 });\n\t}\n}\n\n/**\n * Indicates we hit a fatal error while processing incoming data from the Fluid Service.\n *\n * @remarks\n *\n * The error will often originate in the dataStore or DDS implementation that is responding to incoming changes.\n * This differs from {@link DataCorruptionError} in that this may be a transient error that will not repro in another\n * client or session.\n *\n * @internal\n */\nexport class DataProcessingError extends LoggingError implements IErrorBase, IFluidErrorBase {\n\t/**\n\t * {@inheritDoc IFluidErrorBase.errorType}\n\t */\n\tpublic readonly errorType = FluidErrorTypes.dataProcessingError;\n\n\tpublic readonly canRetry = false;\n\n\tprivate constructor(errorMessage: string, props?: ITelemetryBaseProperties) {\n\t\tsuper(errorMessage, props);\n\t}\n\n\t/**\n\t * Create a new `DataProcessingError` detected and raised within the Fluid Framework.\n\t */\n\tpublic static create(\n\t\terrorMessage: string,\n\t\tdataProcessingCodepath: string,\n\t\tsequencedMessage?: ISequencedDocumentMessage,\n\t\tprops: ITelemetryBaseProperties = {},\n\t): IFluidErrorBase {\n\t\tconst dataProcessingError = DataProcessingError.wrapIfUnrecognized(\n\t\t\terrorMessage,\n\t\t\tdataProcessingCodepath,\n\t\t\tsequencedMessage,\n\t\t);\n\t\tdataProcessingError.addTelemetryProperties(props);\n\n\t\treturn dataProcessingError;\n\t}\n\n\t/**\n\t * Wrap the given error in a `DataProcessingError`, unless the error is already of a known type\n\t * with the exception of a normalized {@link LoggingError}, which will still be wrapped.\n\t *\n\t * In either case, the error will have some relevant properties added for telemetry.\n\t *\n\t * @remarks\n\t *\n\t * We wrap conditionally since known error types represent well-understood failure modes, and ideally\n\t * one day we will move away from throwing these errors but rather we'll return them.\n\t * But an unrecognized error needs to be classified as `DataProcessingError`.\n\t *\n\t * @param originalError - The error to be converted.\n\t * @param dataProcessingCodepath - Which code-path failed while processing data.\n\t * @param messageLike - Message to include info about via telemetry props.\n\t *\n\t * @returns Either a new `DataProcessingError`, or (if wrapping is deemed unnecessary) the given error.\n\t */\n\tpublic static wrapIfUnrecognized(\n\t\toriginalError: unknown,\n\t\tdataProcessingCodepath: string,\n\t\tmessageLike?: Partial<\n\t\t\tPick<\n\t\t\t\tISequencedDocumentMessage,\n\t\t\t\t| \"clientId\"\n\t\t\t\t| \"sequenceNumber\"\n\t\t\t\t| \"clientSequenceNumber\"\n\t\t\t\t| \"referenceSequenceNumber\"\n\t\t\t\t| \"minimumSequenceNumber\"\n\t\t\t\t| \"timestamp\"\n\t\t\t>\n\t\t>,\n\t): IFluidErrorBase {\n\t\tconst props = {\n\t\t\tdataProcessingError: 1,\n\t\t\tdataProcessingCodepath,\n\t\t\t...(messageLike === undefined\n\t\t\t\t? undefined\n\t\t\t\t: extractSafePropertiesFromMessage(messageLike)),\n\t\t};\n\n\t\tconst normalizedError = normalizeError(originalError, { props });\n\t\t// Note that other errors may have the NORMALIZED_ERROR_TYPE errorType,\n\t\t// but if so they are still suitable to be wrapped as DataProcessingError.\n\t\tif (\n\t\t\tisExternalError(normalizedError) ||\n\t\t\tnormalizedError.errorType === NORMALIZED_ERROR_TYPE\n\t\t) {\n\t\t\t// Create a new DataProcessingError to wrap this external error\n\t\t\tconst dataProcessingError = wrapError(\n\t\t\t\tnormalizedError,\n\t\t\t\t(message: string) => new DataProcessingError(message),\n\t\t\t);\n\n\t\t\t// Copy over the props above and any others added to this error since first being normalized\n\t\t\tdataProcessingError.addTelemetryProperties(normalizedError.getTelemetryProperties());\n\n\t\t\treturn dataProcessingError;\n\t\t}\n\t\treturn normalizedError;\n\t}\n}\n\n/**\n * Extracts specific properties from the provided message that we know are safe to log.\n *\n * @param messageLike - Message to include info about via telemetry props.\n *\n * @internal\n */\nexport const extractSafePropertiesFromMessage = (\n\tmessageLike: Partial<\n\t\tPick<\n\t\t\tISequencedDocumentMessage,\n\t\t\t| \"clientId\"\n\t\t\t| \"sequenceNumber\"\n\t\t\t| \"clientSequenceNumber\"\n\t\t\t| \"referenceSequenceNumber\"\n\t\t\t| \"minimumSequenceNumber\"\n\t\t\t| \"timestamp\"\n\t\t>\n\t>,\n): {\n\tmessageClientId: string | undefined;\n\tmessageSequenceNumber: number | undefined;\n\tmessageClientSequenceNumber: number | undefined;\n\tmessageReferenceSequenceNumber: number | undefined;\n\tmessageMinimumSequenceNumber: number | undefined;\n\tmessageTimestamp: number | undefined;\n} => ({\n\tmessageClientId: messageLike.clientId === null ? \"null\" : messageLike.clientId,\n\tmessageSequenceNumber: messageLike.sequenceNumber,\n\tmessageClientSequenceNumber: messageLike.clientSequenceNumber,\n\tmessageReferenceSequenceNumber: messageLike.referenceSequenceNumber,\n\tmessageMinimumSequenceNumber: messageLike.minimumSequenceNumber,\n\tmessageTimestamp: messageLike.timestamp,\n});\n"]}