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