Skip to content

Commit 732d105

Browse files
committed
feat: SMs for browser connect response
1 parent 09ff9b3 commit 732d105

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

docs/supportability-metrics.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,3 +439,11 @@ EventBuffer/soft_navigations/Dropped/Bytes
439439
* rrweb/node/3/bytes
440440
<!-- node type 4 = Meta -->
441441
* rrweb/node/4/bytes
442+
443+
### Browser Connect Response Metrics
444+
<!--- HTTP status code of failed browser connect response --->
445+
* Browser/Supportability/BCS/Error/StatusCode
446+
<!--- Total dropped payload size of failed browser connect response --->
447+
* Browser/Supportability/BCS/Error/Dropped/Bytes
448+
<!--- Response time of failed browser connect response --->
449+
* Browser/Supportability/BCS/Error/Duration/Ms

src/features/page_view_event/aggregate/index.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte'
1717
import { now } from '../../../common/timing/now'
1818
import { TimeKeeper } from '../../../common/timing/time-keeper'
1919
import { applyFnToProps } from '../../../common/util/traverse'
20+
import { send } from '../../../common/harvest/harvester'
21+
import { FEATURE_NAMES, FEATURE_TO_ENDPOINT } from '../../../loaders/features/features'
22+
import { getSubmitMethod } from '../../../common/util/submit-data'
2023

2124
export class Aggregate extends AggregateBase {
2225
static featureName = CONSTANTS.FEATURE_NAME
@@ -136,6 +139,54 @@ export class Aggregate extends AggregateBase {
136139

137140
if (status >= 400 || status === 0) {
138141
warn(18, status)
142+
143+
// Get estimated payload size of our backlog
144+
const textEncoder = new TextEncoder()
145+
const payloadSize = Object.values(newrelic.ee.backlog).reduce((acc, value) => {
146+
if (!value) return acc
147+
148+
const encoded = textEncoder.encode(value)
149+
return acc + encoded.byteLength
150+
}, 0)
151+
152+
// Send SMs about failed RUM request
153+
const body = {
154+
sm: [{
155+
params: {
156+
name: 'Browser/Supportability/BCS/Error/StatusCode'
157+
},
158+
stats: {
159+
c: 1,
160+
t: status
161+
}
162+
},
163+
{
164+
params: {
165+
name: 'Browser/Supportability/BCS/Error/Dropped/Bytes'
166+
},
167+
stats: {
168+
c: 1,
169+
t: payloadSize
170+
}
171+
},
172+
{
173+
params: {
174+
name: 'Browser/Supportability/BCS/Error/Duration/Ms'
175+
},
176+
stats: {
177+
c: 1,
178+
t: rumEndTime - this.rumStartTime
179+
}
180+
}]
181+
}
182+
183+
send(this.agentRef, {
184+
endpoint: FEATURE_TO_ENDPOINT[FEATURE_NAMES.metrics],
185+
payload: { body },
186+
submitMethod: getSubmitMethod(),
187+
featureName: FEATURE_NAMES.metrics
188+
})
189+
139190
// Adding retry logic for the rum call will be a separate change; this.blocked will need to be changed since that prevents another triggerHarvestFor()
140191
this.ee.abort()
141192
return
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { testRumRequest, testMetricsRequest } from '../../../tools/testing-server/utils/expect-tests'
2+
3+
describe('basic pve capturing', () => {
4+
let rumCapture
5+
let metricsCapture
6+
7+
beforeEach(async () => {
8+
[rumCapture, metricsCapture] = await browser.testHandle.createNetworkCaptures('bamServer', [
9+
{ test: testRumRequest },
10+
{ test: testMetricsRequest }
11+
])
12+
})
13+
14+
it('should report SMs when RUM call fails to browser connect service', async () => {
15+
// will reply with http status 500 to fake error response from browser connect service
16+
await browser.testHandle.scheduleReply('bamServer', {
17+
test: testRumRequest,
18+
statusCode: 500
19+
})
20+
21+
// visit the webpage, not waiting for agent load since we don't expect the rum feature to load properly
22+
await browser.url(await browser.testHandle.assetURL('instrumented.html'))
23+
24+
// wait for rum response harvest
25+
const rumHarvest = await rumCapture.waitForResult({ totalCount: 1 })
26+
27+
// RUM harvest should have the expected http status code from the bam server
28+
expect(rumHarvest[0].reply.statusCode).toBe(500)
29+
30+
// wait for supportability metrics harvest
31+
const smHarvest = await metricsCapture.waitForResult({ totalCount: 1 })
32+
33+
// check for expected properties on status code supportability metric
34+
const smHarvestStatusCode = smHarvest[0].request.body.sm.find(sm => sm.params.name === 'Browser/Supportability/BCS/Error/StatusCode')
35+
expect(smHarvestStatusCode).toBeDefined()
36+
expect(smHarvestStatusCode.stats).toBeDefined()
37+
expect(smHarvestStatusCode.stats.c).toBe(1)
38+
expect(smHarvestStatusCode.stats.t).toBe(500)
39+
40+
// check for expected properties on dropped bytes supportability metric
41+
const smHarvestDroppedBytes = smHarvest[0].request.body.sm.find(sm => sm.params.name === 'Browser/Supportability/BCS/Error/Dropped/Bytes')
42+
expect(smHarvestDroppedBytes).toBeDefined()
43+
expect(smHarvestDroppedBytes.stats).toBeDefined()
44+
expect(smHarvestDroppedBytes.stats.c).toBe(1)
45+
expect(smHarvestDroppedBytes.stats.t).toBeGreaterThan(0)
46+
47+
// check for expected properties on response time supportability metric
48+
const smHarvestResponseTime = smHarvest[0].request.body.sm.find(sm => sm.params.name === 'Browser/Supportability/BCS/Error/Duration/Ms')
49+
expect(smHarvestResponseTime).toBeDefined()
50+
expect(smHarvestResponseTime.stats).toBeDefined()
51+
expect(smHarvestResponseTime.stats.c).toBe(1)
52+
expect(smHarvestResponseTime.stats.t).toBeGreaterThan(0)
53+
})
54+
})

0 commit comments

Comments
 (0)