diff --git a/packages/core/src/metrics/internal.ts b/packages/core/src/metrics/internal.ts index 443a5c508e80..830fb279303d 100644 --- a/packages/core/src/metrics/internal.ts +++ b/packages/core/src/metrics/internal.ts @@ -191,12 +191,12 @@ export function _INTERNAL_captureMetric(beforeMetric: Metric, options?: Internal : enrichedMetric; if (processedMetric === CALLBACK_ERROR) { - client.recordDroppedEvent('callback_error', 'metric', 1); + client.recordDroppedEvent('callback_error', 'trace_metric', 1); return; } if (!processedMetric) { - client.recordDroppedEvent('before_send', 'metric', 1); + client.recordDroppedEvent('before_send', 'trace_metric', 1); DEBUG_BUILD && debug.log('`beforeSendMetric` returned `null`, will not send metric.'); return; } diff --git a/packages/core/src/types/datacategory.ts b/packages/core/src/types/datacategory.ts index ad1e61732816..f778efd2f348 100644 --- a/packages/core/src/types/datacategory.ts +++ b/packages/core/src/types/datacategory.ts @@ -33,6 +33,6 @@ export type DataCategory = // Log bytes stored (unused for rate limiting) | 'log_byte' // Metric event - | 'metric' + | 'trace_metric' // Unknown data category | 'unknown'; diff --git a/packages/core/src/utils/envelope.ts b/packages/core/src/utils/envelope.ts index 4eacc1919410..dda72dce1c3e 100644 --- a/packages/core/src/utils/envelope.ts +++ b/packages/core/src/utils/envelope.ts @@ -195,7 +195,7 @@ export function createAttachmentEnvelopeItem(attachment: Attachment): Attachment type OverriddenItemType = Exclude; // Map of envelope item types to data categories where the category differs from the type. -// Types that map to themselves (session, attachment, transaction, profile, feedback, span, metric) fall through. +// Types that map to themselves (session, attachment, transaction, profile, feedback, span, trace_metric) fall through. const DATA_CATEGORY_OVERRIDES: Record = { sessions: 'session', event: 'error', @@ -207,7 +207,7 @@ const DATA_CATEGORY_OVERRIDES: Record = { check_in: 'monitor', raw_security: 'security', log: 'log_item', - trace_metric: 'metric', + metric: 'trace_metric', }; function _isOverriddenType(type: EnvelopeItemType): type is OverriddenItemType { diff --git a/packages/core/test/lib/metrics/internal.test.ts b/packages/core/test/lib/metrics/internal.test.ts index 3efda3259dfb..869f2ee38665 100644 --- a/packages/core/test/lib/metrics/internal.test.ts +++ b/packages/core/test/lib/metrics/internal.test.ts @@ -358,7 +358,7 @@ describe('_INTERNAL_captureMetric', () => { ); expect(beforeSendMetric).toHaveBeenCalled(); - expect(recordDroppedEventSpy).toHaveBeenCalledWith('before_send', 'metric', 1); + expect(recordDroppedEventSpy).toHaveBeenCalledWith('before_send', 'trace_metric', 1); expect(loggerWarnSpy).toHaveBeenCalledWith('`beforeSendMetric` returned `null`, will not send metric.'); expect(_INTERNAL_getMetricBuffer(client)).toBeUndefined(); @@ -385,7 +385,7 @@ describe('_INTERNAL_captureMetric', () => { expect(() => _INTERNAL_captureMetric({ type: 'counter', name: 'test.metric', value: 1 }, { scope })).not.toThrow(); expect(beforeSendMetric).toHaveBeenCalled(); - expect(recordDroppedEventSpy).toHaveBeenCalledWith('callback_error', 'metric', 1); + expect(recordDroppedEventSpy).toHaveBeenCalledWith('callback_error', 'trace_metric', 1); expect(debugErrorSpy).toHaveBeenCalledWith( 'The `beforeSendMetric` callback threw an error, dropping the metric:', exception, diff --git a/packages/core/test/lib/transports/base.test.ts b/packages/core/test/lib/transports/base.test.ts index 3ef558c349a1..6425977367b5 100644 --- a/packages/core/test/lib/transports/base.test.ts +++ b/packages/core/test/lib/transports/base.test.ts @@ -351,6 +351,34 @@ describe('createTransport', () => { expect(requestExecutor).not.toHaveBeenCalled(); expect(recordDroppedEventCallback).toHaveBeenCalledWith('ratelimit_backoff', 'log_item', 3); }); + + it('back-off using X-Sentry-Rate-Limits with trace_metric category', async () => { + const { retryAfterSeconds, beforeLimit, withinLimit } = setRateLimitTimes(); + const [transport, , requestExecutor, recordDroppedEventCallback] = createTestTransport({ + headers: { + 'x-sentry-rate-limits': `${retryAfterSeconds}:trace_metric:scope`, + 'retry-after': null, + }, + }); + + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => beforeLimit); + + await transport.send(ERROR_ENVELOPE); + requestExecutor.mockClear(); + + dateNowSpy.mockImplementation(() => withinLimit); + + await transport.send( + createEnvelope({ sent_at: '123' }, [ + [ + { type: 'trace_metric', item_count: 2, content_type: 'application/vnd.sentry.items.trace-metric+json' }, + { items: [] }, + ], + ] as Envelope[1]), + ); + expect(requestExecutor).not.toHaveBeenCalled(); + expect(recordDroppedEventCallback).toHaveBeenCalledWith('ratelimit_backoff', 'trace_metric', 2); + }); }); describe('Client Reports', () => { @@ -479,7 +507,7 @@ describe('createTransport', () => { expect(mockRecordDroppedEventCallback).toHaveBeenCalledTimes(3); expect(mockRecordDroppedEventCallback).toHaveBeenCalledWith('send_error', 'span', 5); expect(mockRecordDroppedEventCallback).toHaveBeenCalledWith('send_error', 'log_item', 3); - expect(mockRecordDroppedEventCallback).toHaveBeenCalledWith('send_error', 'metric', 2); + expect(mockRecordDroppedEventCallback).toHaveBeenCalledWith('send_error', 'trace_metric', 2); }); it('does not record outcomes for client reports when receiving 413', async () => {