Skip to content

Commit

Permalink
Merge pull request #496 from MindscapeHQ/ht/fix-deprecated-page-timin…
Browse files Browse the repository at this point in the history
…g-api

Fix potential access to deprecated web API's
  • Loading branch information
Hamish-taylor authored Aug 10, 2023
2 parents 8d78ba2 + 38baeaf commit 15f4b86
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 23 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!--- EXAMPLE
## [1.1.1]
## [2.27.x]
### Added
Expand All @@ -30,6 +30,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
-->

## [2.27.0]

### Changed

- Page timings are now gathered by default from PerformanceNavigationTiming instead of PerformanceTiming when available. This was done because the PerformanceTiming API has been deprecated.
- Now defaults to using the `PerformanceObserver` object to trigger RUM. This ensures it occurs after the page is fully loaded and all timing objects are populated

### Fixed

- Fixed bug that could stop `captureMissingRequests` from being set.
- Fixed potential access to PerformanceTiming API in browsers where it has been deprecated


## v2.26.6

Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "raygun4js",
"version": "2.26.6",
"version": "2.27.0",
"homepage": "http://raygun.com",
"authors": [
"Mindscape <hello@raygun.com>"
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
],
"title": "Raygun4js",
"description": "Raygun.com plugin for JavaScript",
"version": "2.26.6",
"version": "2.27.0",
"homepage": "https://github.com/MindscapeHQ/raygun4js",
"author": {
"name": "MindscapeHQ",
Expand Down
2 changes: 1 addition & 1 deletion raygun4js.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>raygun4js</id>
<version>2.26.6</version>
<version>2.27.0</version>
<title>Raygun4js</title>
<authors>Raygun Limited</authors>
<owners>Raygun Limited</owners>
Expand Down
12 changes: 10 additions & 2 deletions src/raygun.loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
errorQueue = window[window['RaygunObject']].q;
var rg = Raygun;

var delayedExecutionFunctions = ['trackEvent', 'send', 'recordBreadcrumb'];
var delayedExecutionFunctions = ['trackEvent', 'send', 'recordBreadcrumb','captureMissingRequests'];

var parseSnippetOptions = function() {
snippetOptions = window[window['RaygunObject']].o;
Expand Down Expand Up @@ -279,8 +279,16 @@
};

if (!Raygun.Utilities.isReactNative()) {
var supportsNavigationTiming = !!window.PerformanceObserver && !!window.PerformanceObserver.supportedEntryTypes && window.PerformanceObserver.supportedEntryTypes.includes('navigation');
if (document.readyState === 'complete') {
onLoadHandler();
onLoadHandler();
} else if (supportsNavigationTiming) {
//The other 'load' events are called before the PerformanceNavigationTiming is completed resulting in `loadEventEnd` never being set which is needed to calculate the duration of the timing. This observer triggers after the timing is complete.
var observer = new window.PerformanceObserver(function () {
onLoadHandler();
});

observer.observe({ entryTypes: ['navigation'] });
} else if (window.addEventListener) {
window.addEventListener('load', onLoadHandler);
} else {
Expand Down
33 changes: 18 additions & 15 deletions src/raygun.rum/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,15 +537,21 @@ var raygunRumFactory = function (window, $, Raygun) {
return data;
}

function extractChildData(collection, fromVirtualPage, forceSend) {
function extractChildData(collection, parentIsVirtualPage, forceSend) {
if (!performanceEntryExists('getEntries', 'function')) {
return;
}

try {
var offset = fromVirtualPage ? 0 : window.performance.timing.navigationStart;
var resources = window.performance.getEntries();
var offset = 0;
var navigationEntries = window.performance.getEntriesByType('navigation'); //this tries to fetch the PerformanceNavigationTiming object (this is the new timing API)
if (parentIsVirtualPage || navigationEntries && navigationEntries.length > 0) {
offset = 0; //start time is always 0 with the new api & virtual page so the offset is always 0
} else {
offset = window.performance.timing.navigationStart;
}
var i;
var resources = window.performance.getEntries();

for (i = self.offset; i < resources.length; i++) {
var resource = resources[i];
Expand Down Expand Up @@ -716,10 +722,12 @@ var raygunRumFactory = function (window, $, Raygun) {
}.bind(this);

function getEncodedTimingData() {
var timing = window.performance.timing;

//Try to default to the new timing object, if not use the old
var performanceNavigationTiming = window.performance.getEntriesByType('navigation')[0]; // The navigationEntries array will contain one entry, as it represents the current navigation
var timing = performanceNavigationTiming || window.performance.timing;

var data = {
du: timing.duration,
du: getTimingDuration(timing),
t: Timings.Page,
};

Expand Down Expand Up @@ -1058,13 +1066,8 @@ var raygunRumFactory = function (window, $, Raygun) {
* This utility fallsback to using the responseEnd - startTime when
* that is the case.
*/
var duration = timing.duration;

if (duration !== 0) {
return duration;
}

return timing.responseEnd - timing.startTime;

return timing.duration || (timing.responseEnd - timing.startTime) || 0;
}
this.Utilities["getTimingDuration"] = getTimingDuration;

Expand Down Expand Up @@ -1168,8 +1171,8 @@ var raygunRumFactory = function (window, $, Raygun) {

function shouldIgnoreResource(resource) {
var name = resource.name.split('?')[0];

return shouldIgnoreResourceByName(name) || resource.entryType === "paint" || resource.entryType === "navigation" || resource.entryType === "mark";
//We want to ignore 'navigation' and 'visibility-state' as they are used for the main page timing, so we dont want to use them for the child objects
return shouldIgnoreResourceByName(name) || resource.entryType === "paint" || resource.entryType === "mark"|| resource.entryType === "navigation" || resource.entryType === "visibility-state";
}

function shouldIgnoreResourceByName(name) {
Expand Down

0 comments on commit 15f4b86

Please sign in to comment.