@azure/msal-common 14.0.2 → 14.0.3

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 (269) hide show
  1. package/dist/account/AuthToken.d.ts +14 -17
  2. package/dist/account/AuthToken.d.ts.map +1 -1
  3. package/dist/account/AuthToken.mjs +48 -39
  4. package/dist/account/AuthToken.mjs.map +1 -1
  5. package/dist/account/CcsCredential.mjs +1 -1
  6. package/dist/account/CcsCredential.mjs.map +1 -1
  7. package/dist/account/ClientInfo.d.ts.map +1 -1
  8. package/dist/account/ClientInfo.mjs +3 -4
  9. package/dist/account/ClientInfo.mjs.map +1 -1
  10. package/dist/authority/Authority.mjs +1 -1
  11. package/dist/authority/Authority.mjs.map +1 -1
  12. package/dist/authority/AuthorityFactory.d.ts.map +1 -1
  13. package/dist/authority/AuthorityFactory.mjs +2 -3
  14. package/dist/authority/AuthorityFactory.mjs.map +1 -1
  15. package/dist/authority/AuthorityMetadata.mjs +1 -1
  16. package/dist/authority/AuthorityMetadata.mjs.map +1 -1
  17. package/dist/authority/AuthorityOptions.mjs +1 -1
  18. package/dist/authority/AuthorityOptions.mjs.map +1 -1
  19. package/dist/authority/AuthorityType.mjs +1 -1
  20. package/dist/authority/AuthorityType.mjs.map +1 -1
  21. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
  22. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs.map +1 -1
  23. package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
  24. package/dist/authority/CloudInstanceDiscoveryResponse.mjs.map +1 -1
  25. package/dist/authority/OpenIdConfigResponse.mjs +1 -1
  26. package/dist/authority/OpenIdConfigResponse.mjs.map +1 -1
  27. package/dist/authority/ProtocolMode.mjs +1 -1
  28. package/dist/authority/ProtocolMode.mjs.map +1 -1
  29. package/dist/authority/RegionDiscovery.mjs +1 -1
  30. package/dist/authority/RegionDiscovery.mjs.map +1 -1
  31. package/dist/cache/CacheManager.d.ts.map +1 -1
  32. package/dist/cache/CacheManager.mjs +5 -5
  33. package/dist/cache/CacheManager.mjs.map +1 -1
  34. package/dist/cache/entities/AccessTokenEntity.d.ts.map +1 -1
  35. package/dist/cache/entities/AccessTokenEntity.mjs +4 -7
  36. package/dist/cache/entities/AccessTokenEntity.mjs.map +1 -1
  37. package/dist/cache/entities/AccountEntity.d.ts.map +1 -1
  38. package/dist/cache/entities/AccountEntity.mjs +2 -4
  39. package/dist/cache/entities/AccountEntity.mjs.map +1 -1
  40. package/dist/cache/entities/AppMetadataEntity.mjs +1 -1
  41. package/dist/cache/entities/AppMetadataEntity.mjs.map +1 -1
  42. package/dist/cache/entities/AuthorityMetadataEntity.mjs +1 -1
  43. package/dist/cache/entities/AuthorityMetadataEntity.mjs.map +1 -1
  44. package/dist/cache/entities/CacheRecord.mjs +1 -1
  45. package/dist/cache/entities/CacheRecord.mjs.map +1 -1
  46. package/dist/cache/entities/CredentialEntity.mjs +1 -1
  47. package/dist/cache/entities/CredentialEntity.mjs.map +1 -1
  48. package/dist/cache/entities/IdTokenEntity.mjs +1 -1
  49. package/dist/cache/entities/IdTokenEntity.mjs.map +1 -1
  50. package/dist/cache/entities/RefreshTokenEntity.mjs +1 -1
  51. package/dist/cache/entities/RefreshTokenEntity.mjs.map +1 -1
  52. package/dist/cache/entities/ServerTelemetryEntity.mjs +1 -1
  53. package/dist/cache/entities/ServerTelemetryEntity.mjs.map +1 -1
  54. package/dist/cache/entities/ThrottlingEntity.mjs +1 -1
  55. package/dist/cache/entities/ThrottlingEntity.mjs.map +1 -1
  56. package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
  57. package/dist/cache/persistence/TokenCacheContext.mjs.map +1 -1
  58. package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
  59. package/dist/client/AuthorizationCodeClient.mjs +10 -39
  60. package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
  61. package/dist/client/BaseClient.d.ts +1 -1
  62. package/dist/client/BaseClient.d.ts.map +1 -1
  63. package/dist/client/BaseClient.mjs +8 -2
  64. package/dist/client/BaseClient.mjs.map +1 -1
  65. package/dist/client/RefreshTokenClient.d.ts.map +1 -1
  66. package/dist/client/RefreshTokenClient.mjs +2 -11
  67. package/dist/client/RefreshTokenClient.mjs.map +1 -1
  68. package/dist/client/SilentFlowClient.d.ts.map +1 -1
  69. package/dist/client/SilentFlowClient.mjs +7 -7
  70. package/dist/client/SilentFlowClient.mjs.map +1 -1
  71. package/dist/config/ClientConfiguration.mjs +1 -1
  72. package/dist/config/ClientConfiguration.mjs.map +1 -1
  73. package/dist/crypto/ICrypto.mjs +1 -1
  74. package/dist/crypto/ICrypto.mjs.map +1 -1
  75. package/dist/crypto/JoseHeader.mjs +1 -1
  76. package/dist/crypto/JoseHeader.mjs.map +1 -1
  77. package/dist/crypto/PopTokenGenerator.mjs +1 -1
  78. package/dist/crypto/PopTokenGenerator.mjs.map +1 -1
  79. package/dist/error/AuthError.mjs +1 -1
  80. package/dist/error/AuthError.mjs.map +1 -1
  81. package/dist/error/ClientAuthError.mjs +1 -1
  82. package/dist/error/ClientAuthError.mjs.map +1 -1
  83. package/dist/error/ClientConfigurationError.mjs +1 -1
  84. package/dist/error/ClientConfigurationError.mjs.map +1 -1
  85. package/dist/error/InteractionRequiredAuthError.mjs +1 -1
  86. package/dist/error/InteractionRequiredAuthError.mjs.map +1 -1
  87. package/dist/error/JoseHeaderError.mjs +1 -1
  88. package/dist/error/JoseHeaderError.mjs.map +1 -1
  89. package/dist/error/ServerError.mjs +1 -1
  90. package/dist/error/ServerError.mjs.map +1 -1
  91. package/dist/index.cjs +1641 -1560
  92. package/dist/index.cjs.map +1 -1
  93. package/dist/index.d.ts +3 -3
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.mjs +5 -3
  96. package/dist/index.mjs.map +1 -1
  97. package/dist/logger/Logger.d.ts.map +1 -1
  98. package/dist/logger/Logger.mjs +2 -12
  99. package/dist/logger/Logger.mjs.map +1 -1
  100. package/dist/network/INetworkModule.mjs +1 -1
  101. package/dist/network/INetworkModule.mjs.map +1 -1
  102. package/dist/network/NetworkManager.mjs +1 -1
  103. package/dist/network/NetworkManager.mjs.map +1 -1
  104. package/dist/network/ThrottlingUtils.mjs +1 -1
  105. package/dist/network/ThrottlingUtils.mjs.map +1 -1
  106. package/dist/packageMetadata.d.ts +1 -1
  107. package/dist/packageMetadata.mjs +2 -2
  108. package/dist/packageMetadata.mjs.map +1 -1
  109. package/dist/request/AuthenticationHeaderParser.mjs +1 -1
  110. package/dist/request/AuthenticationHeaderParser.mjs.map +1 -1
  111. package/dist/request/RequestParameterBuilder.d.ts.map +1 -1
  112. package/dist/request/RequestParameterBuilder.mjs +6 -7
  113. package/dist/request/RequestParameterBuilder.mjs.map +1 -1
  114. package/dist/request/RequestValidator.d.ts.map +1 -1
  115. package/dist/request/RequestValidator.mjs +4 -6
  116. package/dist/request/RequestValidator.mjs.map +1 -1
  117. package/dist/request/ScopeSet.mjs +4 -4
  118. package/dist/request/ScopeSet.mjs.map +1 -1
  119. package/dist/response/AuthenticationResult.d.ts +3 -1
  120. package/dist/response/AuthenticationResult.d.ts.map +1 -1
  121. package/dist/response/ResponseHandler.d.ts +4 -3
  122. package/dist/response/ResponseHandler.d.ts.map +1 -1
  123. package/dist/response/ResponseHandler.mjs +57 -39
  124. package/dist/response/ResponseHandler.mjs.map +1 -1
  125. package/dist/response/ServerAuthorizationTokenResponse.d.ts +2 -0
  126. package/dist/response/ServerAuthorizationTokenResponse.d.ts.map +1 -1
  127. package/dist/telemetry/performance/IPerformanceClient.d.ts +4 -4
  128. package/dist/telemetry/performance/IPerformanceClient.d.ts.map +1 -1
  129. package/dist/telemetry/performance/PerformanceClient.d.ts +2 -2
  130. package/dist/telemetry/performance/PerformanceClient.d.ts.map +1 -1
  131. package/dist/telemetry/performance/PerformanceClient.mjs +1 -1
  132. package/dist/telemetry/performance/PerformanceClient.mjs.map +1 -1
  133. package/dist/telemetry/performance/PerformanceEvent.d.ts +8 -1
  134. package/dist/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  135. package/dist/telemetry/performance/PerformanceEvent.mjs +9 -1
  136. package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  137. package/dist/telemetry/performance/StubPerformanceClient.d.ts +3 -3
  138. package/dist/telemetry/performance/StubPerformanceClient.d.ts.map +1 -1
  139. package/dist/telemetry/performance/StubPerformanceClient.mjs +23 -3
  140. package/dist/telemetry/performance/StubPerformanceClient.mjs.map +1 -1
  141. package/dist/telemetry/server/ServerTelemetryManager.d.ts.map +1 -1
  142. package/dist/telemetry/server/ServerTelemetryManager.mjs +3 -4
  143. package/dist/telemetry/server/ServerTelemetryManager.mjs.map +1 -1
  144. package/dist/url/UrlString.d.ts.map +1 -1
  145. package/dist/url/UrlString.mjs +10 -12
  146. package/dist/url/UrlString.mjs.map +1 -1
  147. package/dist/utils/Constants.d.ts +10 -0
  148. package/dist/utils/Constants.d.ts.map +1 -1
  149. package/dist/utils/Constants.mjs +11 -2
  150. package/dist/utils/Constants.mjs.map +1 -1
  151. package/dist/utils/FunctionWrappers.d.ts +28 -0
  152. package/dist/utils/FunctionWrappers.d.ts.map +1 -0
  153. package/dist/utils/FunctionWrappers.mjs +90 -0
  154. package/dist/utils/FunctionWrappers.mjs.map +1 -0
  155. package/dist/utils/ProtocolUtils.d.ts.map +1 -1
  156. package/dist/utils/ProtocolUtils.mjs +4 -7
  157. package/dist/utils/ProtocolUtils.mjs.map +1 -1
  158. package/dist/utils/StringUtils.d.ts +0 -13
  159. package/dist/utils/StringUtils.d.ts.map +1 -1
  160. package/dist/utils/StringUtils.mjs +3 -34
  161. package/dist/utils/StringUtils.mjs.map +1 -1
  162. package/dist/utils/TimeUtils.mjs +1 -1
  163. package/dist/utils/TimeUtils.mjs.map +1 -1
  164. package/package.json +6 -4
  165. package/src/account/AccountInfo.ts +44 -0
  166. package/src/account/AuthToken.ts +70 -0
  167. package/src/account/CcsCredential.ts +16 -0
  168. package/src/account/ClientCredentials.ts +20 -0
  169. package/src/account/ClientInfo.ts +64 -0
  170. package/src/account/TokenClaims.ts +70 -0
  171. package/src/authority/Authority.ts +1225 -0
  172. package/src/authority/AuthorityFactory.ts +106 -0
  173. package/src/authority/AuthorityMetadata.ts +953 -0
  174. package/src/authority/AuthorityOptions.ts +40 -0
  175. package/src/authority/AuthorityType.ts +15 -0
  176. package/src/authority/AzureRegion.ts +7 -0
  177. package/src/authority/AzureRegionConfiguration.ts +16 -0
  178. package/src/authority/CloudDiscoveryMetadata.ts +10 -0
  179. package/src/authority/CloudInstanceDiscoveryErrorResponse.ts +26 -0
  180. package/src/authority/CloudInstanceDiscoveryResponse.ts +21 -0
  181. package/src/authority/ImdsOptions.ts +10 -0
  182. package/src/authority/OIDCOptions.ts +14 -0
  183. package/src/authority/OpenIdConfigResponse.ts +24 -0
  184. package/src/authority/ProtocolMode.ts +13 -0
  185. package/src/authority/RegionDiscovery.ts +193 -0
  186. package/src/authority/RegionDiscoveryMetadata.ts +15 -0
  187. package/src/broker/nativeBroker/INativeBrokerPlugin.ts +29 -0
  188. package/src/cache/CacheManager.ts +1619 -0
  189. package/src/cache/entities/AccessTokenEntity.ts +162 -0
  190. package/src/cache/entities/AccountEntity.ts +309 -0
  191. package/src/cache/entities/AppMetadataEntity.ts +91 -0
  192. package/src/cache/entities/AuthorityMetadataEntity.ts +112 -0
  193. package/src/cache/entities/CacheRecord.ts +33 -0
  194. package/src/cache/entities/CredentialEntity.ts +215 -0
  195. package/src/cache/entities/IdTokenEntity.ts +74 -0
  196. package/src/cache/entities/RefreshTokenEntity.ts +78 -0
  197. package/src/cache/entities/ServerTelemetryEntity.ts +38 -0
  198. package/src/cache/entities/ThrottlingEntity.ts +36 -0
  199. package/src/cache/interface/ICacheManager.ts +218 -0
  200. package/src/cache/interface/ICachePlugin.ts +11 -0
  201. package/src/cache/interface/ISerializableTokenCache.ts +9 -0
  202. package/src/cache/persistence/TokenCacheContext.ts +39 -0
  203. package/src/cache/utils/CacheTypes.ts +93 -0
  204. package/src/client/AuthorizationCodeClient.ts +714 -0
  205. package/src/client/BaseClient.ts +205 -0
  206. package/src/client/RefreshTokenClient.ts +442 -0
  207. package/src/client/SilentFlowClient.ts +186 -0
  208. package/src/config/AppTokenProvider.ts +47 -0
  209. package/src/config/ClientConfiguration.ts +287 -0
  210. package/src/crypto/ICrypto.ts +127 -0
  211. package/src/crypto/IGuidGenerator.ts +9 -0
  212. package/src/crypto/JoseHeader.ts +55 -0
  213. package/src/crypto/PopTokenGenerator.ts +155 -0
  214. package/src/crypto/SignedHttpRequest.ts +16 -0
  215. package/src/error/AuthError.ts +85 -0
  216. package/src/error/ClientAuthError.ts +738 -0
  217. package/src/error/ClientConfigurationError.ts +396 -0
  218. package/src/error/InteractionRequiredAuthError.ts +134 -0
  219. package/src/error/JoseHeaderError.ts +52 -0
  220. package/src/error/ServerError.ts +18 -0
  221. package/src/index.ts +215 -0
  222. package/src/logger/Logger.ts +272 -0
  223. package/src/network/INetworkModule.ts +57 -0
  224. package/src/network/NetworkManager.ts +76 -0
  225. package/src/network/RequestThumbprint.ts +22 -0
  226. package/src/network/ThrottlingUtils.ts +156 -0
  227. package/src/packageMetadata.ts +3 -0
  228. package/src/request/AuthenticationHeaderParser.ts +89 -0
  229. package/src/request/BaseAuthRequest.ts +46 -0
  230. package/src/request/CommonAuthorizationCodeRequest.ts +33 -0
  231. package/src/request/CommonAuthorizationUrlRequest.ts +56 -0
  232. package/src/request/CommonClientCredentialRequest.ts +23 -0
  233. package/src/request/CommonDeviceCodeRequest.ts +31 -0
  234. package/src/request/CommonEndSessionRequest.ts +27 -0
  235. package/src/request/CommonOnBehalfOfRequest.ts +19 -0
  236. package/src/request/CommonRefreshTokenRequest.ts +25 -0
  237. package/src/request/CommonSilentFlowRequest.ts +24 -0
  238. package/src/request/CommonUsernamePasswordRequest.ts +23 -0
  239. package/src/request/NativeRequest.ts +25 -0
  240. package/src/request/NativeSignOutRequest.ts +10 -0
  241. package/src/request/RequestParameterBuilder.ts +606 -0
  242. package/src/request/RequestValidator.ts +103 -0
  243. package/src/request/ScopeSet.ts +230 -0
  244. package/src/request/StoreInCache.ts +16 -0
  245. package/src/response/AuthenticationResult.ts +47 -0
  246. package/src/response/AuthorizationCodePayload.ts +18 -0
  247. package/src/response/DeviceCodeResponse.ts +31 -0
  248. package/src/response/ExternalTokenResponse.ts +24 -0
  249. package/src/response/IMDSBadResponse.ts +9 -0
  250. package/src/response/ResponseHandler.ts +614 -0
  251. package/src/response/ServerAuthorizationCodeResponse.ts +33 -0
  252. package/src/response/ServerAuthorizationTokenResponse.ts +54 -0
  253. package/src/telemetry/performance/IPerformanceClient.ts +71 -0
  254. package/src/telemetry/performance/IPerformanceMeasurement.ts +10 -0
  255. package/src/telemetry/performance/PerformanceClient.ts +635 -0
  256. package/src/telemetry/performance/PerformanceEvent.ts +542 -0
  257. package/src/telemetry/performance/StubPerformanceClient.ts +101 -0
  258. package/src/telemetry/server/ServerTelemetryManager.ts +274 -0
  259. package/src/telemetry/server/ServerTelemetryRequest.ts +13 -0
  260. package/src/url/IUri.ts +17 -0
  261. package/src/url/UrlString.ts +363 -0
  262. package/src/utils/Constants.ts +436 -0
  263. package/src/utils/FunctionWrappers.ts +105 -0
  264. package/src/utils/MsalTypes.ts +9 -0
  265. package/src/utils/ProtocolUtils.ts +124 -0
  266. package/src/utils/StringUtils.ts +106 -0
  267. package/src/utils/TimeUtils.ts +51 -0
  268. package/dist/account/DecodedAuthToken.d.ts +0 -9
  269. package/dist/account/DecodedAuthToken.d.ts.map +0 -1
