@@ -11,6 +11,7 @@ import { getFID } from './web-vitals/getFID';
11
11
import { getLCP } from './web-vitals/getLCP' ;
12
12
import { getTTFB } from './web-vitals/getTTFB' ;
13
13
import { getFirstHidden } from './web-vitals/lib/getFirstHidden' ;
14
+ import { NavigatorDeviceMemory , NavigatorNetworkInformation } from './web-vitals/types' ;
14
15
15
16
const global = getGlobalObject < Window > ( ) ;
16
17
@@ -129,6 +130,8 @@ export class MetricsInstrumentation {
129
130
130
131
this . _performanceCursor = Math . max ( performance . getEntries ( ) . length - 1 , 0 ) ;
131
132
133
+ this . _trackNavigator ( transaction ) ;
134
+
132
135
// Measurements are only available for pageload transactions
133
136
if ( transaction . op === 'pageload' ) {
134
137
transaction . setMeasurements ( this . _measurements ) ;
@@ -149,6 +152,46 @@ export class MetricsInstrumentation {
149
152
} ) ;
150
153
}
151
154
155
+ /**
156
+ * Capture the information of the user agent.
157
+ */
158
+ private _trackNavigator ( transaction : Transaction ) : void {
159
+ const navigator = global . navigator as null | ( Navigator & NavigatorNetworkInformation & NavigatorDeviceMemory ) ;
160
+
161
+ if ( ! navigator ) {
162
+ return ;
163
+ }
164
+
165
+ // track network connectivity
166
+
167
+ const connection = navigator . connection ;
168
+ if ( connection ) {
169
+ if ( connection . effectiveType ) {
170
+ transaction . setTag ( 'effectiveConnectionType' , connection . effectiveType ) ;
171
+ }
172
+
173
+ if ( connection . type ) {
174
+ transaction . setTag ( 'connectionType' , connection . type ) ;
175
+ }
176
+
177
+ if ( isMeasurementValue ( connection . rtt ) ) {
178
+ this . _measurements [ 'connection.rtt' ] = { value : connection . rtt as number } ;
179
+ }
180
+
181
+ if ( isMeasurementValue ( connection . downlink ) ) {
182
+ this . _measurements [ 'connection.downlink' ] = { value : connection . downlink as number } ;
183
+ }
184
+ }
185
+
186
+ if ( isMeasurementValue ( navigator . deviceMemory ) ) {
187
+ transaction . setTag ( 'deviceMemory' , String ( navigator . deviceMemory ) ) ;
188
+ }
189
+
190
+ if ( isMeasurementValue ( navigator . hardwareConcurrency ) ) {
191
+ transaction . setTag ( 'hardwareConcurrency' , String ( navigator . hardwareConcurrency ) ) ;
192
+ }
193
+ }
194
+
152
195
/** Starts tracking the Largest Contentful Paint on the current page. */
153
196
private _trackLCP ( ) : void {
154
197
getLCP ( metric => {
@@ -332,3 +375,10 @@ export function _startChild(transaction: Transaction, { startTimestamp, ...ctx }
332
375
...ctx ,
333
376
} ) ;
334
377
}
378
+
379
+ /**
380
+ * Checks if a given value is a valid measurement value.
381
+ */
382
+ function isMeasurementValue ( value : any ) : boolean {
383
+ return typeof value === 'number' && isFinite ( value ) ;
384
+ }
0 commit comments