Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial webvitals integration #25

Merged
merged 5 commits into from
Dec 7, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions integration-tests/tests/webvitals/webvitals.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webvitals</title>

<%- renderAgent({debug: true}) %>
</head>
<body>
<p>Webvitals</p>
<script>
let id = 1;
function clicky() {
const p = document.createElement('p');
p.setAttribute('id', 'p'+id);
id++;
p.innerText = 'Very long paragraph to force a visual change. '.repeat(30);
document.body.firstElementChild.appendChild(p);
}
window.addEventListener('load', clicky);
</script>
<!-- a dummy "interactive" link in order to compute FID -->
<a href="javascript:clicky()" id="clicky">Click me</a>
</body>
</html>
56 changes: 56 additions & 0 deletions integration-tests/tests/webvitals/webvitals.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2020 Splunk Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

module.exports = {
'webvitals spans': async function(browser) {
// the google webvitals library only works on chrome (and chrome-based edge) at the moment
const SUPPORTED_BROWSERS = ['Chrome', 'chrome', 'Edge'];
const currentBrowser = browser.options.desiredCapabilities.browserName;
if (!SUPPORTED_BROWSERS.includes(currentBrowser)) {
return;
}

const url = browser.globals.getUrl('/webvitals/webvitals.ejs');
await browser.url(url);
// fid won't happen unless there is interaction, so simulate a bit of that
await browser.click('#clicky');
await browser.waitForElementPresent('#p2');
// webvitals library won't send the cls unless a visibility change happens, so
// force a fake one
await browser.execute(function() {
Object.defineProperty(document, 'visibilityState', { value: 'hidden', configurable: true });
document.dispatchEvent(new Event('visibilitychange'));
});

const lcp = await browser.globals.findSpan(span => span.tags.lcp !== undefined);
const cls = await browser.globals.findSpan(span => span.tags.cls !== undefined);
const fid = await browser.globals.findSpan(span => span.tags.fid !== undefined);

await browser.assert.ok(lcp);
await browser.assert.ok(cls);
await browser.assert.ok(fid);

await browser.assert.strictEqual(lcp.name, 'webvitals');
await browser.assert.strictEqual(cls.name, 'webvitals');
await browser.assert.strictEqual(fid.name, 'webvitals');

await browser.assert.ok(lcp.tags.lcp >= 0);
await browser.assert.ok(cls.tags.cls >= 0);
await browser.assert.ok(fid.tags.fid >= 0);

await browser.end();
}
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"author": "",
"license": "Apache-2.0",
"dependencies": {
"shimmer": "^1.2.1"
"shimmer": "^1.2.1",
"web-vitals": "^1.0.1"
},
"devDependencies": {
"@rollup/plugin-alias": "^3.1.1",
Expand Down
2 changes: 2 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {captureErrors} from './errors';
import {findCookieValue, generateId} from './utils';
import {version as SplunkRumVersion} from '../package.json';
import {WebSocketInstrumentation} from './websocket';
import { initWebVitals } from './webvitals';

function browserSupported() {
// FIXME very short-term patch for Safari 10.1 -> upstream fixes pending
Expand Down Expand Up @@ -152,6 +153,7 @@ if (!window.SplunkRum) {
// stub out error reporting method to not break apps that call it
this.error = function() { };
}
initWebVitals(provider);
this.inited = true;
console.log('SplunkRum.init() complete');
};
Expand Down
43 changes: 43 additions & 0 deletions src/webvitals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Copyright 2020 Splunk Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import {getCLS,getLCP,getFID} from 'web-vitals';
const reported = {};

function report(tracer, name, metric) {
if (reported[name]) {
return;
}
reported[name] = true;
const value = metric.value;
const span = tracer.startSpan('webvitals');
span.setAttribute(name, value);
span.end(span.startTime);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have we confirmed this with Justin? or are we deciding now it's going to be sent like that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent point. I'll post on the team channel and seek some input.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to approve this, but now I'm not sure, I can't seem to find any conclusions in that Slack thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read it as "looks good enough" but we can wait another day or two for any more objections/discussion to pop up.

}

export function initWebVitals(provider) {
const tracer = provider.getTracer('webvitals');
// CLS is defined as being sent more than once, easier to just ensure that everything is sent just on the first occurence.
getFID((metric) => {
report(tracer, 'fid', metric);
});
getCLS((metric) => {
report(tracer, 'cls', metric);
});
getLCP((metric) => {
report(tracer, 'lcp', metric);
});
}