Skip to content

Commit ea8111c

Browse files
authored
test(profiles): test sample stats and raw weights across formats (#43685)
Adds tests for rawWeights cross profile formats.
1 parent b242dfd commit ea8111c

File tree

12 files changed

+271
-75
lines changed

12 files changed

+271
-75
lines changed

static/app/utils/profiling/profile/chromeTraceProfile.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ export function collapseSamples(profile: ChromeTrace.CpuProfile): {
513513
elapsed = Math.max(elapsed + profile.timeDeltas[i + 1], elapsed);
514514
}
515515
}
516+
516517
return {samples, sampleTimes};
517518
}
518519

static/app/utils/profiling/profile/eventedProfile.spec.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,30 @@ describe('EventedProfile', () => {
6767
expect(profile.stats.negativeSamplesCount).toBe(1);
6868
});
6969

70+
it('tracks raw weights', () => {
71+
const trace: Profiling.EventedProfile = {
72+
name: 'profile',
73+
startValue: 0,
74+
endValue: 1000,
75+
unit: 'milliseconds',
76+
threadID: 0,
77+
type: 'evented',
78+
events: [
79+
{type: 'O', at: 0, frame: 0},
80+
{type: 'C', at: 10, frame: 0},
81+
{type: 'O', at: 15, frame: 0},
82+
{type: 'C', at: 20, frame: 0},
83+
],
84+
};
85+
86+
const profile = EventedProfile.FromProfile(
87+
trace,
88+
createFrameIndex('mobile', [{name: 'f0'}])
89+
);
90+
91+
expect(profile.rawWeights.length).toBe(2);
92+
});
93+
7094
it('rebuilds the stack', () => {
7195
const trace: Profiling.EventedProfile = {
7296
name: 'profile',

static/app/utils/profiling/profile/eventedProfile.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,9 @@ export class EventedProfile extends Profile {
8181
}
8282
}
8383

84-
recordRawWeight(at: number) {
85-
const weight = at - this.lastValue;
86-
if (weight > 0) {
87-
this.rawWeights.push(weight);
88-
}
89-
}
90-
9184
enterFrame(frame: Frame, at: number): void {
9285
this.addWeightToFrames(at);
9386
this.addWeightsToNodes(at);
94-
this.recordRawWeight(at);
9587

9688
const lastTop = lastOfArray(this.appendOrderStack);
9789

@@ -146,7 +138,6 @@ export class EventedProfile extends Profile {
146138
this.addWeightToFrames(at);
147139
this.addWeightsToNodes(at);
148140
this.trackSampleStats(at);
149-
this.recordRawWeight(at);
150141

151142
const leavingStackTop = this.appendOrderStack.pop();
152143

static/app/utils/profiling/profile/importProfile.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {JSSelfProfile} from 'sentry/utils/profiling/profile/jsSelfProfile';
88
import {SampledProfile} from 'sentry/utils/profiling/profile/sampledProfile';
99

1010
import {SentrySampledProfile} from './sentrySampledProfile';
11-
import {makeSentrySampledProfile} from './sentrySampledProfile.specutil';
11+
import {makeSentrySampledProfile} from './sentrySampledProfile.spec';
1212

1313
describe('importProfile', () => {
1414
it('imports evented profile', () => {

static/app/utils/profiling/profile/jsSelfProfile.spec.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,37 @@ describe('jsSelfProfile', () => {
8585
expect(profile.stats.negativeSamplesCount).toBe(1);
8686
});
8787

88+
it('tracks raw weights', () => {
89+
const trace: JSSelfProfiling.Trace = {
90+
resources: ['app.js', 'vendor.js'],
91+
frames: [{name: 'ReactDOM.render', line: 1, column: 1, resourceId: 0}],
92+
samples: [
93+
{
94+
timestamp: 5,
95+
},
96+
{
97+
timestamp: 10,
98+
},
99+
{
100+
timestamp: 15,
101+
},
102+
],
103+
stacks: [
104+
{
105+
frameId: 0,
106+
},
107+
],
108+
};
109+
110+
const profile = JSSelfProfile.FromProfile(
111+
trace,
112+
createFrameIndex('web', [{name: 'f0'}])
113+
);
114+
// For JsSelfProfile, first sample is appended with 0 weight because it
115+
// contains the stack sample of when startProfile was called
116+
expect(profile.rawWeights.length).toBe(2);
117+
});
118+
88119
it('handles the first stack sample differently', () => {
89120
const trace: JSSelfProfiling.Trace = {
90121
resources: ['app.js'],

static/app/utils/profiling/profile/profile.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ export class Profile {
8787
if (duration < 0) {
8888
this.stats.negativeSamplesCount++;
8989
}
90+
if (duration > 0) {
91+
this.rawWeights.push(duration);
92+
}
9093
}
9194

9295
forEach(

static/app/utils/profiling/profile/sampledProfile.spec.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,25 @@ describe('SampledProfile', () => {
6363
expect(profile.stats.negativeSamplesCount).toBe(1);
6464
});
6565

66+
it('tracks raw weights', () => {
67+
const trace: Profiling.SampledProfile = {
68+
name: 'profile',
69+
startValue: 0,
70+
endValue: 1000,
71+
unit: 'milliseconds',
72+
threadID: 0,
73+
type: 'sampled',
74+
weights: [0, 10, 20],
75+
samples: [[0], [0], []],
76+
};
77+
78+
const profile = SampledProfile.FromProfile(
79+
trace,
80+
createFrameIndex('mobile', [{name: 'f0'}])
81+
);
82+
expect(profile.rawWeights.length).toBe(2);
83+
});
84+
6685
it('rebuilds the stack', () => {
6786
const trace: Profiling.SampledProfile = {
6887
name: 'profile',

static/app/utils/profiling/profile/sampledProfile.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ export class SampledProfile extends Profile {
151151
this.samples.push(node);
152152
this.weights.push(weight);
153153
}
154-
this.rawWeights.push(weight);
155154
}
156155

157156
build(): Profile {

static/app/utils/profiling/profile/sentrySampledProfile.spec.tsx

Lines changed: 190 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,69 @@
1+
import merge from 'lodash/merge';
2+
3+
import {DeepPartial} from 'sentry/types/utils';
4+
15
import {makeTestingBoilerplate} from './profile.spec';
26
import {SentrySampledProfile} from './sentrySampledProfile';
3-
import {makeSentrySampledProfile} from './sentrySampledProfile.specutil';
47
import {createSentrySampleProfileFrameIndex} from './utils';
58

9+
export const makeSentrySampledProfile = (
10+
profile?: DeepPartial<Profiling.SentrySampledProfile>
11+
) => {
12+
return merge(
13+
{
14+
event_id: '1',
15+
version: '1',
16+
os: {
17+
name: 'iOS',
18+
version: '16.0',
19+
build_number: '19H253',
20+
},
21+
device: {
22+
architecture: 'arm64e',
23+
is_emulator: false,
24+
locale: 'en_US',
25+
manufacturer: 'Apple',
26+
model: 'iPhone14,3',
27+
},
28+
timestamp: '2022-09-01T09:45:00.000Z',
29+
release: '0.1 (199)',
30+
platform: 'cocoa',
31+
profile: {
32+
samples: [
33+
{
34+
stack_id: 0,
35+
thread_id: '0',
36+
elapsed_since_start_ns: '0',
37+
},
38+
{
39+
stack_id: 1,
40+
thread_id: '0',
41+
elapsed_since_start_ns: '1000',
42+
},
43+
],
44+
frames: [
45+
{
46+
function: 'foo',
47+
instruction_addr: '',
48+
lineno: 2,
49+
colno: 2,
50+
file: 'main.c',
51+
},
52+
{
53+
function: 'main',
54+
instruction_addr: '',
55+
lineno: 1,
56+
colno: 1,
57+
file: 'main.c',
58+
},
59+
],
60+
stacks: [[0], [0, 1]],
61+
},
62+
},
63+
profile
64+
) as Profiling.SentrySampledProfile;
65+
};
66+
667
describe('SentrySampledProfile', () => {
768
it('constructs a profile', () => {
869
const sampledProfile: Profiling.SentrySampledProfile = makeSentrySampledProfile();
@@ -26,6 +87,134 @@ describe('SentrySampledProfile', () => {
2687
expect(profile.endedAt).toEqual(1000);
2788
});
2889

90+
it('tracks discarded samples', () => {
91+
const sampledProfile = makeSentrySampledProfile({
92+
transactions: [
93+
{
94+
id: '',
95+
name: 'foo',
96+
active_thread_id: '1',
97+
relative_start_ns: '0',
98+
relative_end_ns: '1000000',
99+
trace_id: '1',
100+
},
101+
],
102+
profile: {
103+
samples: [
104+
{
105+
stack_id: 0,
106+
elapsed_since_start_ns: '1000',
107+
thread_id: '0',
108+
},
109+
{
110+
stack_id: 0,
111+
elapsed_since_start_ns: '1000',
112+
thread_id: '0',
113+
},
114+
],
115+
thread_metadata: {
116+
'0': {
117+
name: 'bar',
118+
},
119+
},
120+
},
121+
});
122+
123+
const profile = SentrySampledProfile.FromProfile(
124+
sampledProfile,
125+
createSentrySampleProfileFrameIndex(sampledProfile.profile.frames)
126+
);
127+
128+
expect(profile.stats.discardedSamplesCount).toBe(1);
129+
});
130+
131+
it('tracks negative samples', () => {
132+
const sampledProfile = makeSentrySampledProfile({
133+
transactions: [
134+
{
135+
id: '',
136+
name: 'foo',
137+
active_thread_id: '1',
138+
relative_start_ns: '0',
139+
relative_end_ns: '1000000',
140+
trace_id: '1',
141+
},
142+
],
143+
profile: {
144+
samples: [
145+
{
146+
stack_id: 0,
147+
elapsed_since_start_ns: '1000',
148+
thread_id: '0',
149+
},
150+
{
151+
stack_id: 0,
152+
elapsed_since_start_ns: '-1000',
153+
thread_id: '0',
154+
},
155+
],
156+
thread_metadata: {
157+
'0': {
158+
name: 'bar',
159+
},
160+
},
161+
},
162+
});
163+
164+
const profile = SentrySampledProfile.FromProfile(
165+
sampledProfile,
166+
createSentrySampleProfileFrameIndex(sampledProfile.profile.frames)
167+
);
168+
169+
expect(profile.stats.negativeSamplesCount).toBe(1);
170+
});
171+
172+
it('tracks raw weights', () => {
173+
const sampledProfile = makeSentrySampledProfile({
174+
transactions: [
175+
{
176+
id: '',
177+
name: 'foo',
178+
active_thread_id: '1',
179+
relative_start_ns: '0',
180+
relative_end_ns: '1000000',
181+
trace_id: '1',
182+
},
183+
],
184+
profile: {
185+
samples: [
186+
{
187+
stack_id: 0,
188+
elapsed_since_start_ns: '1000',
189+
thread_id: '0',
190+
},
191+
{
192+
stack_id: 0,
193+
elapsed_since_start_ns: '2000',
194+
thread_id: '0',
195+
},
196+
{
197+
stack_id: 0,
198+
elapsed_since_start_ns: '3000',
199+
thread_id: '0',
200+
},
201+
],
202+
thread_metadata: {
203+
'0': {
204+
name: 'bar',
205+
},
206+
},
207+
},
208+
});
209+
210+
const profile = SentrySampledProfile.FromProfile(
211+
sampledProfile,
212+
createSentrySampleProfileFrameIndex(sampledProfile.profile.frames)
213+
);
214+
215+
expect(profile.rawWeights.length).toBe(3);
216+
});
217+
29218
it('derives a profile name from the transaction.name and thread_id', () => {
30219
const sampledProfile = makeSentrySampledProfile({
31220
transactions: [

0 commit comments

Comments
 (0)