@adobe/spacecat-shared-rum-api-client 2.12.6 → 2.13.0
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/functions/cwv.js +132 -25
- package/src/index.d.ts +4 -0
- package/src/index.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-rum-api-client-v2.13.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.12.6...@adobe/spacecat-shared-rum-api-client-v2.13.0) (2024-11-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Introduce configurable grouping patterns ([#458](https://github.com/adobe/spacecat-shared/issues/458)) ([6414b13](https://github.com/adobe/spacecat-shared/commit/6414b13ccffdf567460efddb019f8f3de0200b5a))
|
|
7
|
+
|
|
1
8
|
# [@adobe/spacecat-shared-rum-api-client-v2.12.6](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-rum-api-client-v2.12.5...@adobe/spacecat-shared-rum-api-client-v2.12.6) (2024-11-27)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/functions/cwv.js
CHANGED
|
@@ -13,37 +13,144 @@
|
|
|
13
13
|
import {
|
|
14
14
|
DataChunks, series, facets,
|
|
15
15
|
} from '@adobe/rum-distiller';
|
|
16
|
-
import { loadBundles } from '../utils.js';
|
|
16
|
+
import { generateKey, DELIMITER, loadBundles } from '../utils.js';
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const METRICS = ['lcp', 'cls', 'inp', 'ttfb'];
|
|
19
|
+
|
|
20
|
+
const USER_AGENT_DELIMITER = ':';
|
|
21
|
+
|
|
22
|
+
const FACET_TYPE = {
|
|
23
|
+
GROUP: 'group',
|
|
24
|
+
URL: 'url',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const findMatchedPattern = (url, urlPatterns) => {
|
|
28
|
+
for (const urlPattern of urlPatterns) {
|
|
29
|
+
const regex = new RegExp(`^${urlPattern.pattern.replace(/\*/g, '.*')}$`);
|
|
30
|
+
if (regex.test(url)) {
|
|
31
|
+
return urlPattern;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const mapUrlsToPatterns = (bundles, patterns) => {
|
|
38
|
+
const urlToPatternMap = {};
|
|
39
|
+
if (!patterns || patterns.length === 0) {
|
|
40
|
+
return urlToPatternMap;
|
|
41
|
+
}
|
|
20
42
|
|
|
43
|
+
for (const bundle of bundles) {
|
|
44
|
+
const matchedPattern = findMatchedPattern(bundle.url, patterns);
|
|
45
|
+
|
|
46
|
+
if (matchedPattern) {
|
|
47
|
+
// Check if any cwv metric exists in bundle.events
|
|
48
|
+
const hasMetrics = bundle.events.some((event) => METRICS.some((metric) => event.checkpoint.includes(`cwv-${metric}`)));
|
|
49
|
+
|
|
50
|
+
if (hasMetrics) {
|
|
51
|
+
urlToPatternMap[bundle.url] = matchedPattern;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return urlToPatternMap;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const calculateMetricsPercentile = (metrics) => ({
|
|
59
|
+
lcp: metrics.lcp.percentile(75) || null,
|
|
60
|
+
lcpCount: metrics.lcp.count || 0,
|
|
61
|
+
cls: metrics.cls.percentile(75) || null,
|
|
62
|
+
clsCount: metrics.cls.count || 0,
|
|
63
|
+
inp: metrics.inp.percentile(75) || null,
|
|
64
|
+
inpCount: metrics.inp.count || 0,
|
|
65
|
+
ttfb: metrics.ttfb.percentile(75) || null,
|
|
66
|
+
ttfbCount: metrics.ttfb.count || 0,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
function handler(rawBundles, opts = []) {
|
|
70
|
+
const bundles = rawBundles.map((bundle) => ({
|
|
71
|
+
...bundle,
|
|
72
|
+
url: facets.url(bundle), // URL without ids, hashes, and other encoded data
|
|
73
|
+
}));
|
|
74
|
+
const urlToPatternMap = mapUrlsToPatterns(bundles, opts.groupedURLs);
|
|
75
|
+
|
|
76
|
+
const dataChunks = new DataChunks();
|
|
21
77
|
loadBundles(bundles, dataChunks);
|
|
22
78
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
79
|
+
// groups by url and device
|
|
80
|
+
dataChunks.addFacet(
|
|
81
|
+
'urlsDevices',
|
|
82
|
+
(bundle) => generateKey(bundle.url, bundle.userAgent.split(USER_AGENT_DELIMITER)[0]),
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// groups by pattern and device
|
|
86
|
+
dataChunks.addFacet('patternsDevices', (bundle) => {
|
|
87
|
+
const device = bundle.userAgent.split(USER_AGENT_DELIMITER)[0];
|
|
88
|
+
return urlToPatternMap[bundle.url]?.pattern
|
|
89
|
+
? generateKey(urlToPatternMap[bundle.url].pattern, device)
|
|
90
|
+
: null;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// counts metrics per each facet
|
|
94
|
+
METRICS.forEach((metric) => dataChunks.addSeries(metric, series[metric]));
|
|
95
|
+
|
|
96
|
+
const patternsResult = dataChunks.facets.patternsDevices.reduce((acc, facet) => {
|
|
97
|
+
const [pattern, deviceType] = facet.value.split(DELIMITER);
|
|
98
|
+
const patternData = Object.values(urlToPatternMap).find((p) => p.pattern === pattern);
|
|
99
|
+
|
|
100
|
+
acc[pattern] = acc[pattern] || {
|
|
101
|
+
type: FACET_TYPE.GROUP,
|
|
102
|
+
name: patternData.name,
|
|
103
|
+
pattern,
|
|
104
|
+
pageviews: 0,
|
|
105
|
+
metrics: [],
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Increment the total pageviews for pattern
|
|
109
|
+
acc[pattern].pageviews += facet.weight;
|
|
110
|
+
|
|
111
|
+
// Add metrics for the specific device type
|
|
112
|
+
acc[pattern].metrics.push({
|
|
113
|
+
deviceType,
|
|
114
|
+
pageviews: facet.weight, // Pageviews for this device type
|
|
115
|
+
...calculateMetricsPercentile(facet.metrics),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return acc;
|
|
119
|
+
}, {});
|
|
120
|
+
|
|
121
|
+
const urlsResult = dataChunks.facets.urlsDevices.reduce((acc, facet) => {
|
|
122
|
+
const [url, deviceType] = facet.value.split(DELIMITER);
|
|
123
|
+
|
|
124
|
+
acc[url] = acc[url] || {
|
|
125
|
+
type: FACET_TYPE.URL,
|
|
126
|
+
url,
|
|
127
|
+
pageviews: 0,
|
|
128
|
+
metrics: [],
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// Increment the total pageviews for url
|
|
132
|
+
acc[url].pageviews += facet.weight;
|
|
133
|
+
|
|
134
|
+
// Add metrics for the specific device type
|
|
135
|
+
acc[url].metrics.push({
|
|
136
|
+
deviceType,
|
|
137
|
+
pageviews: facet.weight, // Pageviews for this device type
|
|
138
|
+
...calculateMetricsPercentile(facet.metrics),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return acc;
|
|
142
|
+
}, {});
|
|
143
|
+
|
|
144
|
+
const result = [...Object.values(patternsResult), ...Object.values(urlsResult)]
|
|
145
|
+
// filter out pages with no cwv data
|
|
146
|
+
.filter((row) => METRICS.some((metric) => row.metrics.some((entry) => entry[metric])))
|
|
147
|
+
// sort desc by pageviews
|
|
148
|
+
.sort((a, b) => b.metrics.pageviews - a.metrics.pageviews);
|
|
149
|
+
|
|
150
|
+
return result;
|
|
44
151
|
}
|
|
45
152
|
|
|
46
153
|
export default {
|
|
47
154
|
handler,
|
|
48
|
-
checkpoints:
|
|
155
|
+
checkpoints: METRICS.map((metric) => `cwv-${metric}`),
|
|
49
156
|
};
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED