@@ -70,7 +70,8 @@ describe('_addMeasureSpans', () => {
|
70 | 70 | name: 'measure-1',
|
71 | 71 | duration: 10,
|
72 | 72 | startTime: 12,
|
73 |
| -} as PerformanceEntry; |
| 73 | +detail: null, |
| 74 | +} as PerformanceMeasure; |
74 | 75 |
|
75 | 76 | const timeOrigin = 100;
|
76 | 77 | const startTime = 23;
|
@@ -106,7 +107,8 @@ describe('_addMeasureSpans', () => {
|
106 | 107 | name: 'measure-1',
|
107 | 108 | duration: 10,
|
108 | 109 | startTime: 12,
|
109 |
| -} as PerformanceEntry; |
| 110 | +detail: null, |
| 111 | +} as PerformanceMeasure; |
110 | 112 |
|
111 | 113 | const timeOrigin = 100;
|
112 | 114 | const startTime = 23;
|
@@ -116,6 +118,165 @@ describe('_addMeasureSpans', () => {
|
116 | 118 |
|
117 | 119 | expect(spans).toHaveLength(0);
|
118 | 120 | });
|
| 121 | + |
| 122 | +it('adds measure spans with primitive detail', () => { |
| 123 | +const spans: Span[] = []; |
| 124 | + |
| 125 | +getClient()?.on('spanEnd', span => { |
| 126 | +spans.push(span); |
| 127 | +}); |
| 128 | + |
| 129 | +const entry = { |
| 130 | +entryType: 'measure', |
| 131 | +name: 'measure-1', |
| 132 | +duration: 10, |
| 133 | +startTime: 12, |
| 134 | +detail: 'test-detail', |
| 135 | +} as PerformanceMeasure; |
| 136 | + |
| 137 | +const timeOrigin = 100; |
| 138 | +const startTime = 23; |
| 139 | +const duration = 356; |
| 140 | + |
| 141 | +_addMeasureSpans(span, entry, startTime, duration, timeOrigin); |
| 142 | + |
| 143 | +expect(spans).toHaveLength(1); |
| 144 | +expect(spanToJSON(spans[0]!)).toEqual( |
| 145 | +expect.objectContaining({ |
| 146 | +description: 'measure-1', |
| 147 | +start_timestamp: timeOrigin + startTime, |
| 148 | +timestamp: timeOrigin + startTime + duration, |
| 149 | +op: 'measure', |
| 150 | +origin: 'auto.resource.browser.metrics', |
| 151 | +data: { |
| 152 | +[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'measure', |
| 153 | +[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics', |
| 154 | +'sentry.browser.measure.detail': 'test-detail', |
| 155 | +}, |
| 156 | +}), |
| 157 | +); |
| 158 | +}); |
| 159 | + |
| 160 | +it('adds measure spans with object detail', () => { |
| 161 | +const spans: Span[] = []; |
| 162 | + |
| 163 | +getClient()?.on('spanEnd', span => { |
| 164 | +spans.push(span); |
| 165 | +}); |
| 166 | + |
| 167 | +const detail = { |
| 168 | +component: 'Button', |
| 169 | +action: 'click', |
| 170 | +metadata: { id: 123 }, |
| 171 | +}; |
| 172 | + |
| 173 | +const entry = { |
| 174 | +entryType: 'measure', |
| 175 | +name: 'measure-1', |
| 176 | +duration: 10, |
| 177 | +startTime: 12, |
| 178 | +detail, |
| 179 | +} as PerformanceMeasure; |
| 180 | + |
| 181 | +const timeOrigin = 100; |
| 182 | +const startTime = 23; |
| 183 | +const duration = 356; |
| 184 | + |
| 185 | +_addMeasureSpans(span, entry, startTime, duration, timeOrigin); |
| 186 | + |
| 187 | +expect(spans).toHaveLength(1); |
| 188 | +expect(spanToJSON(spans[0]!)).toEqual( |
| 189 | +expect.objectContaining({ |
| 190 | +description: 'measure-1', |
| 191 | +start_timestamp: timeOrigin + startTime, |
| 192 | +timestamp: timeOrigin + startTime + duration, |
| 193 | +op: 'measure', |
| 194 | +origin: 'auto.resource.browser.metrics', |
| 195 | +data: { |
| 196 | +[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'measure', |
| 197 | +[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics', |
| 198 | +'sentry.browser.measure.detail.component': 'Button', |
| 199 | +'sentry.browser.measure.detail.action': 'click', |
| 200 | +'sentry.browser.measure.detail.metadata': JSON.stringify({ id: 123 }), |
| 201 | +}, |
| 202 | +}), |
| 203 | +); |
| 204 | +}); |
| 205 | + |
| 206 | +it('handles non-primitive detail values by stringifying them', () => { |
| 207 | +const spans: Span[] = []; |
| 208 | + |
| 209 | +getClient()?.on('spanEnd', span => { |
| 210 | +spans.push(span); |
| 211 | +}); |
| 212 | + |
| 213 | +const detail = { |
| 214 | +component: 'Button', |
| 215 | +action: 'click', |
| 216 | +metadata: { id: 123 }, |
| 217 | +callback: () => {}, |
| 218 | +}; |
| 219 | + |
| 220 | +const entry = { |
| 221 | +entryType: 'measure', |
| 222 | +name: 'measure-1', |
| 223 | +duration: 10, |
| 224 | +startTime: 12, |
| 225 | +detail, |
| 226 | +} as PerformanceMeasure; |
| 227 | + |
| 228 | +const timeOrigin = 100; |
| 229 | +const startTime = 23; |
| 230 | +const duration = 356; |
| 231 | + |
| 232 | +_addMeasureSpans(span, entry, startTime, duration, timeOrigin); |
| 233 | + |
| 234 | +expect(spans).toHaveLength(1); |
| 235 | +const spanData = spanToJSON(spans[0]!).data; |
| 236 | +expect(spanData['sentry.browser.measure.detail.component']).toBe('Button'); |
| 237 | +expect(spanData['sentry.browser.measure.detail.action']).toBe('click'); |
| 238 | +expect(spanData['sentry.browser.measure.detail.metadata']).toBe(JSON.stringify({ id: 123 })); |
| 239 | +expect(spanData['sentry.browser.measure.detail.callback']).toBe(JSON.stringify(detail.callback)); |
| 240 | +}); |
| 241 | + |
| 242 | +it('handles errors in object detail value stringification', () => { |
| 243 | +const spans: Span[] = []; |
| 244 | + |
| 245 | +getClient()?.on('spanEnd', span => { |
| 246 | +spans.push(span); |
| 247 | +}); |
| 248 | + |
| 249 | +const circular: any = {}; |
| 250 | +circular.self = circular; |
| 251 | + |
| 252 | +const detail = { |
| 253 | +component: 'Button', |
| 254 | +action: 'click', |
| 255 | +circular, |
| 256 | +}; |
| 257 | + |
| 258 | +const entry = { |
| 259 | +entryType: 'measure', |
| 260 | +name: 'measure-1', |
| 261 | +duration: 10, |
| 262 | +startTime: 12, |
| 263 | +detail, |
| 264 | +} as PerformanceMeasure; |
| 265 | + |
| 266 | +const timeOrigin = 100; |
| 267 | +const startTime = 23; |
| 268 | +const duration = 356; |
| 269 | + |
| 270 | +// Should not throw |
| 271 | +_addMeasureSpans(span, entry, startTime, duration, timeOrigin); |
| 272 | + |
| 273 | +expect(spans).toHaveLength(1); |
| 274 | +const spanData = spanToJSON(spans[0]!).data; |
| 275 | +expect(spanData['sentry.browser.measure.detail.component']).toBe('Button'); |
| 276 | +expect(spanData['sentry.browser.measure.detail.action']).toBe('click'); |
| 277 | +// The circular reference should be skipped |
| 278 | +expect(spanData['sentry.browser.measure.detail.circular']).toBeUndefined(); |
| 279 | +}); |
119 | 280 | });
|
120 | 281 |
|
121 | 282 | describe('_addResourceSpans', () => {
|
@@ -464,7 +625,6 @@ describe('_addNavigationSpans', () => {
|
464 | 625 | transferSize: 14726,
|
465 | 626 | encodedBodySize: 14426,
|
466 | 627 | decodedBodySize: 67232,
|
467 |
| -responseStatus: 200, |
468 | 628 | serverTiming: [],
|
469 | 629 | unloadEventStart: 0,
|
470 | 630 | unloadEventEnd: 0,
|
|
0 commit comments