import type {TraceContextType} from 'sentry/components/events/interfaces/spans/types'; import type {SymbolicatorStatus} from 'sentry/components/events/interfaces/types'; import type {PlatformKey} from 'sentry/data/platformCategories'; import type {RawCrumb} from './breadcrumbs'; import type {Image} from './debugImage'; import type {IssueAttachment, IssueCategory} from './group'; import type {Release} from './release'; import type {RawStacktrace, StackTraceMechanism, StacktraceType} from './stacktrace'; // TODO(epurkhiser): objc and cocoa should almost definitely be moved into PlatformKey export type PlatformType = PlatformKey | 'objc' | 'cocoa'; export type Level = 'error' | 'fatal' | 'info' | 'warning' | 'sample' | 'unknown'; /** * Grouping Configuration. */ export type EventGroupComponent = { contributes: boolean; hint: string | null; id: string; name: string | null; values: EventGroupComponent[] | string[]; }; export type EventGroupingConfig = { base: string | null; changelog: string; delegates: string[]; hidden: boolean; id: string; latest: boolean; risk: number; strategies: string[]; }; export type VariantEvidence = { desc: string; fingerprint: string; cause_span_hashes?: string[]; offender_span_hashes?: string[]; op?: string; parent_span_hashes?: string[]; }; type EventGroupVariantKey = 'custom-fingerprint' | 'app' | 'default' | 'system'; export enum EventGroupVariantType { CHECKSUM = 'checksum', FALLBACK = 'fallback', CUSTOM_FINGERPRINT = 'custom-fingerprint', COMPONENT = 'component', SALTED_COMPONENT = 'salted-component', PERFORMANCE_PROBLEM = 'performance-problem', } interface BaseVariant { description: string | null; hash: string | null; hashMismatch: boolean; key: string; type: string; } interface FallbackVariant extends BaseVariant { type: EventGroupVariantType.FALLBACK; } interface ChecksumVariant extends BaseVariant { type: EventGroupVariantType.CHECKSUM; } interface HasComponentGrouping { client_values?: Array<string>; component?: EventGroupComponent; config?: EventGroupingConfig; matched_rule?: string; values?: Array<string>; } interface ComponentVariant extends BaseVariant, HasComponentGrouping { type: EventGroupVariantType.COMPONENT; } interface CustomFingerprintVariant extends BaseVariant, HasComponentGrouping { type: EventGroupVariantType.CUSTOM_FINGERPRINT; } interface SaltedComponentVariant extends BaseVariant, HasComponentGrouping { type: EventGroupVariantType.SALTED_COMPONENT; } interface PerformanceProblemVariant extends BaseVariant { evidence: VariantEvidence; type: EventGroupVariantType.PERFORMANCE_PROBLEM; } export type EventGroupVariant = | FallbackVariant | ChecksumVariant | ComponentVariant | SaltedComponentVariant | CustomFingerprintVariant | PerformanceProblemVariant; export type EventGroupInfo = Record<EventGroupVariantKey, EventGroupVariant>; /** * SDK Update metadata */ type EnableIntegrationSuggestion = { enables: Array<SDKUpdatesSuggestion>; integrationName: string; type: 'enableIntegration'; integrationUrl?: string | null; }; export type UpdateSdkSuggestion = { enables: Array<SDKUpdatesSuggestion>; newSdkVersion: string; sdkName: string; type: 'updateSdk'; sdkUrl?: string | null; }; type ChangeSdkSuggestion = { enables: Array<SDKUpdatesSuggestion>; newSdkName: string; type: 'changeSdk'; sdkUrl?: string | null; }; export type SDKUpdatesSuggestion = | EnableIntegrationSuggestion | UpdateSdkSuggestion | ChangeSdkSuggestion; /** * Frames, Threads and Event interfaces. */ export interface Thread { crashed: boolean; current: boolean; id: number; rawStacktrace: RawStacktrace; stacktrace: StacktraceType | null; name?: string | null; } export type Frame = { absPath: string | null; colNo: number | null; context: Array<[number, string]>; errors: Array<any> | null; filename: string | null; function: string | null; inApp: boolean; instructionAddr: string | null; lineNo: number | null; module: string | null; package: string | null; platform: PlatformType | null; rawFunction: string | null; symbol: string | null; symbolAddr: string | null; trust: any | null; vars: Record<string, any> | null; addrMode?: string; isPrefix?: boolean; isSentinel?: boolean; map?: string | null; mapUrl?: string | null; minGroupingLevel?: number; origAbsPath?: string | null; symbolicatorStatus?: SymbolicatorStatus; }; export enum FrameBadge { SENTINEL = 'sentinel', PREFIX = 'prefix', GROUPING = 'grouping', } export type ExceptionValue = { mechanism: StackTraceMechanism | null; module: string | null; rawStacktrace: RawStacktrace; stacktrace: StacktraceType | null; threadId: number | null; type: string; value: string; frames?: Frame[] | null; }; export type ExceptionType = { excOmitted: any | null; hasSystemFrames: boolean; values?: Array<ExceptionValue>; }; export type TreeLabelPart = | string | { classbase?: string; datapath?: (string | number)[]; filebase?: string; function?: string; is_prefix?: boolean; // is_sentinel is no longer being used, // but we will still assess whether we will use this property in the near future. is_sentinel?: boolean; package?: string; type?: string; }; // This type is incomplete export type EventMetadata = { current_level?: number; current_tree_label?: TreeLabelPart[]; directive?: string; display_title_with_tree_label?: boolean; filename?: string; finest_tree_label?: TreeLabelPart[]; function?: string; message?: string; origin?: string; stripped_crash?: boolean; title?: string; type?: string; uri?: string; value?: string; }; export enum EventOrGroupType { ERROR = 'error', CSP = 'csp', HPKP = 'hpkp', EXPECTCT = 'expectct', EXPECTSTAPLE = 'expectstaple', DEFAULT = 'default', TRANSACTION = 'transaction', } /** * Event interface types. */ export enum EntryType { EXCEPTION = 'exception', MESSAGE = 'message', REQUEST = 'request', STACKTRACE = 'stacktrace', TEMPLATE = 'template', CSP = 'csp', EXPECTCT = 'expectct', EXPECTSTAPLE = 'expectstaple', HPKP = 'hpkp', BREADCRUMBS = 'breadcrumbs', THREADS = 'threads', DEBUGMETA = 'debugmeta', SPANS = 'spans', RESOURCES = 'resources', } type EntryDebugMeta = { data: { images: Array<Image | null>; }; type: EntryType.DEBUGMETA; }; type EntryBreadcrumbs = { data: { values: Array<RawCrumb>; }; type: EntryType.BREADCRUMBS; }; export type EntryThreads = { data: { values?: Array<Thread>; }; type: EntryType.THREADS; }; export type EntryException = { data: ExceptionType; type: EntryType.EXCEPTION; }; type EntryStacktrace = { data: StacktraceType; type: EntryType.STACKTRACE; }; type EntrySpans = { data: any; type: EntryType.SPANS; }; type EntryMessage = { data: { formatted: string; params?: Record<string, any> | any[]; }; type: EntryType.MESSAGE; }; export type EntryRequest = { data: { method: string; url: string; cookies?: [key: string, value: string][]; data?: string | null | Record<string, any> | [key: string, value: any][]; env?: Record<string, string>; fragment?: string | null; headers?: [key: string, value: string][]; inferredContentType?: | null | 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data'; query?: [key: string, value: string][] | string; }; type: EntryType.REQUEST; }; type EntryTemplate = { data: Frame; type: EntryType.TEMPLATE; }; type EntryCsp = { data: Record<string, any>; type: EntryType.CSP; }; type EntryGeneric = { data: Record<string, any>; type: EntryType.EXPECTCT | EntryType.EXPECTSTAPLE | EntryType.HPKP; }; type EntryResources = { data: any; // Data is unused here type: EntryType.RESOURCES; }; export type Entry = | EntryDebugMeta | EntryBreadcrumbs | EntryThreads | EntryException | EntryStacktrace | EntrySpans | EntryMessage | EntryRequest | EntryTemplate | EntryCsp | EntryGeneric | EntryResources; // Contexts: https://develop.sentry.dev/sdk/event-payloads/contexts/ export interface BaseContext { type: string; } export enum DeviceContextKey { ARCH = 'arch', BATTERY_LEVEL = 'battery_level', BATTERY_STATUS = 'battery_status', BOOT_TIME = 'boot_time', BRAND = 'brand', CHARGING = 'charging', CPU_DESCRIPTION = 'cpu_description', DEVICE_TYPE = 'device_type', DEVICE_UNIQUE_IDENTIFIER = 'device_unique_identifier', EXTERNAL_FREE_STORAGE = 'external_free_storage', EXTERNAL_STORAGE_SIZE = 'external_storage_size', EXTERNAL_TOTAL_STORAGE = 'external_total_storage', FAMILY = 'family', FREE_MEMORY = 'free_memory', FREE_STORAGE = 'free_storage', LOW_MEMORY = 'low_memory', MANUFACTURER = 'manufacturer', MEMORY_SIZE = 'memory_size', MODEL = 'model', MODEL_ID = 'model_id', NAME = 'name', ONLINE = 'online', ORIENTATION = 'orientation', PROCESSOR_COUNT = 'processor_count', PROCESSOR_FREQUENCY = 'processor_frequency', SCREEN_DENSITY = 'screen_density', SCREEN_DPI = 'screen_dpi', SCREEN_HEIGHT_PIXELS = 'screen_height_pixels', SCREEN_RESOLUTION = 'screen_resolution', SCREEN_WIDTH_PIXELS = 'screen_width_pixels', SIMULATOR = 'simulator', STORAGE_SIZE = 'storage_size', SUPPORTS_ACCELEROMETER = 'supports_accelerometer', SUPPORTS_AUDIO = 'supports_audio', SUPPORTS_GYROSCOPE = 'supports_gyroscope', SUPPORTS_LOCATION_SERVICE = 'supports_location_service', SUPPORTS_VIBRATION = 'supports_vibration', USABLE_MEMORY = 'usable_memory', } // https://develop.sentry.dev/sdk/event-payloads/contexts/#device-context export interface DeviceContext extends Partial<Record<DeviceContextKey, unknown>>, BaseContext { type: 'device'; [DeviceContextKey.NAME]: string; [DeviceContextKey.ARCH]?: string; [DeviceContextKey.BATTERY_LEVEL]?: number; [DeviceContextKey.BATTERY_STATUS]?: string; [DeviceContextKey.BOOT_TIME]?: string; [DeviceContextKey.BRAND]?: string; [DeviceContextKey.CHARGING]?: boolean; [DeviceContextKey.CPU_DESCRIPTION]?: string; [DeviceContextKey.DEVICE_TYPE]?: string; [DeviceContextKey.DEVICE_UNIQUE_IDENTIFIER]?: string; [DeviceContextKey.EXTERNAL_FREE_STORAGE]?: number; [DeviceContextKey.EXTERNAL_STORAGE_SIZE]?: number; [DeviceContextKey.EXTERNAL_TOTAL_STORAGE]?: number; [DeviceContextKey.FAMILY]?: string; [DeviceContextKey.FREE_MEMORY]?: number; [DeviceContextKey.FREE_STORAGE]?: number; [DeviceContextKey.LOW_MEMORY]?: boolean; [DeviceContextKey.MANUFACTURER]?: string; [DeviceContextKey.MEMORY_SIZE]?: number; [DeviceContextKey.MODEL]?: string; [DeviceContextKey.MODEL_ID]?: string; [DeviceContextKey.ONLINE]?: boolean; [DeviceContextKey.ORIENTATION]?: 'portrait' | 'landscape'; [DeviceContextKey.PROCESSOR_COUNT]?: number; [DeviceContextKey.PROCESSOR_FREQUENCY]?: number; [DeviceContextKey.SCREEN_DENSITY]?: number; [DeviceContextKey.SCREEN_DPI]?: number; [DeviceContextKey.SCREEN_HEIGHT_PIXELS]?: number; [DeviceContextKey.SCREEN_RESOLUTION]?: string; [DeviceContextKey.SCREEN_WIDTH_PIXELS]?: number; [DeviceContextKey.SIMULATOR]?: boolean; [DeviceContextKey.STORAGE_SIZE]?: number; [DeviceContextKey.SUPPORTS_ACCELEROMETER]?: boolean; [DeviceContextKey.SUPPORTS_AUDIO]?: boolean; [DeviceContextKey.SUPPORTS_GYROSCOPE]?: boolean; [DeviceContextKey.SUPPORTS_LOCATION_SERVICE]?: boolean; [DeviceContextKey.SUPPORTS_VIBRATION]?: boolean; [DeviceContextKey.USABLE_MEMORY]?: number; // This field is deprecated in favour of locale field in culture context language?: string; // This field is deprecated in favour of timezone field in culture context timezone?: string; } enum RuntimeContextKey { BUILD = 'build', NAME = 'name', RAW_DESCRIPTION = 'raw_description', VERSION = 'version', } // https://develop.sentry.dev/sdk/event-payloads/contexts/#runtime-context interface RuntimeContext extends Partial<Record<RuntimeContextKey, unknown>>, BaseContext { type: 'runtime'; [RuntimeContextKey.BUILD]?: string; [RuntimeContextKey.NAME]?: string; [RuntimeContextKey.RAW_DESCRIPTION]?: string; [RuntimeContextKey.VERSION]?: number; } type OSContext = { build: string; kernel_version: string; name: string; type: string; version: string; }; export enum OtelContextKey { ATTRIBUTES = 'attributes', RESOURCE = 'resource', } // OpenTelemetry Context // https://develop.sentry.dev/sdk/performance/opentelemetry/#opentelemetry-context interface OtelContext extends Partial<Record<OtelContextKey, unknown>>, BaseContext { type: 'otel'; [OtelContextKey.ATTRIBUTES]?: Record<string, unknown>; [OtelContextKey.RESOURCE]?: Record<string, unknown>; } type EventContexts = { client_os?: OSContext; device?: DeviceContext; feedback?: Record<string, any>; os?: OSContext; otel?: OtelContext; // TODO (udameli): add better types here // once perf issue data shape is more clear performance_issue?: any; runtime?: RuntimeContext; trace?: TraceContextType; }; export type Measurement = {value: number; unit?: string}; export type EventTag = {key: string; value: string}; export type EventUser = { data?: string | null; email?: string; id?: string; ip_address?: string; name?: string | null; username?: string | null; }; export type PerformanceDetectorData = { causeSpanIds: string[]; offenderSpanIds: string[]; parentSpanIds: string[]; }; interface EventBase { contexts: EventContexts; crashFile: IssueAttachment | null; culprit: string; dateReceived: string; dist: string | null; entries: Entry[]; errors: any[]; eventID: string; fingerprints: string[]; id: string; location: string | null; message: string; metadata: EventMetadata; projectID: string; size: number; tags: EventTag[]; title: string; type: | EventOrGroupType.CSP | EventOrGroupType.DEFAULT | EventOrGroupType.EXPECTCT | EventOrGroupType.EXPECTSTAPLE | EventOrGroupType.HPKP; user: EventUser | null; _meta?: Record<string, any>; context?: Record<string, any>; dateCreated?: string; device?: Record<string, any>; endTimestamp?: number; groupID?: string; groupingConfig?: { enhancements: string; id: string; }; issueCategory?: IssueCategory; latestEventID?: string | null; measurements?: Record<string, Measurement>; nextEventID?: string | null; oldestEventID?: string | null; packages?: Record<string, string>; platform?: PlatformType; previousEventID?: string | null; projectSlug?: string; release?: Release | null; sdk?: { name: string; version: string; } | null; sdkUpdates?: Array<SDKUpdatesSuggestion>; userReport?: any; } interface TraceEventContexts extends EventContexts { trace?: TraceContextType; } export interface EventTransaction extends Omit<EventBase, 'entries' | 'type' | 'contexts'> { contexts: TraceEventContexts; endTimestamp: number; entries: (EntrySpans | EntryRequest)[]; startTimestamp: number; type: EventOrGroupType.TRANSACTION; perfProblem?: PerformanceDetectorData; } export interface EventError extends Omit<EventBase, 'entries' | 'type'> { entries: ( | EntryException | EntryStacktrace | EntryRequest | EntryThreads | EntryDebugMeta )[]; type: EventOrGroupType.ERROR; } export type Event = EventError | EventTransaction | EventBase; // Response from EventIdLookupEndpoint // /organizations/${orgSlug}/eventids/${eventId}/ export type EventIdResponse = { event: Event; eventId: string; groupId: string; organizationSlug: string; projectSlug: string; };