GSI - Employe Self Service Mobile
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1559 lines
62 KiB

2 months ago
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var util = require('@firebase/util');
  4. var logger$1 = require('@firebase/logger');
  5. var tslib = require('tslib');
  6. var app = require('@firebase/app');
  7. var component = require('@firebase/component');
  8. require('@firebase/installations');
  9. var name = "@firebase/performance";
  10. var version = "0.6.1";
  11. /**
  12. * @license
  13. * Copyright 2020 Google LLC
  14. *
  15. * Licensed under the Apache License, Version 2.0 (the "License");
  16. * you may not use this file except in compliance with the License.
  17. * You may obtain a copy of the License at
  18. *
  19. * http://www.apache.org/licenses/LICENSE-2.0
  20. *
  21. * Unless required by applicable law or agreed to in writing, software
  22. * distributed under the License is distributed on an "AS IS" BASIS,
  23. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  24. * See the License for the specific language governing permissions and
  25. * limitations under the License.
  26. */
  27. var SDK_VERSION = version;
  28. /** The prefix for start User Timing marks used for creating Traces. */
  29. var TRACE_START_MARK_PREFIX = 'FB-PERF-TRACE-START';
  30. /** The prefix for stop User Timing marks used for creating Traces. */
  31. var TRACE_STOP_MARK_PREFIX = 'FB-PERF-TRACE-STOP';
  32. /** The prefix for User Timing measure used for creating Traces. */
  33. var TRACE_MEASURE_PREFIX = 'FB-PERF-TRACE-MEASURE';
  34. /** The prefix for out of the box page load Trace name. */
  35. var OOB_TRACE_PAGE_LOAD_PREFIX = '_wt_';
  36. var FIRST_PAINT_COUNTER_NAME = '_fp';
  37. var FIRST_CONTENTFUL_PAINT_COUNTER_NAME = '_fcp';
  38. var FIRST_INPUT_DELAY_COUNTER_NAME = '_fid';
  39. var CONFIG_LOCAL_STORAGE_KEY = '@firebase/performance/config';
  40. var CONFIG_EXPIRY_LOCAL_STORAGE_KEY = '@firebase/performance/configexpire';
  41. var SERVICE = 'performance';
  42. var SERVICE_NAME = 'Performance';
  43. /**
  44. * @license
  45. * Copyright 2020 Google LLC
  46. *
  47. * Licensed under the Apache License, Version 2.0 (the "License");
  48. * you may not use this file except in compliance with the License.
  49. * You may obtain a copy of the License at
  50. *
  51. * http://www.apache.org/licenses/LICENSE-2.0
  52. *
  53. * Unless required by applicable law or agreed to in writing, software
  54. * distributed under the License is distributed on an "AS IS" BASIS,
  55. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  56. * See the License for the specific language governing permissions and
  57. * limitations under the License.
  58. */
  59. var _a;
  60. var ERROR_DESCRIPTION_MAP = (_a = {},
  61. _a["trace started" /* ErrorCode.TRACE_STARTED_BEFORE */] = 'Trace {$traceName} was started before.',
  62. _a["trace stopped" /* ErrorCode.TRACE_STOPPED_BEFORE */] = 'Trace {$traceName} is not running.',
  63. _a["nonpositive trace startTime" /* ErrorCode.NONPOSITIVE_TRACE_START_TIME */] = 'Trace {$traceName} startTime should be positive.',
  64. _a["nonpositive trace duration" /* ErrorCode.NONPOSITIVE_TRACE_DURATION */] = 'Trace {$traceName} duration should be positive.',
  65. _a["no window" /* ErrorCode.NO_WINDOW */] = 'Window is not available.',
  66. _a["no app id" /* ErrorCode.NO_APP_ID */] = 'App id is not available.',
  67. _a["no project id" /* ErrorCode.NO_PROJECT_ID */] = 'Project id is not available.',
  68. _a["no api key" /* ErrorCode.NO_API_KEY */] = 'Api key is not available.',
  69. _a["invalid cc log" /* ErrorCode.INVALID_CC_LOG */] = 'Attempted to queue invalid cc event',
  70. _a["FB not default" /* ErrorCode.FB_NOT_DEFAULT */] = 'Performance can only start when Firebase app instance is the default one.',
  71. _a["RC response not ok" /* ErrorCode.RC_NOT_OK */] = 'RC response is not ok',
  72. _a["invalid attribute name" /* ErrorCode.INVALID_ATTRIBUTE_NAME */] = 'Attribute name {$attributeName} is invalid.',
  73. _a["invalid attribute value" /* ErrorCode.INVALID_ATTRIBUTE_VALUE */] = 'Attribute value {$attributeValue} is invalid.',
  74. _a["invalid custom metric name" /* ErrorCode.INVALID_CUSTOM_METRIC_NAME */] = 'Custom metric name {$customMetricName} is invalid',
  75. _a["invalid String merger input" /* ErrorCode.INVALID_STRING_MERGER_PARAMETER */] = 'Input for String merger is invalid, contact support team to resolve.',
  76. _a["already initialized" /* ErrorCode.ALREADY_INITIALIZED */] = 'initializePerformance() has already been called with ' +
  77. 'different options. To avoid this error, call initializePerformance() with the ' +
  78. 'same options as when it was originally called, or call getPerformance() to return the' +
  79. ' already initialized instance.',
  80. _a);
  81. var ERROR_FACTORY = new util.ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
  82. /**
  83. * @license
  84. * Copyright 2020 Google LLC
  85. *
  86. * Licensed under the Apache License, Version 2.0 (the "License");
  87. * you may not use this file except in compliance with the License.
  88. * You may obtain a copy of the License at
  89. *
  90. * http://www.apache.org/licenses/LICENSE-2.0
  91. *
  92. * Unless required by applicable law or agreed to in writing, software
  93. * distributed under the License is distributed on an "AS IS" BASIS,
  94. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  95. * See the License for the specific language governing permissions and
  96. * limitations under the License.
  97. */
  98. var consoleLogger = new logger$1.Logger(SERVICE_NAME);
  99. consoleLogger.logLevel = logger$1.LogLevel.INFO;
  100. /**
  101. * @license
  102. * Copyright 2020 Google LLC
  103. *
  104. * Licensed under the Apache License, Version 2.0 (the "License");
  105. * you may not use this file except in compliance with the License.
  106. * You may obtain a copy of the License at
  107. *
  108. * http://www.apache.org/licenses/LICENSE-2.0
  109. *
  110. * Unless required by applicable law or agreed to in writing, software
  111. * distributed under the License is distributed on an "AS IS" BASIS,
  112. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  113. * See the License for the specific language governing permissions and
  114. * limitations under the License.
  115. */
  116. var apiInstance;
  117. var windowInstance;
  118. /**
  119. * This class holds a reference to various browser related objects injected by
  120. * set methods.
  121. */
  122. var Api = /** @class */ (function () {
  123. function Api(window) {
  124. this.window = window;
  125. if (!window) {
  126. throw ERROR_FACTORY.create("no window" /* ErrorCode.NO_WINDOW */);
  127. }
  128. this.performance = window.performance;
  129. this.PerformanceObserver = window.PerformanceObserver;
  130. this.windowLocation = window.location;
  131. this.navigator = window.navigator;
  132. this.document = window.document;
  133. if (this.navigator && this.navigator.cookieEnabled) {
  134. // If user blocks cookies on the browser, accessing localStorage will
  135. // throw an exception.
  136. this.localStorage = window.localStorage;
  137. }
  138. if (window.perfMetrics && window.perfMetrics.onFirstInputDelay) {
  139. this.onFirstInputDelay = window.perfMetrics.onFirstInputDelay;
  140. }
  141. }
  142. Api.prototype.getUrl = function () {
  143. // Do not capture the string query part of url.
  144. return this.windowLocation.href.split('?')[0];
  145. };
  146. Api.prototype.mark = function (name) {
  147. if (!this.performance || !this.performance.mark) {
  148. return;
  149. }
  150. this.performance.mark(name);
  151. };
  152. Api.prototype.measure = function (measureName, mark1, mark2) {
  153. if (!this.performance || !this.performance.measure) {
  154. return;
  155. }
  156. this.performance.measure(measureName, mark1, mark2);
  157. };
  158. Api.prototype.getEntriesByType = function (type) {
  159. if (!this.performance || !this.performance.getEntriesByType) {
  160. return [];
  161. }
  162. return this.performance.getEntriesByType(type);
  163. };
  164. Api.prototype.getEntriesByName = function (name) {
  165. if (!this.performance || !this.performance.getEntriesByName) {
  166. return [];
  167. }
  168. return this.performance.getEntriesByName(name);
  169. };
  170. Api.prototype.getTimeOrigin = function () {
  171. // Polyfill the time origin with performance.timing.navigationStart.
  172. return (this.performance &&
  173. (this.performance.timeOrigin || this.performance.timing.navigationStart));
  174. };
  175. Api.prototype.requiredApisAvailable = function () {
  176. if (!fetch || !Promise || !util.areCookiesEnabled()) {
  177. consoleLogger.info('Firebase Performance cannot start if browser does not support fetch and Promise or cookie is disabled.');
  178. return false;
  179. }
  180. if (!util.isIndexedDBAvailable()) {
  181. consoleLogger.info('IndexedDB is not supported by current browswer');
  182. return false;
  183. }
  184. return true;
  185. };
  186. Api.prototype.setupObserver = function (entryType, callback) {
  187. if (!this.PerformanceObserver) {
  188. return;
  189. }
  190. var observer = new this.PerformanceObserver(function (list) {
  191. for (var _i = 0, _a = list.getEntries(); _i < _a.length; _i++) {
  192. var entry = _a[_i];
  193. // `entry` is a PerformanceEntry instance.
  194. callback(entry);
  195. }
  196. });
  197. // Start observing the entry types you care about.
  198. observer.observe({ entryTypes: [entryType] });
  199. };
  200. Api.getInstance = function () {
  201. if (apiInstance === undefined) {
  202. apiInstance = new Api(windowInstance);
  203. }
  204. return apiInstance;
  205. };
  206. return Api;
  207. }());
  208. function setupApi(window) {
  209. windowInstance = window;
  210. }
  211. /**
  212. * @license
  213. * Copyright 2020 Google LLC
  214. *
  215. * Licensed under the Apache License, Version 2.0 (the "License");
  216. * you may not use this file except in compliance with the License.
  217. * You may obtain a copy of the License at
  218. *
  219. * http://www.apache.org/licenses/LICENSE-2.0
  220. *
  221. * Unless required by applicable law or agreed to in writing, software
  222. * distributed under the License is distributed on an "AS IS" BASIS,
  223. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  224. * See the License for the specific language governing permissions and
  225. * limitations under the License.
  226. */
  227. var iid;
  228. function getIidPromise(installationsService) {
  229. var iidPromise = installationsService.getId();
  230. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  231. iidPromise.then(function (iidVal) {
  232. iid = iidVal;
  233. });
  234. return iidPromise;
  235. }
  236. // This method should be used after the iid is retrieved by getIidPromise method.
  237. function getIid() {
  238. return iid;
  239. }
  240. function getAuthTokenPromise(installationsService) {
  241. var authTokenPromise = installationsService.getToken();
  242. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  243. authTokenPromise.then(function (authTokenVal) {
  244. });
  245. return authTokenPromise;
  246. }
  247. /**
  248. * @license
  249. * Copyright 2020 Google LLC
  250. *
  251. * Licensed under the Apache License, Version 2.0 (the "License");
  252. * you may not use this file except in compliance with the License.
  253. * You may obtain a copy of the License at
  254. *
  255. * http://www.apache.org/licenses/LICENSE-2.0
  256. *
  257. * Unless required by applicable law or agreed to in writing, software
  258. * distributed under the License is distributed on an "AS IS" BASIS,
  259. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  260. * See the License for the specific language governing permissions and
  261. * limitations under the License.
  262. */
  263. function mergeStrings(part1, part2) {
  264. var sizeDiff = part1.length - part2.length;
  265. if (sizeDiff < 0 || sizeDiff > 1) {
  266. throw ERROR_FACTORY.create("invalid String merger input" /* ErrorCode.INVALID_STRING_MERGER_PARAMETER */);
  267. }
  268. var resultArray = [];
  269. for (var i = 0; i < part1.length; i++) {
  270. resultArray.push(part1.charAt(i));
  271. if (part2.length > i) {
  272. resultArray.push(part2.charAt(i));
  273. }
  274. }
  275. return resultArray.join('');
  276. }
  277. /**
  278. * @license
  279. * Copyright 2019 Google LLC
  280. *
  281. * Licensed under the Apache License, Version 2.0 (the "License");
  282. * you may not use this file except in compliance with the License.
  283. * You may obtain a copy of the License at
  284. *
  285. * http://www.apache.org/licenses/LICENSE-2.0
  286. *
  287. * Unless required by applicable law or agreed to in writing, software
  288. * distributed under the License is distributed on an "AS IS" BASIS,
  289. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  290. * See the License for the specific language governing permissions and
  291. * limitations under the License.
  292. */
  293. var settingsServiceInstance;
  294. var SettingsService = /** @class */ (function () {
  295. function SettingsService() {
  296. // The variable which controls logging of automatic traces and HTTP/S network monitoring.
  297. this.instrumentationEnabled = true;
  298. // The variable which controls logging of custom traces.
  299. this.dataCollectionEnabled = true;
  300. // Configuration flags set through remote config.
  301. this.loggingEnabled = false;
  302. // Sampling rate between 0 and 1.
  303. this.tracesSamplingRate = 1;
  304. this.networkRequestsSamplingRate = 1;
  305. // Address of logging service.
  306. this.logEndPointUrl = 'https://firebaselogging.googleapis.com/v0cc/log?format=json_proto';
  307. // Performance event transport endpoint URL which should be compatible with proto3.
  308. // New Address for transport service, not configurable via Remote Config.
  309. this.flTransportEndpointUrl = mergeStrings('hts/frbslgigp.ogepscmv/ieo/eaylg', 'tp:/ieaeogn-agolai.o/1frlglgc/o');
  310. this.transportKey = mergeStrings('AzSC8r6ReiGqFMyfvgow', 'Iayx0u-XT3vksVM-pIV');
  311. // Source type for performance event logs.
  312. this.logSource = 462;
  313. // Flags which control per session logging of traces and network requests.
  314. this.logTraceAfterSampling = false;
  315. this.logNetworkAfterSampling = false;
  316. // TTL of config retrieved from remote config in hours.
  317. this.configTimeToLive = 12;
  318. }
  319. SettingsService.prototype.getFlTransportFullUrl = function () {
  320. return this.flTransportEndpointUrl.concat('?key=', this.transportKey);
  321. };
  322. SettingsService.getInstance = function () {
  323. if (settingsServiceInstance === undefined) {
  324. settingsServiceInstance = new SettingsService();
  325. }
  326. return settingsServiceInstance;
  327. };
  328. return SettingsService;
  329. }());
  330. /**
  331. * @license
  332. * Copyright 2020 Google LLC
  333. *
  334. * Licensed under the Apache License, Version 2.0 (the "License");
  335. * you may not use this file except in compliance with the License.
  336. * You may obtain a copy of the License at
  337. *
  338. * http://www.apache.org/licenses/LICENSE-2.0
  339. *
  340. * Unless required by applicable law or agreed to in writing, software
  341. * distributed under the License is distributed on an "AS IS" BASIS,
  342. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  343. * See the License for the specific language governing permissions and
  344. * limitations under the License.
  345. */
  346. var VisibilityState;
  347. (function (VisibilityState) {
  348. VisibilityState[VisibilityState["UNKNOWN"] = 0] = "UNKNOWN";
  349. VisibilityState[VisibilityState["VISIBLE"] = 1] = "VISIBLE";
  350. VisibilityState[VisibilityState["HIDDEN"] = 2] = "HIDDEN";
  351. })(VisibilityState || (VisibilityState = {}));
  352. var RESERVED_ATTRIBUTE_PREFIXES = ['firebase_', 'google_', 'ga_'];
  353. var ATTRIBUTE_FORMAT_REGEX = new RegExp('^[a-zA-Z]\\w*$');
  354. var MAX_ATTRIBUTE_NAME_LENGTH = 40;
  355. var MAX_ATTRIBUTE_VALUE_LENGTH = 100;
  356. function getServiceWorkerStatus() {
  357. var navigator = Api.getInstance().navigator;
  358. if (navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker) {
  359. if (navigator.serviceWorker.controller) {
  360. return 2 /* ServiceWorkerStatus.CONTROLLED */;
  361. }
  362. else {
  363. return 3 /* ServiceWorkerStatus.UNCONTROLLED */;
  364. }
  365. }
  366. else {
  367. return 1 /* ServiceWorkerStatus.UNSUPPORTED */;
  368. }
  369. }
  370. function getVisibilityState() {
  371. var document = Api.getInstance().document;
  372. var visibilityState = document.visibilityState;
  373. switch (visibilityState) {
  374. case 'visible':
  375. return VisibilityState.VISIBLE;
  376. case 'hidden':
  377. return VisibilityState.HIDDEN;
  378. default:
  379. return VisibilityState.UNKNOWN;
  380. }
  381. }
  382. function getEffectiveConnectionType() {
  383. var navigator = Api.getInstance().navigator;
  384. var navigatorConnection = navigator.connection;
  385. var effectiveType = navigatorConnection && navigatorConnection.effectiveType;
  386. switch (effectiveType) {
  387. case 'slow-2g':
  388. return 1 /* EffectiveConnectionType.CONNECTION_SLOW_2G */;
  389. case '2g':
  390. return 2 /* EffectiveConnectionType.CONNECTION_2G */;
  391. case '3g':
  392. return 3 /* EffectiveConnectionType.CONNECTION_3G */;
  393. case '4g':
  394. return 4 /* EffectiveConnectionType.CONNECTION_4G */;
  395. default:
  396. return 0 /* EffectiveConnectionType.UNKNOWN */;
  397. }
  398. }
  399. function isValidCustomAttributeName(name) {
  400. if (name.length === 0 || name.length > MAX_ATTRIBUTE_NAME_LENGTH) {
  401. return false;
  402. }
  403. var matchesReservedPrefix = RESERVED_ATTRIBUTE_PREFIXES.some(function (prefix) {
  404. return name.startsWith(prefix);
  405. });
  406. return !matchesReservedPrefix && !!name.match(ATTRIBUTE_FORMAT_REGEX);
  407. }
  408. function isValidCustomAttributeValue(value) {
  409. return value.length !== 0 && value.length <= MAX_ATTRIBUTE_VALUE_LENGTH;
  410. }
  411. /**
  412. * @license
  413. * Copyright 2020 Google LLC
  414. *
  415. * Licensed under the Apache License, Version 2.0 (the "License");
  416. * you may not use this file except in compliance with the License.
  417. * You may obtain a copy of the License at
  418. *
  419. * http://www.apache.org/licenses/LICENSE-2.0
  420. *
  421. * Unless required by applicable law or agreed to in writing, software
  422. * distributed under the License is distributed on an "AS IS" BASIS,
  423. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  424. * See the License for the specific language governing permissions and
  425. * limitations under the License.
  426. */
  427. function getAppId(firebaseApp) {
  428. var _a;
  429. var appId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.appId;
  430. if (!appId) {
  431. throw ERROR_FACTORY.create("no app id" /* ErrorCode.NO_APP_ID */);
  432. }
  433. return appId;
  434. }
  435. function getProjectId(firebaseApp) {
  436. var _a;
  437. var projectId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.projectId;
  438. if (!projectId) {
  439. throw ERROR_FACTORY.create("no project id" /* ErrorCode.NO_PROJECT_ID */);
  440. }
  441. return projectId;
  442. }
  443. function getApiKey(firebaseApp) {
  444. var _a;
  445. var apiKey = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.apiKey;
  446. if (!apiKey) {
  447. throw ERROR_FACTORY.create("no api key" /* ErrorCode.NO_API_KEY */);
  448. }
  449. return apiKey;
  450. }
  451. /**
  452. * @license
  453. * Copyright 2020 Google LLC
  454. *
  455. * Licensed under the Apache License, Version 2.0 (the "License");
  456. * you may not use this file except in compliance with the License.
  457. * You may obtain a copy of the License at
  458. *
  459. * http://www.apache.org/licenses/LICENSE-2.0
  460. *
  461. * Unless required by applicable law or agreed to in writing, software
  462. * distributed under the License is distributed on an "AS IS" BASIS,
  463. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  464. * See the License for the specific language governing permissions and
  465. * limitations under the License.
  466. */
  467. var REMOTE_CONFIG_SDK_VERSION = '0.0.1';
  468. // These values will be used if the remote config object is successfully
  469. // retrieved, but the template does not have these fields.
  470. var DEFAULT_CONFIGS = {
  471. loggingEnabled: true
  472. };
  473. var FIS_AUTH_PREFIX = 'FIREBASE_INSTALLATIONS_AUTH';
  474. function getConfig(performanceController, iid) {
  475. var config = getStoredConfig();
  476. if (config) {
  477. processConfig(config);
  478. return Promise.resolve();
  479. }
  480. return getRemoteConfig(performanceController, iid)
  481. .then(processConfig)
  482. .then(function (config) { return storeConfig(config); },
  483. /** Do nothing for error, use defaults set in settings service. */
  484. function () { });
  485. }
  486. function getStoredConfig() {
  487. var localStorage = Api.getInstance().localStorage;
  488. if (!localStorage) {
  489. return;
  490. }
  491. var expiryString = localStorage.getItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY);
  492. if (!expiryString || !configValid(expiryString)) {
  493. return;
  494. }
  495. var configStringified = localStorage.getItem(CONFIG_LOCAL_STORAGE_KEY);
  496. if (!configStringified) {
  497. return;
  498. }
  499. try {
  500. var configResponse = JSON.parse(configStringified);
  501. return configResponse;
  502. }
  503. catch (_a) {
  504. return;
  505. }
  506. }
  507. function storeConfig(config) {
  508. var localStorage = Api.getInstance().localStorage;
  509. if (!config || !localStorage) {
  510. return;
  511. }
  512. localStorage.setItem(CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config));
  513. localStorage.setItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY, String(Date.now() +
  514. SettingsService.getInstance().configTimeToLive * 60 * 60 * 1000));
  515. }
  516. var COULD_NOT_GET_CONFIG_MSG = 'Could not fetch config, will use default configs';
  517. function getRemoteConfig(performanceController, iid) {
  518. // Perf needs auth token only to retrieve remote config.
  519. return getAuthTokenPromise(performanceController.installations)
  520. .then(function (authToken) {
  521. var projectId = getProjectId(performanceController.app);
  522. var apiKey = getApiKey(performanceController.app);
  523. var configEndPoint = "https://firebaseremoteconfig.googleapis.com/v1/projects/".concat(projectId, "/namespaces/fireperf:fetch?key=").concat(apiKey);
  524. var request = new Request(configEndPoint, {
  525. method: 'POST',
  526. headers: { Authorization: "".concat(FIS_AUTH_PREFIX, " ").concat(authToken) },
  527. /* eslint-disable camelcase */
  528. body: JSON.stringify({
  529. app_instance_id: iid,
  530. app_instance_id_token: authToken,
  531. app_id: getAppId(performanceController.app),
  532. app_version: SDK_VERSION,
  533. sdk_version: REMOTE_CONFIG_SDK_VERSION
  534. })
  535. /* eslint-enable camelcase */
  536. });
  537. return fetch(request).then(function (response) {
  538. if (response.ok) {
  539. return response.json();
  540. }
  541. // In case response is not ok. This will be caught by catch.
  542. throw ERROR_FACTORY.create("RC response not ok" /* ErrorCode.RC_NOT_OK */);
  543. });
  544. })
  545. .catch(function () {
  546. consoleLogger.info(COULD_NOT_GET_CONFIG_MSG);
  547. return undefined;
  548. });
  549. }
  550. /**
  551. * Processes config coming either from calling RC or from local storage.
  552. * This method only runs if call is successful or config in storage
  553. * is valid.
  554. */
  555. function processConfig(config) {
  556. if (!config) {
  557. return config;
  558. }
  559. var settingsServiceInstance = SettingsService.getInstance();
  560. var entries = config.entries || {};
  561. if (entries.fpr_enabled !== undefined) {
  562. // TODO: Change the assignment of loggingEnabled once the received type is
  563. // known.
  564. settingsServiceInstance.loggingEnabled =
  565. String(entries.fpr_enabled) === 'true';
  566. }
  567. else {
  568. // Config retrieved successfully, but there is no fpr_enabled in template.
  569. // Use secondary configs value.
  570. settingsServiceInstance.loggingEnabled = DEFAULT_CONFIGS.loggingEnabled;
  571. }
  572. if (entries.fpr_log_source) {
  573. settingsServiceInstance.logSource = Number(entries.fpr_log_source);
  574. }
  575. else if (DEFAULT_CONFIGS.logSource) {
  576. settingsServiceInstance.logSource = DEFAULT_CONFIGS.logSource;
  577. }
  578. if (entries.fpr_log_endpoint_url) {
  579. settingsServiceInstance.logEndPointUrl = entries.fpr_log_endpoint_url;
  580. }
  581. else if (DEFAULT_CONFIGS.logEndPointUrl) {
  582. settingsServiceInstance.logEndPointUrl = DEFAULT_CONFIGS.logEndPointUrl;
  583. }
  584. // Key from Remote Config has to be non-empty string, otherwsie use local value.
  585. if (entries.fpr_log_transport_key) {
  586. settingsServiceInstance.transportKey = entries.fpr_log_transport_key;
  587. }
  588. else if (DEFAULT_CONFIGS.transportKey) {
  589. settingsServiceInstance.transportKey = DEFAULT_CONFIGS.transportKey;
  590. }
  591. if (entries.fpr_vc_network_request_sampling_rate !== undefined) {
  592. settingsServiceInstance.networkRequestsSamplingRate = Number(entries.fpr_vc_network_request_sampling_rate);
  593. }
  594. else if (DEFAULT_CONFIGS.networkRequestsSamplingRate !== undefined) {
  595. settingsServiceInstance.networkRequestsSamplingRate =
  596. DEFAULT_CONFIGS.networkRequestsSamplingRate;
  597. }
  598. if (entries.fpr_vc_trace_sampling_rate !== undefined) {
  599. settingsServiceInstance.tracesSamplingRate = Number(entries.fpr_vc_trace_sampling_rate);
  600. }
  601. else if (DEFAULT_CONFIGS.tracesSamplingRate !== undefined) {
  602. settingsServiceInstance.tracesSamplingRate =
  603. DEFAULT_CONFIGS.tracesSamplingRate;
  604. }
  605. // Set the per session trace and network logging flags.
  606. settingsServiceInstance.logTraceAfterSampling = shouldLogAfterSampling(settingsServiceInstance.tracesSamplingRate);
  607. settingsServiceInstance.logNetworkAfterSampling = shouldLogAfterSampling(settingsServiceInstance.networkRequestsSamplingRate);
  608. return config;
  609. }
  610. function configValid(expiry) {
  611. return Number(expiry) > Date.now();
  612. }
  613. function shouldLogAfterSampling(samplingRate) {
  614. return Math.random() <= samplingRate;
  615. }
  616. /**
  617. * @license
  618. * Copyright 2020 Google LLC
  619. *
  620. * Licensed under the Apache License, Version 2.0 (the "License");
  621. * you may not use this file except in compliance with the License.
  622. * You may obtain a copy of the License at
  623. *
  624. * http://www.apache.org/licenses/LICENSE-2.0
  625. *
  626. * Unless required by applicable law or agreed to in writing, software
  627. * distributed under the License is distributed on an "AS IS" BASIS,
  628. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  629. * See the License for the specific language governing permissions and
  630. * limitations under the License.
  631. */
  632. var initializationStatus = 1 /* InitializationStatus.notInitialized */;
  633. var initializationPromise;
  634. function getInitializationPromise(performanceController) {
  635. initializationStatus = 2 /* InitializationStatus.initializationPending */;
  636. initializationPromise =
  637. initializationPromise || initializePerf(performanceController);
  638. return initializationPromise;
  639. }
  640. function isPerfInitialized() {
  641. return initializationStatus === 3 /* InitializationStatus.initialized */;
  642. }
  643. function initializePerf(performanceController) {
  644. return getDocumentReadyComplete()
  645. .then(function () { return getIidPromise(performanceController.installations); })
  646. .then(function (iid) { return getConfig(performanceController, iid); })
  647. .then(function () { return changeInitializationStatus(); }, function () { return changeInitializationStatus(); });
  648. }
  649. /**
  650. * Returns a promise which resolves whenever the document readystate is complete or
  651. * immediately if it is called after page load complete.
  652. */
  653. function getDocumentReadyComplete() {
  654. var document = Api.getInstance().document;
  655. return new Promise(function (resolve) {
  656. if (document && document.readyState !== 'complete') {
  657. var handler_1 = function () {
  658. if (document.readyState === 'complete') {
  659. document.removeEventListener('readystatechange', handler_1);
  660. resolve();
  661. }
  662. };
  663. document.addEventListener('readystatechange', handler_1);
  664. }
  665. else {
  666. resolve();
  667. }
  668. });
  669. }
  670. function changeInitializationStatus() {
  671. initializationStatus = 3 /* InitializationStatus.initialized */;
  672. }
  673. /**
  674. * @license
  675. * Copyright 2020 Google LLC
  676. *
  677. * Licensed under the Apache License, Version 2.0 (the "License");
  678. * you may not use this file except in compliance with the License.
  679. * You may obtain a copy of the License at
  680. *
  681. * http://www.apache.org/licenses/LICENSE-2.0
  682. *
  683. * Unless required by applicable law or agreed to in writing, software
  684. * distributed under the License is distributed on an "AS IS" BASIS,
  685. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  686. * See the License for the specific language governing permissions and
  687. * limitations under the License.
  688. */
  689. var DEFAULT_SEND_INTERVAL_MS = 10 * 1000;
  690. var INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;
  691. // If end point does not work, the call will be tried for these many times.
  692. var DEFAULT_REMAINING_TRIES = 3;
  693. var MAX_EVENT_COUNT_PER_REQUEST = 1000;
  694. var remainingTries = DEFAULT_REMAINING_TRIES;
  695. /* eslint-enable camelcase */
  696. var queue = [];
  697. var isTransportSetup = false;
  698. function setupTransportService() {
  699. if (!isTransportSetup) {
  700. processQueue(INITIAL_SEND_TIME_DELAY_MS);
  701. isTransportSetup = true;
  702. }
  703. }
  704. function processQueue(timeOffset) {
  705. setTimeout(function () {
  706. // If there is no remainingTries left, stop retrying.
  707. if (remainingTries === 0) {
  708. return;
  709. }
  710. // If there are no events to process, wait for DEFAULT_SEND_INTERVAL_MS and try again.
  711. if (!queue.length) {
  712. return processQueue(DEFAULT_SEND_INTERVAL_MS);
  713. }
  714. dispatchQueueEvents();
  715. }, timeOffset);
  716. }
  717. function dispatchQueueEvents() {
  718. // Extract events up to the maximum cap of single logRequest from top of "official queue".
  719. // The staged events will be used for current logRequest attempt, remaining events will be kept
  720. // for next attempt.
  721. var staged = queue.splice(0, MAX_EVENT_COUNT_PER_REQUEST);
  722. /* eslint-disable camelcase */
  723. // We will pass the JSON serialized event to the backend.
  724. var log_event = staged.map(function (evt) { return ({
  725. source_extension_json_proto3: evt.message,
  726. event_time_ms: String(evt.eventTime)
  727. }); });
  728. var data = {
  729. request_time_ms: String(Date.now()),
  730. client_info: {
  731. client_type: 1,
  732. js_client_info: {}
  733. },
  734. log_source: SettingsService.getInstance().logSource,
  735. log_event: log_event
  736. };
  737. /* eslint-enable camelcase */
  738. sendEventsToFl(data, staged).catch(function () {
  739. // If the request fails for some reason, add the events that were attempted
  740. // back to the primary queue to retry later.
  741. queue = tslib.__spreadArray(tslib.__spreadArray([], staged, true), queue, true);
  742. remainingTries--;
  743. consoleLogger.info("Tries left: ".concat(remainingTries, "."));
  744. processQueue(DEFAULT_SEND_INTERVAL_MS);
  745. });
  746. }
  747. function sendEventsToFl(data, staged) {
  748. return postToFlEndpoint(data)
  749. .then(function (res) {
  750. if (!res.ok) {
  751. consoleLogger.info('Call to Firebase backend failed.');
  752. }
  753. return res.json();
  754. })
  755. .then(function (res) {
  756. // Find the next call wait time from the response.
  757. var transportWait = Number(res.nextRequestWaitMillis);
  758. var requestOffset = DEFAULT_SEND_INTERVAL_MS;
  759. if (!isNaN(transportWait)) {
  760. requestOffset = Math.max(transportWait, requestOffset);
  761. }
  762. // Delete request if response include RESPONSE_ACTION_UNKNOWN or DELETE_REQUEST action.
  763. // Otherwise, retry request using normal scheduling if response include RETRY_REQUEST_LATER.
  764. var logResponseDetails = res.logResponseDetails;
  765. if (Array.isArray(logResponseDetails) &&
  766. logResponseDetails.length > 0 &&
  767. logResponseDetails[0].responseAction === 'RETRY_REQUEST_LATER') {
  768. queue = tslib.__spreadArray(tslib.__spreadArray([], staged, true), queue, true);
  769. consoleLogger.info("Retry transport request later.");
  770. }
  771. remainingTries = DEFAULT_REMAINING_TRIES;
  772. // Schedule the next process.
  773. processQueue(requestOffset);
  774. });
  775. }
  776. function postToFlEndpoint(data) {
  777. var flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
  778. return fetch(flTransportFullUrl, {
  779. method: 'POST',
  780. body: JSON.stringify(data)
  781. });
  782. }
  783. function addToQueue(evt) {
  784. if (!evt.eventTime || !evt.message) {
  785. throw ERROR_FACTORY.create("invalid cc log" /* ErrorCode.INVALID_CC_LOG */);
  786. }
  787. // Add the new event to the queue.
  788. queue = tslib.__spreadArray(tslib.__spreadArray([], queue, true), [evt], false);
  789. }
  790. /** Log handler for cc service to send the performance logs to the server. */
  791. function transportHandler(
  792. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  793. serializer) {
  794. return function () {
  795. var args = [];
  796. for (var _i = 0; _i < arguments.length; _i++) {
  797. args[_i] = arguments[_i];
  798. }
  799. var message = serializer.apply(void 0, args);
  800. addToQueue({
  801. message: message,
  802. eventTime: Date.now()
  803. });
  804. };
  805. }
  806. /**
  807. * @license
  808. * Copyright 2020 Google LLC
  809. *
  810. * Licensed under the Apache License, Version 2.0 (the "License");
  811. * you may not use this file except in compliance with the License.
  812. * You may obtain a copy of the License at
  813. *
  814. * http://www.apache.org/licenses/LICENSE-2.0
  815. *
  816. * Unless required by applicable law or agreed to in writing, software
  817. * distributed under the License is distributed on an "AS IS" BASIS,
  818. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  819. * See the License for the specific language governing permissions and
  820. * limitations under the License.
  821. */
  822. /* eslint-enble camelcase */
  823. var logger;
  824. // This method is not called before initialization.
  825. function sendLog(resource, resourceType) {
  826. if (!logger) {
  827. logger = transportHandler(serializer);
  828. }
  829. logger(resource, resourceType);
  830. }
  831. function logTrace(trace) {
  832. var settingsService = SettingsService.getInstance();
  833. // Do not log if trace is auto generated and instrumentation is disabled.
  834. if (!settingsService.instrumentationEnabled && trace.isAuto) {
  835. return;
  836. }
  837. // Do not log if trace is custom and data collection is disabled.
  838. if (!settingsService.dataCollectionEnabled && !trace.isAuto) {
  839. return;
  840. }
  841. // Do not log if required apis are not available.
  842. if (!Api.getInstance().requiredApisAvailable()) {
  843. return;
  844. }
  845. // Only log the page load auto traces if page is visible.
  846. if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) {
  847. return;
  848. }
  849. if (isPerfInitialized()) {
  850. sendTraceLog(trace);
  851. }
  852. else {
  853. // Custom traces can be used before the initialization but logging
  854. // should wait until after.
  855. getInitializationPromise(trace.performanceController).then(function () { return sendTraceLog(trace); }, function () { return sendTraceLog(trace); });
  856. }
  857. }
  858. function sendTraceLog(trace) {
  859. if (!getIid()) {
  860. return;
  861. }
  862. var settingsService = SettingsService.getInstance();
  863. if (!settingsService.loggingEnabled ||
  864. !settingsService.logTraceAfterSampling) {
  865. return;
  866. }
  867. setTimeout(function () { return sendLog(trace, 1 /* ResourceType.Trace */); }, 0);
  868. }
  869. function logNetworkRequest(networkRequest) {
  870. var settingsService = SettingsService.getInstance();
  871. // Do not log network requests if instrumentation is disabled.
  872. if (!settingsService.instrumentationEnabled) {
  873. return;
  874. }
  875. // Do not log the js sdk's call to transport service domain to avoid unnecessary cycle.
  876. // Need to blacklist both old and new endpoints to avoid migration gap.
  877. var networkRequestUrl = networkRequest.url;
  878. // Blacklist old log endpoint and new transport endpoint.
  879. // Because Performance SDK doesn't instrument requests sent from SDK itself.
  880. var logEndpointUrl = settingsService.logEndPointUrl.split('?')[0];
  881. var flEndpointUrl = settingsService.flTransportEndpointUrl.split('?')[0];
  882. if (networkRequestUrl === logEndpointUrl ||
  883. networkRequestUrl === flEndpointUrl) {
  884. return;
  885. }
  886. if (!settingsService.loggingEnabled ||
  887. !settingsService.logNetworkAfterSampling) {
  888. return;
  889. }
  890. setTimeout(function () { return sendLog(networkRequest, 0 /* ResourceType.NetworkRequest */); }, 0);
  891. }
  892. function serializer(resource, resourceType) {
  893. if (resourceType === 0 /* ResourceType.NetworkRequest */) {
  894. return serializeNetworkRequest(resource);
  895. }
  896. return serializeTrace(resource);
  897. }
  898. function serializeNetworkRequest(networkRequest) {
  899. var networkRequestMetric = {
  900. url: networkRequest.url,
  901. http_method: networkRequest.httpMethod || 0,
  902. http_response_code: 200,
  903. response_payload_bytes: networkRequest.responsePayloadBytes,
  904. client_start_time_us: networkRequest.startTimeUs,
  905. time_to_response_initiated_us: networkRequest.timeToResponseInitiatedUs,
  906. time_to_response_completed_us: networkRequest.timeToResponseCompletedUs
  907. };
  908. var perfMetric = {
  909. application_info: getApplicationInfo(networkRequest.performanceController.app),
  910. network_request_metric: networkRequestMetric
  911. };
  912. return JSON.stringify(perfMetric);
  913. }
  914. function serializeTrace(trace) {
  915. var traceMetric = {
  916. name: trace.name,
  917. is_auto: trace.isAuto,
  918. client_start_time_us: trace.startTimeUs,
  919. duration_us: trace.durationUs
  920. };
  921. if (Object.keys(trace.counters).length !== 0) {
  922. traceMetric.counters = trace.counters;
  923. }
  924. var customAttributes = trace.getAttributes();
  925. if (Object.keys(customAttributes).length !== 0) {
  926. traceMetric.custom_attributes = customAttributes;
  927. }
  928. var perfMetric = {
  929. application_info: getApplicationInfo(trace.performanceController.app),
  930. trace_metric: traceMetric
  931. };
  932. return JSON.stringify(perfMetric);
  933. }
  934. function getApplicationInfo(firebaseApp) {
  935. return {
  936. google_app_id: getAppId(firebaseApp),
  937. app_instance_id: getIid(),
  938. web_app_info: {
  939. sdk_version: SDK_VERSION,
  940. page_url: Api.getInstance().getUrl(),
  941. service_worker_status: getServiceWorkerStatus(),
  942. visibility_state: getVisibilityState(),
  943. effective_connection_type: getEffectiveConnectionType()
  944. },
  945. application_process_state: 0
  946. };
  947. }
  948. /**
  949. * @license
  950. * Copyright 2020 Google LLC
  951. *
  952. * Licensed under the Apache License, Version 2.0 (the "License");
  953. * you may not use this file except in compliance with the License.
  954. * You may obtain a copy of the License at
  955. *
  956. * http://www.apache.org/licenses/LICENSE-2.0
  957. *
  958. * Unless required by applicable law or agreed to in writing, software
  959. * distributed under the License is distributed on an "AS IS" BASIS,
  960. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  961. * See the License for the specific language governing permissions and
  962. * limitations under the License.
  963. */
  964. var MAX_METRIC_NAME_LENGTH = 100;
  965. var RESERVED_AUTO_PREFIX = '_';
  966. var oobMetrics = [
  967. FIRST_PAINT_COUNTER_NAME,
  968. FIRST_CONTENTFUL_PAINT_COUNTER_NAME,
  969. FIRST_INPUT_DELAY_COUNTER_NAME
  970. ];
  971. /**
  972. * Returns true if the metric is custom and does not start with reserved prefix, or if
  973. * the metric is one of out of the box page load trace metrics.
  974. */
  975. function isValidMetricName(name, traceName) {
  976. if (name.length === 0 || name.length > MAX_METRIC_NAME_LENGTH) {
  977. return false;
  978. }
  979. return ((traceName &&
  980. traceName.startsWith(OOB_TRACE_PAGE_LOAD_PREFIX) &&
  981. oobMetrics.indexOf(name) > -1) ||
  982. !name.startsWith(RESERVED_AUTO_PREFIX));
  983. }
  984. /**
  985. * Converts the provided value to an integer value to be used in case of a metric.
  986. * @param providedValue Provided number value of the metric that needs to be converted to an integer.
  987. *
  988. * @returns Converted integer number to be set for the metric.
  989. */
  990. function convertMetricValueToInteger(providedValue) {
  991. var valueAsInteger = Math.floor(providedValue);
  992. if (valueAsInteger < providedValue) {
  993. consoleLogger.info("Metric value should be an Integer, setting the value as : ".concat(valueAsInteger, "."));
  994. }
  995. return valueAsInteger;
  996. }
  997. /**
  998. * @license
  999. * Copyright 2020 Google LLC
  1000. *
  1001. * Licensed under the Apache License, Version 2.0 (the "License");
  1002. * you may not use this file except in compliance with the License.
  1003. * You may obtain a copy of the License at
  1004. *
  1005. * http://www.apache.org/licenses/LICENSE-2.0
  1006. *
  1007. * Unless required by applicable law or agreed to in writing, software
  1008. * distributed under the License is distributed on an "AS IS" BASIS,
  1009. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1010. * See the License for the specific language governing permissions and
  1011. * limitations under the License.
  1012. */
  1013. var Trace = /** @class */ (function () {
  1014. /**
  1015. * @param performanceController The performance controller running.
  1016. * @param name The name of the trace.
  1017. * @param isAuto If the trace is auto-instrumented.
  1018. * @param traceMeasureName The name of the measure marker in user timing specification. This field
  1019. * is only set when the trace is built for logging when the user directly uses the user timing
  1020. * api (performance.mark and performance.measure).
  1021. */
  1022. function Trace(performanceController, name, isAuto, traceMeasureName) {
  1023. if (isAuto === void 0) { isAuto = false; }
  1024. this.performanceController = performanceController;
  1025. this.name = name;
  1026. this.isAuto = isAuto;
  1027. this.state = 1 /* TraceState.UNINITIALIZED */;
  1028. this.customAttributes = {};
  1029. this.counters = {};
  1030. this.api = Api.getInstance();
  1031. this.randomId = Math.floor(Math.random() * 1000000);
  1032. if (!this.isAuto) {
  1033. this.traceStartMark = "".concat(TRACE_START_MARK_PREFIX, "-").concat(this.randomId, "-").concat(this.name);
  1034. this.traceStopMark = "".concat(TRACE_STOP_MARK_PREFIX, "-").concat(this.randomId, "-").concat(this.name);
  1035. this.traceMeasure =
  1036. traceMeasureName ||
  1037. "".concat(TRACE_MEASURE_PREFIX, "-").concat(this.randomId, "-").concat(this.name);
  1038. if (traceMeasureName) {
  1039. // For the case of direct user timing traces, no start stop will happen. The measure object
  1040. // is already available.
  1041. this.calculateTraceMetrics();
  1042. }
  1043. }
  1044. }
  1045. /**
  1046. * Starts a trace. The measurement of the duration starts at this point.
  1047. */
  1048. Trace.prototype.start = function () {
  1049. if (this.state !== 1 /* TraceState.UNINITIALIZED */) {
  1050. throw ERROR_FACTORY.create("trace started" /* ErrorCode.TRACE_STARTED_BEFORE */, {
  1051. traceName: this.name
  1052. });
  1053. }
  1054. this.api.mark(this.traceStartMark);
  1055. this.state = 2 /* TraceState.RUNNING */;
  1056. };
  1057. /**
  1058. * Stops the trace. The measurement of the duration of the trace stops at this point and trace
  1059. * is logged.
  1060. */
  1061. Trace.prototype.stop = function () {
  1062. if (this.state !== 2 /* TraceState.RUNNING */) {
  1063. throw ERROR_FACTORY.create("trace stopped" /* ErrorCode.TRACE_STOPPED_BEFORE */, {
  1064. traceName: this.name
  1065. });
  1066. }
  1067. this.state = 3 /* TraceState.TERMINATED */;
  1068. this.api.mark(this.traceStopMark);
  1069. this.api.measure(this.traceMeasure, this.traceStartMark, this.traceStopMark);
  1070. this.calculateTraceMetrics();
  1071. logTrace(this);
  1072. };
  1073. /**
  1074. * Records a trace with predetermined values. If this method is used a trace is created and logged
  1075. * directly. No need to use start and stop methods.
  1076. * @param startTime Trace start time since epoch in millisec
  1077. * @param duration The duraction of the trace in millisec
  1078. * @param options An object which can optionally hold maps of custom metrics and custom attributes
  1079. */
  1080. Trace.prototype.record = function (startTime, duration, options) {
  1081. if (startTime <= 0) {
  1082. throw ERROR_FACTORY.create("nonpositive trace startTime" /* ErrorCode.NONPOSITIVE_TRACE_START_TIME */, {
  1083. traceName: this.name
  1084. });
  1085. }
  1086. if (duration <= 0) {
  1087. throw ERROR_FACTORY.create("nonpositive trace duration" /* ErrorCode.NONPOSITIVE_TRACE_DURATION */, {
  1088. traceName: this.name
  1089. });
  1090. }
  1091. this.durationUs = Math.floor(duration * 1000);
  1092. this.startTimeUs = Math.floor(startTime * 1000);
  1093. if (options && options.attributes) {
  1094. this.customAttributes = tslib.__assign({}, options.attributes);
  1095. }
  1096. if (options && options.metrics) {
  1097. for (var _i = 0, _a = Object.keys(options.metrics); _i < _a.length; _i++) {
  1098. var metricName = _a[_i];
  1099. if (!isNaN(Number(options.metrics[metricName]))) {
  1100. this.counters[metricName] = Math.floor(Number(options.metrics[metricName]));
  1101. }
  1102. }
  1103. }
  1104. logTrace(this);
  1105. };
  1106. /**
  1107. * Increments a custom metric by a certain number or 1 if number not specified. Will create a new
  1108. * custom metric if one with the given name does not exist. The value will be floored down to an
  1109. * integer.
  1110. * @param counter Name of the custom metric
  1111. * @param numAsInteger Increment by value
  1112. */
  1113. Trace.prototype.incrementMetric = function (counter, numAsInteger) {
  1114. if (numAsInteger === void 0) { numAsInteger = 1; }
  1115. if (this.counters[counter] === undefined) {
  1116. this.putMetric(counter, numAsInteger);
  1117. }
  1118. else {
  1119. this.putMetric(counter, this.counters[counter] + numAsInteger);
  1120. }
  1121. };
  1122. /**
  1123. * Sets a custom metric to a specified value. Will create a new custom metric if one with the
  1124. * given name does not exist. The value will be floored down to an integer.
  1125. * @param counter Name of the custom metric
  1126. * @param numAsInteger Set custom metric to this value
  1127. */
  1128. Trace.prototype.putMetric = function (counter, numAsInteger) {
  1129. if (isValidMetricName(counter, this.name)) {
  1130. this.counters[counter] = convertMetricValueToInteger(numAsInteger !== null && numAsInteger !== void 0 ? numAsInteger : 0);
  1131. }
  1132. else {
  1133. throw ERROR_FACTORY.create("invalid custom metric name" /* ErrorCode.INVALID_CUSTOM_METRIC_NAME */, {
  1134. customMetricName: counter
  1135. });
  1136. }
  1137. };
  1138. /**
  1139. * Returns the value of the custom metric by that name. If a custom metric with that name does
  1140. * not exist will return zero.
  1141. * @param counter
  1142. */
  1143. Trace.prototype.getMetric = function (counter) {
  1144. return this.counters[counter] || 0;
  1145. };
  1146. /**
  1147. * Sets a custom attribute of a trace to a certain value.
  1148. * @param attr
  1149. * @param value
  1150. */
  1151. Trace.prototype.putAttribute = function (attr, value) {
  1152. var isValidName = isValidCustomAttributeName(attr);
  1153. var isValidValue = isValidCustomAttributeValue(value);
  1154. if (isValidName && isValidValue) {
  1155. this.customAttributes[attr] = value;
  1156. return;
  1157. }
  1158. // Throw appropriate error when the attribute name or value is invalid.
  1159. if (!isValidName) {
  1160. throw ERROR_FACTORY.create("invalid attribute name" /* ErrorCode.INVALID_ATTRIBUTE_NAME */, {
  1161. attributeName: attr
  1162. });
  1163. }
  1164. if (!isValidValue) {
  1165. throw ERROR_FACTORY.create("invalid attribute value" /* ErrorCode.INVALID_ATTRIBUTE_VALUE */, {
  1166. attributeValue: value
  1167. });
  1168. }
  1169. };
  1170. /**
  1171. * Retrieves the value a custom attribute of a trace is set to.
  1172. * @param attr
  1173. */
  1174. Trace.prototype.getAttribute = function (attr) {
  1175. return this.customAttributes[attr];
  1176. };
  1177. Trace.prototype.removeAttribute = function (attr) {
  1178. if (this.customAttributes[attr] === undefined) {
  1179. return;
  1180. }
  1181. delete this.customAttributes[attr];
  1182. };
  1183. Trace.prototype.getAttributes = function () {
  1184. return tslib.__assign({}, this.customAttributes);
  1185. };
  1186. Trace.prototype.setStartTime = function (startTime) {
  1187. this.startTimeUs = startTime;
  1188. };
  1189. Trace.prototype.setDuration = function (duration) {
  1190. this.durationUs = duration;
  1191. };
  1192. /**
  1193. * Calculates and assigns the duration and start time of the trace using the measure performance
  1194. * entry.
  1195. */
  1196. Trace.prototype.calculateTraceMetrics = function () {
  1197. var perfMeasureEntries = this.api.getEntriesByName(this.traceMeasure);
  1198. var perfMeasureEntry = perfMeasureEntries && perfMeasureEntries[0];
  1199. if (perfMeasureEntry) {
  1200. this.durationUs = Math.floor(perfMeasureEntry.duration * 1000);
  1201. this.startTimeUs = Math.floor((perfMeasureEntry.startTime + this.api.getTimeOrigin()) * 1000);
  1202. }
  1203. };
  1204. /**
  1205. * @param navigationTimings A single element array which contains the navigationTIming object of
  1206. * the page load
  1207. * @param paintTimings A array which contains paintTiming object of the page load
  1208. * @param firstInputDelay First input delay in millisec
  1209. */
  1210. Trace.createOobTrace = function (performanceController, navigationTimings, paintTimings, firstInputDelay) {
  1211. var route = Api.getInstance().getUrl();
  1212. if (!route) {
  1213. return;
  1214. }
  1215. var trace = new Trace(performanceController, OOB_TRACE_PAGE_LOAD_PREFIX + route, true);
  1216. var timeOriginUs = Math.floor(Api.getInstance().getTimeOrigin() * 1000);
  1217. trace.setStartTime(timeOriginUs);
  1218. // navigationTimings includes only one element.
  1219. if (navigationTimings && navigationTimings[0]) {
  1220. trace.setDuration(Math.floor(navigationTimings[0].duration * 1000));
  1221. trace.putMetric('domInteractive', Math.floor(navigationTimings[0].domInteractive * 1000));
  1222. trace.putMetric('domContentLoadedEventEnd', Math.floor(navigationTimings[0].domContentLoadedEventEnd * 1000));
  1223. trace.putMetric('loadEventEnd', Math.floor(navigationTimings[0].loadEventEnd * 1000));
  1224. }
  1225. var FIRST_PAINT = 'first-paint';
  1226. var FIRST_CONTENTFUL_PAINT = 'first-contentful-paint';
  1227. if (paintTimings) {
  1228. var firstPaint = paintTimings.find(function (paintObject) { return paintObject.name === FIRST_PAINT; });
  1229. if (firstPaint && firstPaint.startTime) {
  1230. trace.putMetric(FIRST_PAINT_COUNTER_NAME, Math.floor(firstPaint.startTime * 1000));
  1231. }
  1232. var firstContentfulPaint = paintTimings.find(function (paintObject) { return paintObject.name === FIRST_CONTENTFUL_PAINT; });
  1233. if (firstContentfulPaint && firstContentfulPaint.startTime) {
  1234. trace.putMetric(FIRST_CONTENTFUL_PAINT_COUNTER_NAME, Math.floor(firstContentfulPaint.startTime * 1000));
  1235. }
  1236. if (firstInputDelay) {
  1237. trace.putMetric(FIRST_INPUT_DELAY_COUNTER_NAME, Math.floor(firstInputDelay * 1000));
  1238. }
  1239. }
  1240. logTrace(trace);
  1241. };
  1242. Trace.createUserTimingTrace = function (performanceController, measureName) {
  1243. var trace = new Trace(performanceController, measureName, false, measureName);
  1244. logTrace(trace);
  1245. };
  1246. return Trace;
  1247. }());
  1248. /**
  1249. * @license
  1250. * Copyright 2020 Google LLC
  1251. *
  1252. * Licensed under the Apache License, Version 2.0 (the "License");
  1253. * you may not use this file except in compliance with the License.
  1254. * You may obtain a copy of the License at
  1255. *
  1256. * http://www.apache.org/licenses/LICENSE-2.0
  1257. *
  1258. * Unless required by applicable law or agreed to in writing, software
  1259. * distributed under the License is distributed on an "AS IS" BASIS,
  1260. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1261. * See the License for the specific language governing permissions and
  1262. * limitations under the License.
  1263. */
  1264. function createNetworkRequestEntry(performanceController, entry) {
  1265. var performanceEntry = entry;
  1266. if (!performanceEntry || performanceEntry.responseStart === undefined) {
  1267. return;
  1268. }
  1269. var timeOrigin = Api.getInstance().getTimeOrigin();
  1270. var startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
  1271. var timeToResponseInitiatedUs = performanceEntry.responseStart
  1272. ? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
  1273. : undefined;
  1274. var timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
  1275. // Remove the query params from logged network request url.
  1276. var url = performanceEntry.name && performanceEntry.name.split('?')[0];
  1277. var networkRequest = {
  1278. performanceController: performanceController,
  1279. url: url,
  1280. responsePayloadBytes: performanceEntry.transferSize,
  1281. startTimeUs: startTimeUs,
  1282. timeToResponseInitiatedUs: timeToResponseInitiatedUs,
  1283. timeToResponseCompletedUs: timeToResponseCompletedUs
  1284. };
  1285. logNetworkRequest(networkRequest);
  1286. }
  1287. /**
  1288. * @license
  1289. * Copyright 2020 Google LLC
  1290. *
  1291. * Licensed under the Apache License, Version 2.0 (the "License");
  1292. * you may not use this file except in compliance with the License.
  1293. * You may obtain a copy of the License at
  1294. *
  1295. * http://www.apache.org/licenses/LICENSE-2.0
  1296. *
  1297. * Unless required by applicable law or agreed to in writing, software
  1298. * distributed under the License is distributed on an "AS IS" BASIS,
  1299. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1300. * See the License for the specific language governing permissions and
  1301. * limitations under the License.
  1302. */
  1303. var FID_WAIT_TIME_MS = 5000;
  1304. function setupOobResources(performanceController) {
  1305. // Do not initialize unless iid is available.
  1306. if (!getIid()) {
  1307. return;
  1308. }
  1309. // The load event might not have fired yet, and that means performance navigation timing
  1310. // object has a duration of 0. The setup should run after all current tasks in js queue.
  1311. setTimeout(function () { return setupOobTraces(performanceController); }, 0);
  1312. setTimeout(function () { return setupNetworkRequests(performanceController); }, 0);
  1313. setTimeout(function () { return setupUserTimingTraces(performanceController); }, 0);
  1314. }
  1315. function setupNetworkRequests(performanceController) {
  1316. var api = Api.getInstance();
  1317. var resources = api.getEntriesByType('resource');
  1318. for (var _i = 0, resources_1 = resources; _i < resources_1.length; _i++) {
  1319. var resource = resources_1[_i];
  1320. createNetworkRequestEntry(performanceController, resource);
  1321. }
  1322. api.setupObserver('resource', function (entry) {
  1323. return createNetworkRequestEntry(performanceController, entry);
  1324. });
  1325. }
  1326. function setupOobTraces(performanceController) {
  1327. var api = Api.getInstance();
  1328. var navigationTimings = api.getEntriesByType('navigation');
  1329. var paintTimings = api.getEntriesByType('paint');
  1330. // If First Input Desly polyfill is added to the page, report the fid value.
  1331. // https://github.com/GoogleChromeLabs/first-input-delay
  1332. if (api.onFirstInputDelay) {
  1333. // If the fid call back is not called for certain time, continue without it.
  1334. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  1335. var timeoutId_1 = setTimeout(function () {
  1336. Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
  1337. timeoutId_1 = undefined;
  1338. }, FID_WAIT_TIME_MS);
  1339. api.onFirstInputDelay(function (fid) {
  1340. if (timeoutId_1) {
  1341. clearTimeout(timeoutId_1);
  1342. Trace.createOobTrace(performanceController, navigationTimings, paintTimings, fid);
  1343. }
  1344. });
  1345. }
  1346. else {
  1347. Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
  1348. }
  1349. }
  1350. function setupUserTimingTraces(performanceController) {
  1351. var api = Api.getInstance();
  1352. // Run through the measure performance entries collected up to this point.
  1353. var measures = api.getEntriesByType('measure');
  1354. for (var _i = 0, measures_1 = measures; _i < measures_1.length; _i++) {
  1355. var measure = measures_1[_i];
  1356. createUserTimingTrace(performanceController, measure);
  1357. }
  1358. // Setup an observer to capture the measures from this point on.
  1359. api.setupObserver('measure', function (entry) {
  1360. return createUserTimingTrace(performanceController, entry);
  1361. });
  1362. }
  1363. function createUserTimingTrace(performanceController, measure) {
  1364. var measureName = measure.name;
  1365. // Do not create a trace, if the user timing marks and measures are created by the sdk itself.
  1366. if (measureName.substring(0, TRACE_MEASURE_PREFIX.length) ===
  1367. TRACE_MEASURE_PREFIX) {
  1368. return;
  1369. }
  1370. Trace.createUserTimingTrace(performanceController, measureName);
  1371. }
  1372. /**
  1373. * @license
  1374. * Copyright 2020 Google LLC
  1375. *
  1376. * Licensed under the Apache License, Version 2.0 (the "License");
  1377. * you may not use this file except in compliance with the License.
  1378. * You may obtain a copy of the License at
  1379. *
  1380. * http://www.apache.org/licenses/LICENSE-2.0
  1381. *
  1382. * Unless required by applicable law or agreed to in writing, software
  1383. * distributed under the License is distributed on an "AS IS" BASIS,
  1384. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1385. * See the License for the specific language governing permissions and
  1386. * limitations under the License.
  1387. */
  1388. var PerformanceController = /** @class */ (function () {
  1389. function PerformanceController(app, installations) {
  1390. this.app = app;
  1391. this.installations = installations;
  1392. this.initialized = false;
  1393. }
  1394. /**
  1395. * This method *must* be called internally as part of creating a
  1396. * PerformanceController instance.
  1397. *
  1398. * Currently it's not possible to pass the settings object through the
  1399. * constructor using Components, so this method exists to be called with the
  1400. * desired settings, to ensure nothing is collected without the user's
  1401. * consent.
  1402. */
  1403. PerformanceController.prototype._init = function (settings) {
  1404. var _this = this;
  1405. if (this.initialized) {
  1406. return;
  1407. }
  1408. if ((settings === null || settings === void 0 ? void 0 : settings.dataCollectionEnabled) !== undefined) {
  1409. this.dataCollectionEnabled = settings.dataCollectionEnabled;
  1410. }
  1411. if ((settings === null || settings === void 0 ? void 0 : settings.instrumentationEnabled) !== undefined) {
  1412. this.instrumentationEnabled = settings.instrumentationEnabled;
  1413. }
  1414. if (Api.getInstance().requiredApisAvailable()) {
  1415. util.validateIndexedDBOpenable()
  1416. .then(function (isAvailable) {
  1417. if (isAvailable) {
  1418. setupTransportService();
  1419. getInitializationPromise(_this).then(function () { return setupOobResources(_this); }, function () { return setupOobResources(_this); });
  1420. _this.initialized = true;
  1421. }
  1422. })
  1423. .catch(function (error) {
  1424. consoleLogger.info("Environment doesn't support IndexedDB: ".concat(error));
  1425. });
  1426. }
  1427. else {
  1428. consoleLogger.info('Firebase Performance cannot start if the browser does not support ' +
  1429. '"Fetch" and "Promise", or cookies are disabled.');
  1430. }
  1431. };
  1432. Object.defineProperty(PerformanceController.prototype, "instrumentationEnabled", {
  1433. get: function () {
  1434. return SettingsService.getInstance().instrumentationEnabled;
  1435. },
  1436. set: function (val) {
  1437. SettingsService.getInstance().instrumentationEnabled = val;
  1438. },
  1439. enumerable: false,
  1440. configurable: true
  1441. });
  1442. Object.defineProperty(PerformanceController.prototype, "dataCollectionEnabled", {
  1443. get: function () {
  1444. return SettingsService.getInstance().dataCollectionEnabled;
  1445. },
  1446. set: function (val) {
  1447. SettingsService.getInstance().dataCollectionEnabled = val;
  1448. },
  1449. enumerable: false,
  1450. configurable: true
  1451. });
  1452. return PerformanceController;
  1453. }());
  1454. /**
  1455. * Firebase Performance Monitoring
  1456. *
  1457. * @packageDocumentation
  1458. */
  1459. var DEFAULT_ENTRY_NAME = '[DEFAULT]';
  1460. /**
  1461. * Returns a {@link FirebasePerformance} instance for the given app.
  1462. * @param app - The {@link @firebase/app#FirebaseApp} to use.
  1463. * @public
  1464. */
  1465. function getPerformance(app$1) {
  1466. if (app$1 === void 0) { app$1 = app.getApp(); }
  1467. app$1 = util.getModularInstance(app$1);
  1468. var provider = app._getProvider(app$1, 'performance');
  1469. var perfInstance = provider.getImmediate();
  1470. return perfInstance;
  1471. }
  1472. /**
  1473. * Returns a {@link FirebasePerformance} instance for the given app. Can only be called once.
  1474. * @param app - The {@link @firebase/app#FirebaseApp} to use.
  1475. * @param settings - Optional settings for the {@link FirebasePerformance} instance.
  1476. * @public
  1477. */
  1478. function initializePerformance(app$1, settings) {
  1479. app$1 = util.getModularInstance(app$1);
  1480. var provider = app._getProvider(app$1, 'performance');
  1481. // throw if an instance was already created.
  1482. // It could happen if initializePerformance() is called more than once, or getPerformance() is called first.
  1483. if (provider.isInitialized()) {
  1484. var existingInstance = provider.getImmediate();
  1485. var initialSettings = provider.getOptions();
  1486. if (util.deepEqual(initialSettings, settings !== null && settings !== void 0 ? settings : {})) {
  1487. return existingInstance;
  1488. }
  1489. else {
  1490. throw ERROR_FACTORY.create("already initialized" /* ErrorCode.ALREADY_INITIALIZED */);
  1491. }
  1492. }
  1493. var perfInstance = provider.initialize({
  1494. options: settings
  1495. });
  1496. return perfInstance;
  1497. }
  1498. /**
  1499. * Returns a new `PerformanceTrace` instance.
  1500. * @param performance - The {@link FirebasePerformance} instance to use.
  1501. * @param name - The name of the trace.
  1502. * @public
  1503. */
  1504. function trace(performance, name) {
  1505. performance = util.getModularInstance(performance);
  1506. return new Trace(performance, name);
  1507. }
  1508. var factory = function (container, _a) {
  1509. var settings = _a.options;
  1510. // Dependencies
  1511. var app = container.getProvider('app').getImmediate();
  1512. var installations = container
  1513. .getProvider('installations-internal')
  1514. .getImmediate();
  1515. if (app.name !== DEFAULT_ENTRY_NAME) {
  1516. throw ERROR_FACTORY.create("FB not default" /* ErrorCode.FB_NOT_DEFAULT */);
  1517. }
  1518. if (typeof window === 'undefined') {
  1519. throw ERROR_FACTORY.create("no window" /* ErrorCode.NO_WINDOW */);
  1520. }
  1521. setupApi(window);
  1522. var perfInstance = new PerformanceController(app, installations);
  1523. perfInstance._init(settings);
  1524. return perfInstance;
  1525. };
  1526. function registerPerformance() {
  1527. app._registerComponent(new component.Component('performance', factory, "PUBLIC" /* ComponentType.PUBLIC */));
  1528. app.registerVersion(name, version);
  1529. // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
  1530. app.registerVersion(name, version, 'cjs5');
  1531. }
  1532. registerPerformance();
  1533. exports.getPerformance = getPerformance;
  1534. exports.initializePerformance = initializePerformance;
  1535. exports.trace = trace;
  1536. //# sourceMappingURL=index.cjs.js.map