diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 849e34f6c92b..53db1e1743fe 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -79,6 +79,7 @@ export { export { applyScopeDataToEvent, mergeScopeData } from './utils/applyScopeDataToEvent'; export { prepareEvent } from './utils/prepareEvent'; export { createCheckInEnvelope } from './checkin'; +export { createSpanEnvelope } from './span'; export { hasTracingEnabled } from './utils/hasTracingEnabled'; export { isSentryRequestUrl } from './utils/isSentryRequestUrl'; export { handleCallbackErrors } from './utils/handleCallbackErrors'; diff --git a/packages/core/src/span.ts b/packages/core/src/span.ts new file mode 100644 index 000000000000..405ceeddab30 --- /dev/null +++ b/packages/core/src/span.ts @@ -0,0 +1,22 @@ +import type { SpanEnvelope, SpanItem } from '@sentry/types'; +import type { Span } from '@sentry/types'; +import { createEnvelope } from '@sentry/utils'; + +/** + * Create envelope from Span item. + */ +export function createSpanEnvelope(spans: Span[]): SpanEnvelope { + const headers: SpanEnvelope[0] = { + sent_at: new Date().toISOString(), + }; + + const items = spans.map(createSpanItem); + return createEnvelope(headers, items); +} + +function createSpanItem(span: Span): SpanItem { + const spanHeaders: SpanItem[0] = { + type: 'span', + }; + return [spanHeaders, span]; +} diff --git a/packages/types/src/datacategory.ts b/packages/types/src/datacategory.ts index ca2acd29e235..b86c1bafdc9e 100644 --- a/packages/types/src/datacategory.ts +++ b/packages/types/src/datacategory.ts @@ -27,4 +27,6 @@ export type DataCategory = // Feedback type event (v2) | 'feedback' // Unknown data category - | 'unknown'; + | 'unknown' + // Span + | 'span'; diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index 98bb9145a547..fe08ce1962d1 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -7,6 +7,7 @@ import type { Profile } from './profiling'; import type { ReplayEvent, ReplayRecordingData } from './replay'; import type { SdkInfo } from './sdkinfo'; import type { SerializedSession, Session, SessionAggregates } from './session'; +import type { Span } from './span'; import type { Transaction } from './transaction'; import type { UserFeedback } from './user'; @@ -41,7 +42,8 @@ export type EnvelopeItemType = | 'replay_event' | 'replay_recording' | 'check_in' - | 'statsd'; + | 'statsd' + | 'span'; export type BaseEnvelopeHeaders = { [key: string]: unknown; @@ -82,6 +84,7 @@ type ReplayRecordingItemHeaders = { type: 'replay_recording'; length: number }; type CheckInItemHeaders = { type: 'check_in' }; type StatsdItemHeaders = { type: 'statsd'; length: number }; type ProfileItemHeaders = { type: 'profile' }; +type SpanItemHeaders = { type: 'span' }; // TODO (v8): Replace `Event` with `SerializedEvent` export type EventItem = BaseEnvelopeItem; @@ -98,6 +101,7 @@ type ReplayRecordingItem = BaseEnvelopeItem; export type FeedbackItem = BaseEnvelopeItem; export type ProfileItem = BaseEnvelopeItem; +export type SpanItem = BaseEnvelopeItem; export type EventEnvelopeHeaders = { event_id: string; sent_at: string; trace?: DynamicSamplingContext }; type SessionEnvelopeHeaders = { sent_at: string }; @@ -105,6 +109,7 @@ type CheckInEnvelopeHeaders = { trace?: DynamicSamplingContext }; type ClientReportEnvelopeHeaders = BaseEnvelopeHeaders; type ReplayEnvelopeHeaders = BaseEnvelopeHeaders; type StatsdEnvelopeHeaders = BaseEnvelopeHeaders; +type SpanEnvelopeHeaders = BaseEnvelopeHeaders; export type EventEnvelope = BaseEnvelope< EventEnvelopeHeaders, @@ -115,6 +120,7 @@ export type ClientReportEnvelope = BaseEnvelope; export type StatsdEnvelope = BaseEnvelope; +export type SpanEnvelope = BaseEnvelope; export type Envelope = | EventEnvelope @@ -122,5 +128,6 @@ export type Envelope = | ClientReportEnvelope | ReplayEnvelope | CheckInEnvelope - | StatsdEnvelope; + | StatsdEnvelope + | SpanEnvelope; export type EnvelopeItem = Envelope[1][number]; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index d4fcd439ae4a..a167f45aa5eb 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -45,6 +45,8 @@ export type { StatsdItem, StatsdEnvelope, ProfileItem, + SpanEnvelope, + SpanItem, } from './envelope'; export type { ExtendedError } from './error'; export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent, SerializedEvent } from './event'; diff --git a/packages/utils/src/envelope.ts b/packages/utils/src/envelope.ts index c716ab282dfe..1aa87938ed8c 100644 --- a/packages/utils/src/envelope.ts +++ b/packages/utils/src/envelope.ts @@ -209,6 +209,7 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP: Record = { replay_recording: 'replay', check_in: 'monitor', feedback: 'feedback', + span: 'span', // TODO: This is a temporary workaround until we have a proper data category for metrics statsd: 'unknown', };