@@ -0,0 +1,635 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { ApplicationTelemetry } from "../../config/ClientConfiguration";
7
+ import { Logger } from "../../logger/Logger";
8
+ import {
9
+ InProgressPerformanceEvent,
10
+ IPerformanceClient,
11
+ PerformanceCallbackFunction,
12
+ QueueMeasurement,
13
+ } from "./IPerformanceClient";
14
+ import { IPerformanceMeasurement } from "./IPerformanceMeasurement";
15
+ import {
16
+ IntFields,
17
+ PerformanceEvent,
18
+ PerformanceEvents,
19
+ PerformanceEventStatus,
20
+ } from "./PerformanceEvent";
21
+
22
+ export interface PreQueueEvent {
23
+ name: PerformanceEvents;
24
+ time: number;
25
+ }
26
+
27
+ export abstract class PerformanceClient implements IPerformanceClient {
28
+ protected authority: string;
29
+ protected libraryName: string;
30
+ protected libraryVersion: string;
31
+ protected applicationTelemetry: ApplicationTelemetry;
32
+ protected clientId: string;
33
+ protected logger: Logger;
34
+ protected callbacks: Map<string, PerformanceCallbackFunction>;
35
+
36
+ /**
37
+ * Multiple events with the same correlation id.
38
+ * @protected
39
+ * @type {Map<string, PerformanceEvent>}
40
+ */
41
+ protected eventsByCorrelationId: Map<string, PerformanceEvent>;
42
+
43
+ /**
44
+ * Map of pre-queue times by correlation Id
45
+ *
46
+ * @protected
47
+ * @type {Map<string, PreQueueEvent>}
48
+ */
49
+ protected preQueueTimeByCorrelationId: Map<string, PreQueueEvent>;
50
+
51
+ /**
52
+ * Map of queue measurements by correlation Id
53
+ *
54
+ * @protected
55
+ * @type {Map<string, Array<QueueMeasurement>>}
56
+ */
57
+ protected queueMeasurements: Map<string, Array<QueueMeasurement>>;
58
+
59
+ protected intFields: Set<string>;
60
+
61
+ /**
62
+ * Creates an instance of PerformanceClient,
63
+ * an abstract class containing core performance telemetry logic.
64
+ *
65
+ * @constructor
66
+ * @param {string} clientId Client ID of the application
67
+ * @param {string} authority Authority used by the application
68
+ * @param {Logger} logger Logger used by the application
69
+ * @param {string} libraryName Name of the library
70
+ * @param {string} libraryVersion Version of the library
71
+ * @param {ApplicationTelemetry} applicationTelemetry application name and version
72
+ * @param {Set<String>} intFields integer fields to be truncated
73
+ */
74
+ constructor(
75
+ clientId: string,
76
+ authority: string,
77
+ logger: Logger,
78
+ libraryName: string,
79
+ libraryVersion: string,
80
+ applicationTelemetry: ApplicationTelemetry,
81
+ intFields?: Set<string>
82
+ ) {
83
+ this.authority = authority;
84
+ this.libraryName = libraryName;
85
+ this.libraryVersion = libraryVersion;
86
+ this.applicationTelemetry = applicationTelemetry;
87
+ this.clientId = clientId;
88
+ this.logger = logger;
89
+ this.callbacks = new Map();
90
+ this.eventsByCorrelationId = new Map();
91
+ this.queueMeasurements = new Map();
92
+ this.preQueueTimeByCorrelationId = new Map();
93
+ this.intFields = intFields || new Set();
94
+ for (const item of IntFields) {
95
+ this.intFields.add(item);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Generates and returns a unique id, typically a guid.
101
+ *
102
+ * @abstract
103
+ * @returns {string}
104
+ */
105
+ abstract generateId(): string;
106
+
107
+ /**
108
+ * Starts and returns an platform-specific implementation of IPerformanceMeasurement.
109
+ * Note: this function can be changed to abstract at the next major version bump.
110
+ *
111
+ * @param {string} measureName
112
+ * @param {string} correlationId
113
+ * @returns {IPerformanceMeasurement}
114
+ */
115
+ startPerformanceMeasurement(
116
+ measureName: string, // eslint-disable-line @typescript-eslint/no-unused-vars
117
+ correlationId: string // eslint-disable-line @typescript-eslint/no-unused-vars
118
+ ): IPerformanceMeasurement {
119
+ return {} as IPerformanceMeasurement;
120
+ }
121
+
122
+ /**
123
+ * Sets pre-queue time by correlation Id
124
+ *
125
+ * @abstract
126
+ * @param {PerformanceEvents} eventName
127
+ * @param {string} correlationId
128
+ * @returns
129
+ */
130
+ abstract setPreQueueTime(
131
+ eventName: PerformanceEvents,
132
+ correlationId?: string
133
+ ): void;
134
+
135
+ /**
136
+ * Gets map of pre-queue times by correlation Id
137
+ *
138
+ * @param {PerformanceEvents} eventName
139
+ * @param {string} correlationId
140
+ * @returns {number}
141
+ */
142
+ getPreQueueTime(eventName: string, correlationId: string): number | void {
143
+ const preQueueEvent: PreQueueEvent | undefined =
144
+ this.preQueueTimeByCorrelationId.get(correlationId);
145
+
146
+ if (!preQueueEvent) {
147
+ this.logger.trace(
148
+ `PerformanceClient.getPreQueueTime: no pre-queue times found for correlationId: ${correlationId}, unable to add queue measurement`
149
+ );
150
+ return;
151
+ } else if (preQueueEvent.name !== eventName) {
152
+ this.logger.trace(
153
+ `PerformanceClient.getPreQueueTime: no pre-queue time found for ${eventName}, unable to add queue measurement`
154
+ );
155
+ return;
156
+ }
157
+
158
+ return preQueueEvent.time;
159
+ }
160
+
161
+ /**
162
+ * Calculates the difference between current time and time when function was queued.
163
+ * Note: It is possible to have 0 as the queue time if the current time and the queued time was the same.
164
+ *
165
+ * @param {number} preQueueTime
166
+ * @param {number} currentTime
167
+ * @returns {number}
168
+ */
169
+ calculateQueuedTime(preQueueTime: number, currentTime: number): number {
170
+ if (preQueueTime < 1) {
171
+ this.logger.trace(
172
+ `PerformanceClient: preQueueTime should be a positive integer and not ${preQueueTime}`
173
+ );
174
+ return 0;
175
+ }
176
+
177
+ if (currentTime < 1) {
178
+ this.logger.trace(
179
+ `PerformanceClient: currentTime should be a positive integer and not ${currentTime}`
180
+ );
181
+ return 0;
182
+ }
183
+
184
+ if (currentTime < preQueueTime) {
185
+ this.logger.trace(
186
+ "PerformanceClient: currentTime is less than preQueueTime, check how time is being retrieved"
187
+ );
188
+ return 0;
189
+ }
190
+
191
+ return currentTime - preQueueTime;
192
+ }
193
+
194
+ /**
195
+ * Adds queue measurement time to QueueMeasurements array for given correlation ID.
196
+ *
197
+ * @param {PerformanceEvents} eventName
198
+ * @param {?string} correlationId
199
+ * @param {?number} queueTime
200
+ * @param {?boolean} manuallyCompleted - indicator for manually completed queue measurements
201
+ * @returns
202
+ */
203
+ addQueueMeasurement(
204
+ eventName: string,
205
+ correlationId?: string,
206
+ queueTime?: number,
207
+ manuallyCompleted?: boolean
208
+ ): void {
209
+ if (!correlationId) {
210
+ this.logger.trace(
211
+ `PerformanceClient.addQueueMeasurement: correlationId not provided for ${eventName}, cannot add queue measurement`
212
+ );
213
+ return;
214
+ }
215
+
216
+ if (queueTime === 0) {
217
+ // Possible for there to be no queue time after calculation
218
+ this.logger.trace(
219
+ `PerformanceClient.addQueueMeasurement: queue time provided for ${eventName} is ${queueTime}`
220
+ );
221
+ } else if (!queueTime) {
222
+ this.logger.trace(
223
+ `PerformanceClient.addQueueMeasurement: no queue time provided for ${eventName}`
224
+ );
225
+ return;
226
+ }
227
+
228
+ const queueMeasurement: QueueMeasurement = {
229
+ eventName,
230
+ queueTime,
231
+ manuallyCompleted,
232
+ };
233
+
234
+ // Adds to existing correlation Id if present in queueMeasurements
235
+ const existingMeasurements = this.queueMeasurements.get(correlationId);
236
+ if (existingMeasurements) {
237
+ existingMeasurements.push(queueMeasurement);
238
+ this.queueMeasurements.set(correlationId, existingMeasurements);
239
+ } else {
240
+ // Sets new correlation Id if not present in queueMeasurements
241
+ this.logger.trace(
242
+ `PerformanceClient.addQueueMeasurement: adding correlationId ${correlationId} to queue measurements`
243
+ );
244
+ const measurementArray = [queueMeasurement];
245
+ this.queueMeasurements.set(correlationId, measurementArray);
246
+ }
247
+ // Delete processed pre-queue event.
248
+ this.preQueueTimeByCorrelationId.delete(correlationId);
249
+ }
250
+
251
+ /**
252
+ * Starts measuring performance for a given operation. Returns a function that should be used to end the measurement.
253
+ *
254
+ * @param {PerformanceEvents} measureName
255
+ * @param {?string} [correlationId]
256
+ * @returns {InProgressPerformanceEvent}
257
+ */
258
+ startMeasurement(
259
+ measureName: string,
260
+ correlationId?: string
261
+ ): InProgressPerformanceEvent {
262
+ // Generate a placeholder correlation if the request does not provide one
263
+ const eventCorrelationId = correlationId || this.generateId();
264
+ if (!correlationId) {
265
+ this.logger.info(
266
+ `PerformanceClient: No correlation id provided for ${measureName}, generating`,
267
+ eventCorrelationId
268
+ );
269
+ }
270
+
271
+ this.logger.trace(
272
+ `PerformanceClient: Performance measurement started for ${measureName}`,
273
+ eventCorrelationId
274
+ );
275
+ const performanceMeasurement = this.startPerformanceMeasurement(
276
+ measureName,
277
+ eventCorrelationId
278
+ );
279
+ performanceMeasurement.startMeasurement();
280
+
281
+ const inProgressEvent: PerformanceEvent = {
282
+ eventId: this.generateId(),
283
+ status: PerformanceEventStatus.InProgress,
284
+ authority: this.authority,
285
+ libraryName: this.libraryName,
286
+ libraryVersion: this.libraryVersion,
287
+ clientId: this.clientId,
288
+ name: measureName,
289
+ startTimeMs: Date.now(),
290
+ correlationId: eventCorrelationId,
291
+ appName: this.applicationTelemetry?.appName,
292
+ appVersion: this.applicationTelemetry?.appVersion,
293
+ };
294
+
295
+ // Store in progress events so they can be discarded if not ended properly
296
+ this.cacheEventByCorrelationId(inProgressEvent);
297
+
298
+ // Return the event and functions the caller can use to properly end/flush the measurement
299
+ return {
300
+ end: (
301
+ event?: Partial<PerformanceEvent>
302
+ ): PerformanceEvent | null => {
303
+ return this.endMeasurement(
304
+ {
305
+ // Initial set of event properties
306
+ ...inProgressEvent,
307
+ // Properties set when event ends
308
+ ...event,
309
+ },
310
+ performanceMeasurement
311
+ );
312
+ },
313
+ discard: () => {
314
+ return this.discardMeasurements(inProgressEvent.correlationId);
315
+ },
316
+ add: (fields: { [key: string]: {} | undefined }) => {
317
+ return this.addFields(fields, inProgressEvent.correlationId);
318
+ },
319
+ increment: (fields: { [key: string]: number | undefined }) => {
320
+ return this.incrementFields(
321
+ fields,
322
+ inProgressEvent.correlationId
323
+ );
324
+ },
325
+ measurement: performanceMeasurement,
326
+ event: inProgressEvent,
327
+ };
328
+ }
329
+
330
+ /**
331
+ * Stops measuring the performance for an operation. Should only be called directly by PerformanceClient classes,
332
+ * as consumers should instead use the function returned by startMeasurement.
333
+ * Adds a new field named as "[event name]DurationMs" for sub-measurements, completes and emits an event
334
+ * otherwise.
335
+ *
336
+ * @param {PerformanceEvent} event
337
+ * @param {IPerformanceMeasurement} measurement
338
+ * @returns {(PerformanceEvent | null)}
339
+ */
340
+ endMeasurement(
341
+ event: PerformanceEvent,
342
+ measurement?: IPerformanceMeasurement
343
+ ): PerformanceEvent | null {
344
+ const rootEvent: PerformanceEvent | undefined =
345
+ this.eventsByCorrelationId.get(event.correlationId);
346
+ if (!rootEvent) {
347
+ this.logger.trace(
348
+ `PerformanceClient: Measurement not found for ${event.eventId}`,
349
+ event.correlationId
350
+ );
351
+ return null;
352
+ }
353
+
354
+ const isRoot = event.eventId === rootEvent.eventId;
355
+ let queueInfo = {
356
+ totalQueueTime: 0,
357
+ totalQueueCount: 0,
358
+ manuallyCompletedCount: 0,
359
+ };
360
+ if (isRoot) {
361
+ queueInfo = this.getQueueInfo(event.correlationId);
362
+ this.discardCache(rootEvent.correlationId);
363
+ } else {
364
+ rootEvent.incompleteSubMeasurements?.delete(event.eventId);
365
+ }
366
+
367
+ measurement?.endMeasurement();
368
+ const durationMs = measurement?.flushMeasurement();
369
+ // null indicates no measurement was taken (e.g. needed performance APIs not present)
370
+ if (!durationMs) {
371
+ this.logger.trace(
372
+ "PerformanceClient: Performance measurement not taken",
373
+ rootEvent.correlationId
374
+ );
375
+ return null;
376
+ }
377
+
378
+ this.logger.trace(
379
+ `PerformanceClient: Performance measurement ended for ${event.name}: ${durationMs} ms`,
380
+ event.correlationId
381
+ );
382
+
383
+ // Add sub-measurement attribute to root event.
384
+ if (!isRoot) {
385
+ rootEvent[event.name + "DurationMs"] = Math.floor(durationMs);
386
+ return { ...rootEvent };
387
+ }
388
+
389
+ let finalEvent: PerformanceEvent = { ...rootEvent, ...event };
390
+ let incompleteSubsCount: number = 0;
391
+ // Incomplete sub-measurements are discarded. They are likely an instrumentation bug that should be fixed.
392
+ finalEvent.incompleteSubMeasurements?.forEach((subMeasurement) => {
393
+ this.logger.trace(
394
+ `PerformanceClient: Incomplete submeasurement ${subMeasurement.name} found for ${event.name}`,
395
+ finalEvent.correlationId
396
+ );
397
+ incompleteSubsCount++;
398
+ });
399
+ finalEvent.incompleteSubMeasurements = undefined;
400
+
401
+ finalEvent = {
402
+ ...finalEvent,
403
+ durationMs: Math.round(durationMs),
404
+ queuedTimeMs: queueInfo.totalQueueTime,
405
+ queuedCount: queueInfo.totalQueueCount,
406
+ queuedManuallyCompletedCount: queueInfo.manuallyCompletedCount,
407
+ status: PerformanceEventStatus.Completed,
408
+ incompleteSubsCount,
409
+ };
410
+ this.truncateIntegralFields(finalEvent);
411
+ this.emitEvents([finalEvent], event.correlationId);
412
+
413
+ return finalEvent;
414
+ }
415
+
416
+ /**
417
+ * Saves extra information to be emitted when the measurements are flushed
418
+ * @param fields
419
+ * @param correlationId
420
+ */
421
+ addFields(
422
+ fields: { [key: string]: {} | undefined },
423
+ correlationId: string
424
+ ): void {
425
+ this.logger.trace("PerformanceClient: Updating static fields");
426
+ const event = this.eventsByCorrelationId.get(correlationId);
427
+ if (event) {
428
+ this.eventsByCorrelationId.set(correlationId, {
429
+ ...event,
430
+ ...fields,
431
+ });
432
+ } else {
433
+ this.logger.trace(
434
+ "PerformanceClient: Event not found for",
435
+ correlationId
436
+ );
437
+ }
438
+ }
439
+
440
+ /**
441
+ * Increment counters to be emitted when the measurements are flushed
442
+ * @param fields {string[]}
443
+ * @param correlationId {string} correlation identifier
444
+ */
445
+ incrementFields(
446
+ fields: { [key: string]: number | undefined },
447
+ correlationId: string
448
+ ): void {
449
+ this.logger.trace("PerformanceClient: Updating counters");
450
+ const event = this.eventsByCorrelationId.get(correlationId);
451
+ if (event) {
452
+ for (const counter in fields) {
453
+ if (!event.hasOwnProperty(counter)) {
454
+ event[counter] = 0;
455
+ } else if (isNaN(Number(event[counter]))) {
456
+ return;
457
+ }
458
+ event[counter] += fields[counter];
459
+ }
460
+ } else {
461
+ this.logger.trace(
462
+ "PerformanceClient: Event not found for",
463
+ correlationId
464
+ );
465
+ }
466
+ }
467
+
468
+ /**
469
+ * Upserts event into event cache.
470
+ * First key is the correlation id, second key is the event id.
471
+ * Allows for events to be grouped by correlation id,
472
+ * and to easily allow for properties on them to be updated.
473
+ *
474
+ * @private
475
+ * @param {PerformanceEvent} event
476
+ */
477
+ protected cacheEventByCorrelationId(event: PerformanceEvent): void {
478
+ const rootEvent = this.eventsByCorrelationId.get(event.correlationId);
479
+ if (rootEvent) {
480
+ this.logger.trace(
481
+ `PerformanceClient: Performance measurement for ${event.name} added/updated`,
482
+ event.correlationId
483
+ );
484
+ rootEvent.incompleteSubMeasurements =
485
+ rootEvent.incompleteSubMeasurements || new Map();
486
+ rootEvent.incompleteSubMeasurements.set(event.eventId, {
487
+ name: event.name,
488
+ startTimeMs: event.startTimeMs,
489
+ });
490
+ } else {
491
+ this.logger.trace(
492
+ `PerformanceClient: Performance measurement for ${event.name} started`,
493
+ event.correlationId
494
+ );
495
+ this.eventsByCorrelationId.set(event.correlationId, { ...event });
496
+ }
497
+ }
498
+
499
+ private getQueueInfo(correlationId: string): {
500
+ totalQueueTime: number;
501
+ totalQueueCount: number;
502
+ manuallyCompletedCount: number;
503
+ } {
504
+ const queueMeasurementForCorrelationId =
505
+ this.queueMeasurements.get(correlationId);
506
+ if (!queueMeasurementForCorrelationId) {
507
+ this.logger.trace(
508
+ `PerformanceClient: no queue measurements found for for correlationId: ${correlationId}`
509
+ );
510
+ }
511
+
512
+ let totalQueueTime = 0;
513
+ let totalQueueCount = 0;
514
+ let manuallyCompletedCount = 0;
515
+ queueMeasurementForCorrelationId?.forEach((measurement) => {
516
+ totalQueueTime += measurement.queueTime;
517
+ totalQueueCount++;
518
+ manuallyCompletedCount += measurement.manuallyCompleted ? 1 : 0;
519
+ });
520
+
521
+ return {
522
+ totalQueueTime,
523
+ totalQueueCount,
524
+ manuallyCompletedCount,
525
+ };
526
+ }
527
+
528
+ /**
529
+ * Removes measurements for a given correlation id.
530
+ *
531
+ * @param {string} correlationId
532
+ */
533
+ discardMeasurements(correlationId: string): void {
534
+ this.logger.trace(
535
+ "PerformanceClient: Performance measurements discarded",
536
+ correlationId
537
+ );
538
+ this.eventsByCorrelationId.delete(correlationId);
539
+ }
540
+
541
+ /**
542
+ * Removes cache for a given correlation id.
543
+ *
544
+ * @param {string} correlationId correlation identifier
545
+ */
546
+ private discardCache(correlationId: string): void {
547
+ this.discardMeasurements(correlationId);
548
+
549
+ this.logger.trace(
550
+ "PerformanceClient: QueueMeasurements discarded",
551
+ correlationId
552
+ );
553
+ this.queueMeasurements.delete(correlationId);
554
+
555
+ this.logger.trace(
556
+ "PerformanceClient: Pre-queue times discarded",
557
+ correlationId
558
+ );
559
+ this.preQueueTimeByCorrelationId.delete(correlationId);
560
+ }
561
+
562
+ /**
563
+ * Registers a callback function to receive performance events.
564
+ *
565
+ * @param {PerformanceCallbackFunction} callback
566
+ * @returns {string}
567
+ */
568
+ addPerformanceCallback(callback: PerformanceCallbackFunction): string {
569
+ const callbackId = this.generateId();
570
+ this.callbacks.set(callbackId, callback);
571
+ this.logger.verbose(
572
+ `PerformanceClient: Performance callback registered with id: ${callbackId}`
573
+ );
574
+
575
+ return callbackId;
576
+ }
577
+
578
+ /**
579
+ * Removes a callback registered with addPerformanceCallback.
580
+ *
581
+ * @param {string} callbackId
582
+ * @returns {boolean}
583
+ */
584
+ removePerformanceCallback(callbackId: string): boolean {
585
+ const result = this.callbacks.delete(callbackId);
586
+
587
+ if (result) {
588
+ this.logger.verbose(
589
+ `PerformanceClient: Performance callback ${callbackId} removed.`
590
+ );
591
+ } else {
592
+ this.logger.verbose(
593
+ `PerformanceClient: Performance callback ${callbackId} not removed.`
594
+ );
595
+ }
596
+
597
+ return result;
598
+ }
599
+
600
+ /**
601
+ * Emits events to all registered callbacks.
602
+ *
603
+ * @param {PerformanceEvent[]} events
604
+ * @param {?string} [correlationId]
605
+ */
606
+ emitEvents(events: PerformanceEvent[], correlationId: string): void {
607
+ this.logger.verbose(
608
+ "PerformanceClient: Emitting performance events",
609
+ correlationId
610
+ );
611
+
612
+ this.callbacks.forEach(
613
+ (callback: PerformanceCallbackFunction, callbackId: string) => {
614
+ this.logger.trace(
615
+ `PerformanceClient: Emitting event to callback ${callbackId}`,
616
+ correlationId
617
+ );
618
+ callback.apply(null, [events]);
619
+ }
620
+ );
621
+ }
622
+
623
+ /**
624
+ * Enforce truncation of integral fields in performance event.
625
+ * @param {PerformanceEvent} event performance event to update.
626
+ * @param {Set<string>} intFields integral fields.
627
+ */
628
+ private truncateIntegralFields(event: PerformanceEvent): void {
629
+ this.intFields.forEach((key) => {
630
+ if (key in event && typeof event[key] === "number") {
631
+ event[key] = Math.floor(event[key]);
632
+ }
633
+ });
634
+ }
635
+ }