Skip to content

Commit 4b8506e

Browse files
authored
feat: link lcp attribution to image resource and navigation page load (#448)
1 parent 7339c78 commit 4b8506e

File tree

16 files changed

+401
-34
lines changed

16 files changed

+401
-34
lines changed

app/assets/lcp.png

3.98 KB
Loading

app/web_vital_event.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,6 @@
111111
<td id="response_body"></td>
112112
</tr>
113113
</table>
114+
<img src="assets/lcp.png" alt="LCP resource image" />
114115
</body>
115116
</html>

src/dispatch/dataplane.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// use the type definitions from the CloudWatch RUM SDK, we have made a copy of
66
// them here to completely remove the dependency on the CloudWatch RUM SDK.
77

8+
import { MetaData } from '../events/meta-data';
9+
810
export interface PutRumEventsRequest {
911
BatchId: string;
1012
AppMonitorDetails: AppMonitorDetails;
@@ -29,3 +31,11 @@ export interface RumEvent {
2931
metadata?: string;
3032
details: string;
3133
}
34+
35+
export interface ParsedRumEvent {
36+
id: string;
37+
timestamp: Date;
38+
type: string;
39+
metadata?: MetaData;
40+
details: object;
41+
}

src/event-bus/EventBus.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default class EventBus<T = Topic> {
1010

1111
subscribe(topic: T, subscriber: Subscriber): void {
1212
const list = this.subscribers.get(topic) ?? [];
13-
if (list.length === 0) {
13+
if (!list.length) {
1414
this.subscribers.set(topic, list);
1515
}
1616
list.push(subscriber);

src/event-bus/__tests__/EventBus.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
1-
import EventBus from '../EventBus';
1+
import { context } from '../../test-utils/test-utils';
2+
import EventBus, { Topic } from '../EventBus';
3+
import { InternalPlugin } from '../../plugins/InternalPlugin';
4+
import { PluginContext } from '../../plugins/types';
25

36
export enum MockTopics {
47
FOOD = 'food',
58
BOOKS = 'books'
69
}
10+
11+
const MockPluginId = 'Mock-Plugin';
12+
class MockPlugin extends InternalPlugin {
13+
count = 0;
14+
15+
constructor() {
16+
super(MockPluginId);
17+
this.subscriber = this.subscriber.bind(this);
18+
}
19+
20+
enable(): void {} // eslint-disable-line
21+
disable(): void {} // eslint-disable-line
22+
23+
protected onload(): void {
24+
this.context.eventBus.subscribe(Topic.EVENT, this.subscriber); // eslint-disable-line
25+
}
26+
27+
subscriber(msg: any) {
28+
this.count++;
29+
}
30+
}
31+
732
describe('EventBus tests', () => {
833
let eventBus: EventBus<MockTopics>;
934
const l1 = jest.fn();
@@ -50,4 +75,14 @@ describe('EventBus tests', () => {
5075
// assert
5176
expect(l2).not.toHaveBeenCalled();
5277
});
78+
79+
test('when plugin subscribes then observes events', async () => {
80+
const plugin = new MockPlugin();
81+
const spy = jest.spyOn(plugin, 'subscriber');
82+
83+
plugin.load(context);
84+
context.eventBus.dispatch(Topic.EVENT, 'hat');
85+
86+
expect(spy).toHaveBeenCalledWith('hat');
87+
});
5388
});

src/event-schemas/largest-contentful-paint-event.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
"elementRenderDelay": {
4141
"type": "number",
4242
"description": "Duration rendering the LCP resource"
43+
},
44+
"navigationEntry": {
45+
"type": "string",
46+
"description": "Event id of the navigation event for the current page"
47+
},
48+
"lcpResourceEntry": {
49+
"type": "string",
50+
"description": "Event id of the resource event for the LCP resource, if any"
4351
}
4452
},
4553
"required": [

src/loader/loader-web-vital-event.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import { loader } from './loader';
22
import { showRequestClientBuilder } from '../test-utils/mock-http-handler';
33
import { WebVitalsPlugin } from '../plugins/event-plugins/WebVitalsPlugin';
4+
import { NavigationPlugin } from '../plugins/event-plugins/NavigationPlugin';
5+
import { ResourcePlugin } from '../plugins/event-plugins/ResourcePlugin';
46
loader('cwr', 'abc123', '1.0', 'us-west-2', './rum_javascript_telemetry.js', {
57
dispatchInterval: 0,
68
metaDataPluginsToLoad: [],
7-
eventPluginsToLoad: [new WebVitalsPlugin()],
9+
eventPluginsToLoad: [
10+
new ResourcePlugin(),
11+
new NavigationPlugin(),
12+
new WebVitalsPlugin()
13+
],
814
telemetries: [],
915
clientBuilder: showRequestClientBuilder
1016
});

src/orchestration/Orchestration.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ export class Orchestration {
402402
id: applicationId,
403403
version: applicationVersion
404404
},
405-
this.config
405+
this.config,
406+
this.eventBus
406407
);
407408
}
408409

src/orchestration/__tests__/Orchestration.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ jest.mock('../../dispatch/Dispatch', () => ({
2121
}))
2222
}));
2323

24+
jest.mock('../../utils/common-utils', () => {
25+
const originalModule = jest.requireActual('../../utils/common-utils');
26+
return {
27+
__esModule: true,
28+
...originalModule,
29+
isLCPSupported: jest.fn().mockReturnValue(true)
30+
};
31+
});
32+
2433
const enableEventCache = jest.fn();
2534
const disableEventCache = jest.fn();
2635
const recordPageView = jest.fn();

src/plugins/event-plugins/ResourcePlugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export class ResourcePlugin extends InternalPlugin {
8484

8585
recordResourceEvent = ({
8686
name,
87+
startTime,
8788
initiatorType,
8889
duration,
8990
transferSize
@@ -105,6 +106,7 @@ export class ResourcePlugin extends InternalPlugin {
105106
const eventData: ResourceEvent = {
106107
version: '1.0.0',
107108
initiatorType,
109+
startTime,
108110
duration,
109111
fileType: getResourceFileType(name, initiatorType),
110112
transferSize

0 commit comments

Comments
 (0)