Files
2024-02-15 17:01:50 +00:00

1596 lines
46 KiB
TypeScript

import {t} from 'sentry/locale';
import type {TagCollection} from 'sentry/types';
// Don't forget to update https://docs.sentry.io/product/sentry-basics/search/searchable-properties/ for any changes made here
export enum FieldKind {
TAG = 'tag',
MEASUREMENT = 'measurement',
BREAKDOWN = 'breakdown',
FIELD = 'field',
FUNCTION = 'function',
EQUATION = 'equation',
METRICS = 'metric',
NUMERIC_METRICS = 'numeric_metric',
}
export enum FieldKey {
AGE = 'age',
ASSIGNED = 'assigned',
ASSIGNED_OR_SUGGESTED = 'assigned_or_suggested',
BOOKMARKS = 'bookmarks',
BROWSER_NAME = 'browser.name',
CULPRIT = 'culprit',
DEVICE_ARCH = 'device.arch',
DEVICE_BATTERY_LEVEL = 'device.battery_level',
DEVICE_BRAND = 'device.brand',
DEVICE_CHARGING = 'device.charging',
// device.class is a synthesized field calculated based off device info found in context such
// as model (for iOS devices), and device specs like processor_frequency (for Android devices).
// https://github.com/getsentry/relay/blob/master/relay-general/src/protocol/device_class.rs
DEVICE_CLASS = 'device.class',
DEVICE_FAMILY = 'device.family',
DEVICE_LOCALE = 'device.locale',
DEVICE_MODEL_ID = 'device.model_id',
DEVICE_NAME = 'device.name',
DEVICE_ONLINE = 'device.online',
DEVICE_ORIENTATION = 'device.orientation',
DEVICE_SCREEN_DENSITY = 'device.screen_density',
DEVICE_SCREEN_DPI = 'device.screen_dpi',
DEVICE_SCREEN_HEIGHT_PIXELS = 'device.screen_height_pixels',
DEVICE_SCREEN_WIDTH_PIXELS = 'device.screen_width_pixels',
DEVICE_SIMULATOR = 'device.simulator',
DEVICE_UUID = 'device.uuid',
DIST = 'dist',
ENVIRONMENT = 'environment',
ERROR_HANDLED = 'error.handled',
ERROR_MECHANISM = 'error.mechanism',
ERROR_TYPE = 'error.type',
ERROR_UNHANDLED = 'error.unhandled',
ERROR_VALUE = 'error.value',
ERROR_RECEIVED = 'error.received',
ERROR_MAIN_THREAD = 'error.main_thread',
EVENT_TIMESTAMP = 'event.timestamp',
EVENT_TYPE = 'event.type',
FIRST_RELEASE = 'firstRelease',
FIRST_SEEN = 'firstSeen',
GEO_CITY = 'geo.city',
GEO_COUNTRY_CODE = 'geo.country_code',
GEO_REGION = 'geo.region',
GEO_SUBDIVISION = 'geo.subdivision',
HAS = 'has',
HTTP_METHOD = 'http.method',
HTTP_REFERER = 'http.referer',
HTTP_STATUS_CODE = 'http.status_code',
HTTP_URL = 'http.url',
ID = 'id',
IS = 'is',
ISSUE = 'issue',
ISSUE_CATEGORY = 'issue.category',
ISSUE_TYPE = 'issue.type',
LAST_SEEN = 'lastSeen',
LEVEL = 'level',
LOCATION = 'location',
MESSAGE = 'message',
OS = 'os',
OS_BUILD = 'os.build',
OS_KERNEL_VERSION = 'os.kernel_version',
OS_NAME = 'os.name',
PLATFORM = 'platform',
PLATFORM_NAME = 'platform.name',
PROFILE_ID = 'profile.id',
PROJECT = 'project',
RELEASE = 'release',
RELEASE_BUILD = 'release.build',
RELEASE_PACKAGE = 'release.package',
RELEASE_STAGE = 'release.stage',
RELEASE_VERSION = 'release.version',
REPLAY_ID = 'replayId',
SDK_NAME = 'sdk.name',
SDK_VERSION = 'sdk.version',
STACK_ABS_PATH = 'stack.abs_path',
STACK_COLNO = 'stack.colno',
STACK_FILENAME = 'stack.filename',
STACK_FUNCTION = 'stack.function',
STACK_IN_APP = 'stack.in_app',
STACK_LINENO = 'stack.lineno',
STACK_MODULE = 'stack.module',
STACK_PACKAGE = 'stack.package',
STACK_RESOURCE = 'stack.resource',
STACK_STACK_LEVEL = 'stack.stack_level',
TIMESTAMP = 'timestamp',
TIMESTAMP_TO_DAY = 'timestamp.to_day',
TIMESTAMP_TO_HOUR = 'timestamp.to_hour',
TIMES_SEEN = 'timesSeen',
TITLE = 'title',
TOTAL_COUNT = 'total.count',
TRACE = 'trace',
TRACE_PARENT_SPAN = 'trace.parent_span',
TRACE_SPAN = 'trace.span',
TRANSACTION = 'transaction',
TRANSACTION_DURATION = 'transaction.duration',
TRANSACTION_OP = 'transaction.op',
TRANSACTION_STATUS = 'transaction.status',
UNREAL_CRASH_TYPE = 'unreal.crash_type',
USER = 'user',
USER_DISPLAY = 'user.display',
USER_EMAIL = 'user.email',
USER_ID = 'user.id',
USER_IP = 'user.ip',
USER_USERNAME = 'user.username',
USER_SEGMENT = 'user.segment',
APP_IN_FOREGROUND = 'app.in_foreground',
FUNCTION_DURATION = 'function.duration',
}
export enum FieldValueType {
BOOLEAN = 'boolean',
DATE = 'date',
DURATION = 'duration',
INTEGER = 'integer',
NUMBER = 'number',
PERCENTAGE = 'percentage',
STRING = 'string',
NEVER = 'never',
SIZE = 'size',
RATE = 'rate',
PERCENT_CHANGE = 'percent_change',
}
export enum WebVital {
FP = 'measurements.fp',
FCP = 'measurements.fcp',
LCP = 'measurements.lcp',
FID = 'measurements.fid',
CLS = 'measurements.cls',
TTFB = 'measurements.ttfb',
INP = 'measurements.inp',
REQUEST_TIME = 'measurements.ttfb.requesttime',
}
export enum MobileVital {
APP_START_COLD = 'measurements.app_start_cold',
APP_START_WARM = 'measurements.app_start_warm',
FRAMES_TOTAL = 'measurements.frames_total',
FRAMES_SLOW = 'measurements.frames_slow',
FRAMES_FROZEN = 'measurements.frames_frozen',
FRAMES_SLOW_RATE = 'measurements.frames_slow_rate',
FRAMES_FROZEN_RATE = 'measurements.frames_frozen_rate',
STALL_COUNT = 'measurements.stall_count',
STALL_TOTAL_TIME = 'measurements.stall_total_time',
STALL_LONGEST_TIME = 'measurements.stall_longest_time',
STALL_PERCENTAGE = 'measurements.stall_percentage',
TIME_TO_FULL_DISPLAY = 'measurements.time_to_full_display',
TIME_TO_INITIAL_DISPLAY = 'measurements.time_to_initial_display',
}
export enum StackTags {
STACK_ABS_PATH = 'stack.abs_path',
STACK_COLNO = 'stack.colno',
STACK_FILENAME = 'stack.filename',
STACK_FUNCTION = 'stack.function',
STACK_IN_APP = 'stack.in_app',
STACK_LINENO = 'stack.lineno',
STACK_MODULE = 'stack.module',
STACK_PACKAGE = 'stack.package',
STACK_RESOURCE = 'stack.resource',
STACK_STACK_LEVEL = 'stack.stack_level',
}
export enum ErrorTags {
ERROR_HANDLED = 'error.handled',
ERROR_MECHANISM = 'error.mechanism',
ERROR_TYPE = 'error.type',
ERROR_UNHANDLED = 'error.unhandled',
ERROR_VALUE = 'error.value',
ERROR_RECEIVED = 'error.received',
ERROR_MAIN_THREAD = 'error.main_thread',
}
export enum SpanOpBreakdown {
SPANS_BROWSER = 'spans.browser',
SPANS_DB = 'spans.db',
SPANS_HTTP = 'spans.http',
SPANS_RESOURCE = 'spans.resource',
SPANS_UI = 'spans.ui',
}
export enum AggregationKey {
COUNT = 'count',
COUNT_UNIQUE = 'count_unique',
COUNT_MISERABLE = 'count_miserable',
COUNT_IF = 'count_if',
COUNT_WEB_VITALS = 'count_web_vitals',
EPS = 'eps',
EPM = 'epm',
FAILURE_COUNT = 'failure_count',
MIN = 'min',
MAX = 'max',
SUM = 'sum',
ANY = 'any',
P50 = 'p50',
P75 = 'p75',
P90 = 'p90',
P95 = 'p95',
P99 = 'p99',
P100 = 'p100',
PERCENTILE = 'percentile',
AVG = 'avg',
APDEX = 'apdex',
USER_MISERY = 'user_misery',
FAILURE_RATE = 'failure_rate',
LAST_SEEN = 'last_seen',
}
export interface FieldDefinition {
kind: FieldKind;
valueType: FieldValueType | null;
/**
* Is this field being deprecated
*/
deprecated?: boolean;
/**
* Description of the field
*/
desc?: string;
/**
* Feature flag that indicates gating of the field from use
*/
featureFlag?: string;
/**
* Additional keywords used when filtering via autocomplete
*/
keywords?: string[];
}
export const AGGREGATION_FIELDS: Record<AggregationKey, FieldDefinition> = {
[AggregationKey.COUNT]: {
desc: t('count of events'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.COUNT_UNIQUE]: {
desc: t('Unique count of the field values'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.INTEGER,
},
[AggregationKey.COUNT_MISERABLE]: {
desc: t('Count of unique miserable users'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.COUNT_IF]: {
desc: t('Count of events matching the parameter conditions'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.COUNT_WEB_VITALS]: {
desc: t('Count of web vitals with a specific status'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.EPS]: {
desc: t('Events per second'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.EPM]: {
desc: t('Events per minute'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.FAILURE_RATE]: {
desc: t('Failed event percentage based on transaction.status'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.PERCENTAGE,
},
[AggregationKey.FAILURE_COUNT]: {
desc: t('Failed event count based on transaction.status'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.MIN]: {
desc: t('Returns the minimum value of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.MAX]: {
desc: t('Returns maximum value of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.SUM]: {
desc: t('Returns the total value for the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.ANY]: {
desc: t('Not Recommended, a random field value'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.P50]: {
desc: t('Returns the 50th percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.P75]: {
desc: t('Returns the 75th percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.P90]: {
desc: t('Returns the 90th percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.P95]: {
desc: t('Returns the 95th percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.P99]: {
desc: t('Returns the 99th percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.P100]: {
desc: t('Returns the 100th percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.PERCENTILE]: {
desc: t('Returns the percentile of the selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.AVG]: {
desc: t('Returns averages for a selected field'),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.APDEX]: {
desc: t('Performance score based on a duration threshold'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.NUMBER,
},
[AggregationKey.USER_MISERY]: {
desc: t(
'User-weighted performance metric that counts the number of unique users who were frustrated'
),
kind: FieldKind.FUNCTION,
valueType: null,
},
[AggregationKey.LAST_SEEN]: {
desc: t('Issues last seen at a date and time'),
kind: FieldKind.FUNCTION,
valueType: FieldValueType.DATE,
},
};
export const MEASUREMENT_FIELDS: Record<WebVital | MobileVital, FieldDefinition> = {
[WebVital.FP]: {
desc: t('Web Vital First Paint'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[WebVital.FCP]: {
desc: t('Web Vital First Contentful Paint'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[WebVital.LCP]: {
desc: t('Web Vital Largest Contentful Paint'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[WebVital.FID]: {
desc: t('Web Vital First Input Delay'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[WebVital.CLS]: {
desc: t('Web Vital Cumulative Layout Shift'),
kind: FieldKind.METRICS,
valueType: FieldValueType.NUMBER,
},
[WebVital.TTFB]: {
desc: t('Web Vital Time To First Byte'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[WebVital.REQUEST_TIME]: {
desc: t('Time between start of request to start of response'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[MobileVital.APP_START_COLD]: {
desc: t('First launch (not in memory and no process exists)'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[MobileVital.APP_START_WARM]: {
desc: t('Already launched (partial memory and process may exist)'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[MobileVital.FRAMES_TOTAL]: {
desc: t('Total number of frames'),
kind: FieldKind.METRICS,
valueType: FieldValueType.INTEGER,
},
[MobileVital.FRAMES_SLOW]: {
desc: t('Number of slow frames'),
kind: FieldKind.METRICS,
valueType: FieldValueType.INTEGER,
},
[MobileVital.FRAMES_FROZEN]: {
desc: t('Number of frozen frames'),
kind: FieldKind.METRICS,
valueType: FieldValueType.INTEGER,
},
[MobileVital.FRAMES_SLOW_RATE]: {
desc: t('Number of slow frames out of the total'),
kind: FieldKind.METRICS,
valueType: FieldValueType.PERCENTAGE,
},
[MobileVital.FRAMES_FROZEN_RATE]: {
desc: t('Number of frozen frames out of the total'),
kind: FieldKind.METRICS,
valueType: FieldValueType.PERCENTAGE,
},
[MobileVital.STALL_COUNT]: {
desc: t('Count of slow Javascript event loops (React Native)'),
kind: FieldKind.METRICS,
valueType: FieldValueType.INTEGER,
},
[MobileVital.STALL_TOTAL_TIME]: {
desc: t('Total stall duration (React Native)'),
kind: FieldKind.METRICS,
valueType: FieldValueType.PERCENTAGE,
},
[MobileVital.STALL_LONGEST_TIME]: {
desc: t('Duration of slowest Javascript event loop (React Native)'),
kind: FieldKind.METRICS,
valueType: FieldValueType.INTEGER,
},
[MobileVital.STALL_PERCENTAGE]: {
desc: t('Total stall duration out of the total transaction duration (React Native)'),
kind: FieldKind.METRICS,
valueType: FieldValueType.PERCENTAGE,
},
[MobileVital.TIME_TO_FULL_DISPLAY]: {
desc: t(
'The time between application launch and complete display of all resources and views'
),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[MobileVital.TIME_TO_INITIAL_DISPLAY]: {
desc: t('The time it takes for an application to produce its first frame'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[WebVital.INP]: {
desc: t('Web Vital Interaction to Next Paint'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
};
export const SPAN_OP_FIELDS: Record<SpanOpBreakdown, FieldDefinition> = {
[SpanOpBreakdown.SPANS_BROWSER]: {
desc: t('Cumulative time based on the browser operation'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[SpanOpBreakdown.SPANS_DB]: {
desc: t('Cumulative time based on the database operation'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[SpanOpBreakdown.SPANS_HTTP]: {
desc: t('Cumulative time based on the http operation'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[SpanOpBreakdown.SPANS_RESOURCE]: {
desc: t('Cumulative time based on the resource operation'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
[SpanOpBreakdown.SPANS_UI]: {
desc: t('Cumulative time based on the ui operation'),
kind: FieldKind.METRICS,
valueType: FieldValueType.DURATION,
},
};
type AllEventFieldKeys =
| keyof typeof AGGREGATION_FIELDS
| keyof typeof MEASUREMENT_FIELDS
| keyof typeof SPAN_OP_FIELDS
| FieldKey;
const EVENT_FIELD_DEFINITIONS: Record<AllEventFieldKeys, FieldDefinition> = {
...AGGREGATION_FIELDS,
...MEASUREMENT_FIELDS,
...SPAN_OP_FIELDS,
[FieldKey.AGE]: {
desc: t('The age of the issue in relative time'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DURATION,
},
[FieldKey.ASSIGNED]: {
desc: t('Assignee of the issue as a user ID'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ASSIGNED_OR_SUGGESTED]: {
desc: t('Assignee or suggestee of the issue as a user ID'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.CULPRIT]: {
deprecated: true,
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.BOOKMARKS]: {
desc: t('The issues bookmarked by a user ID'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.BROWSER_NAME]: {
desc: t('Name of the browser'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_ARCH]: {
desc: t('CPU architecture'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_BATTERY_LEVEL]: {
desc: t('Indicates remaining battery life'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_BRAND]: {
desc: t('Brand of device'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_CHARGING]: {
desc: t('Charging at the time of the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.DEVICE_CLASS]: {
desc: t('The estimated performance level of the device, graded low, medium, or high'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_FAMILY]: {
desc: t('Model name across generations'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_LOCALE]: {
desc: t("The locale of the user's device"),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_MODEL_ID]: {
desc: t('Internal hardware revision'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_NAME]: {
desc: t('Descriptor details'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_ONLINE]: {
desc: t('Online at the time of the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.DEVICE_ORIENTATION]: {
desc: t('Portrait or landscape view '),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_SCREEN_DENSITY]: {
desc: t('Pixel density of the device screen'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_SCREEN_DPI]: {
desc: t('Dots per inch of the device screen'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_SCREEN_HEIGHT_PIXELS]: {
desc: t('Height of the device screen in pixels'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_SCREEN_WIDTH_PIXELS]: {
desc: t('Width of the device screen in pixels'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DEVICE_SIMULATOR]: {
desc: t('Indicates if it occured on a simulator'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.DEVICE_UUID]: {
desc: t('Unique device identifier'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.DIST]: {
desc: t(
'Distinguishes between build or deployment variants of the same release of an application.'
),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ENVIRONMENT]: {
desc: t('The environment the event was seen in'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ERROR_HANDLED]: {
desc: t('Determines handling status of the error'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.ERROR_MECHANISM]: {
desc: t('The mechanism that created the error'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ERROR_TYPE]: {
desc: t('The type of exception'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ERROR_UNHANDLED]: {
desc: t('Determines unhandling status of the error'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.ERROR_VALUE]: {
desc: t('Original value that exhibits error'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ERROR_RECEIVED]: {
desc: t('The datetime that the error was received'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.ERROR_MAIN_THREAD]: {
desc: t('Indicates if the error occurred on the main thread'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.EVENT_TIMESTAMP]: {
desc: t('Date and time of the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.EVENT_TYPE]: {
desc: t('Type of event (Errors, transactions, csp and default)'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.GEO_CITY]: {
desc: t('Full name of the city'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.GEO_COUNTRY_CODE]: {
desc: t('Country code based on ISO 3166-1'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.GEO_REGION]: {
desc: t('Full name of the country'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.GEO_SUBDIVISION]: {
desc: t('Full name of the subdivision'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.HTTP_METHOD]: {
desc: t('Method of the request that created the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.HTTP_REFERER]: {
desc: t('The web page the resource was requested from'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.HTTP_STATUS_CODE]: {
desc: t('Type of response (i.e., 200, 404)'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.HTTP_URL]: {
desc: t('Full URL of the request without parameters'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ID]: {
desc: t('The event identification number'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.IS]: {
desc: t('The properties of an issue (i.e. Resolved, unresolved)'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
keywords: ['ignored', 'assigned', 'for_review', 'unassigned', 'linked', 'unlinked'],
},
[FieldKey.ISSUE]: {
desc: t('The issue identification short code'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.ISSUE_CATEGORY]: {
desc: t('Category of issue (error or performance)'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
keywords: ['error', 'performance'],
},
[FieldKey.ISSUE_TYPE]: {
desc: t('Type of problem the issue represents (i.e. N+1 Query)'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.LAST_SEEN]: {
desc: t('Issues last seen at a given time'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.LEVEL]: {
kind: FieldKind.FIELD,
desc: t('Severity of the event (i.e., fatal, error, warning)'),
valueType: FieldValueType.STRING,
},
[FieldKey.LOCATION]: {
desc: t('Location of error'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.MESSAGE]: {
desc: t('Error message or transaction name'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.OS]: {
desc: t('Build and kernel version'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.OS_BUILD]: {
desc: t('Name of the build'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.OS_KERNEL_VERSION]: {
desc: t('Version number'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.PLATFORM]: {
desc: t('Name of the platform'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.PLATFORM_NAME]: {
desc: t('Name of the platform'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.PROFILE_ID]: {
desc: t('The ID of an associated profile'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.PROJECT]: {
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.FIRST_RELEASE]: {
desc: t('Issues first seen in a given release'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.FIRST_SEEN]: {
desc: t('Issues first seen at a given time'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.HAS]: {
desc: t('Determines if a tag or field exists in an event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.OS_NAME]: {
desc: t('Name of the Operating System'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.RELEASE]: {
desc: t('The version of your code deployed to an environment'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.RELEASE_BUILD]: {
desc: t('The full version number that identifies the iteration'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.RELEASE_PACKAGE]: {
desc: t('The identifier unique to the project or application'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.RELEASE_STAGE]: {
desc: t('Stage of usage (i.e., adopted, replaced, low)'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.RELEASE_VERSION]: {
desc: t('An abbreviated version number of the build'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.REPLAY_ID]: {
desc: t('The ID of an associated Session Replay'),
kind: FieldKind.TAG,
valueType: FieldValueType.STRING,
},
[FieldKey.SDK_NAME]: {
desc: t('Name of the platform that sent the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.SDK_VERSION]: {
desc: t('Version of the platform that sent the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_ABS_PATH]: {
desc: t('Absolute path to the source file'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_COLNO]: {
desc: t('Column number of the call starting at 1'),
kind: FieldKind.FIELD,
valueType: FieldValueType.NUMBER,
},
[FieldKey.STACK_FILENAME]: {
desc: t('Relative path to the source file from the root directory'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_FUNCTION]: {
desc: t('Name of function being called'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_IN_APP]: {
desc: t('Indicates if frame is related to relevant code in stack trace'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.STACK_LINENO]: {
desc: t('Line number of the call starting at 1'),
kind: FieldKind.FIELD,
valueType: FieldValueType.NUMBER,
},
[FieldKey.STACK_MODULE]: {
desc: t('Platform specific module path'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_PACKAGE]: {
desc: t('The package the frame is from'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_RESOURCE]: {
desc: t('The package the frame is from'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.STACK_STACK_LEVEL]: {
desc: t('Number of frames per stacktrace'),
kind: FieldKind.FIELD,
valueType: FieldValueType.NUMBER,
},
[FieldKey.TIMES_SEEN]: {
desc: t('Total number of events'),
kind: FieldKind.FIELD,
valueType: FieldValueType.NUMBER,
keywords: ['count'],
},
[FieldKey.TIMESTAMP]: {
desc: t('The time an event finishes'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.TIMESTAMP_TO_HOUR]: {
desc: t('Rounded down to the nearest hour'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.TIMESTAMP_TO_DAY]: {
desc: t('Rounded down to the nearest day'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DATE,
},
[FieldKey.TITLE]: {
desc: t('Error or transaction name identifier'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.TRACE]: {
desc: t('The trace identification number'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.TOTAL_COUNT]: {
desc: t('The total number of events for the current query'),
kind: FieldKind.FIELD,
valueType: FieldValueType.NUMBER,
},
[FieldKey.TRACE_PARENT_SPAN]: {
desc: t('Span identification number of the parent to the event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.TRACE_SPAN]: {
desc: t('Span identification number of the root span'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.TRANSACTION]: {
desc: t('Error or transaction name identifier'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.TRANSACTION_OP]: {
desc: t('Short code identifying the type of operation the span is measuring'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.TRANSACTION_DURATION]: {
desc: t('Duration, in milliseconds, of the transaction'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DURATION,
},
[FieldKey.TRANSACTION_STATUS]: {
desc: t('Describes the status of the span/transaction'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.UNREAL_CRASH_TYPE]: {
desc: t('Crash type of an Unreal event'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER]: {
desc: t('User identification value'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER_DISPLAY]: {
desc: t('The first user field available of email, username, ID, and IP'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER_EMAIL]: {
desc: t('Email address of the user'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER_ID]: {
desc: t('Application specific internal identifier of the user'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER_IP]: {
desc: t('IP Address of the user'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER_USERNAME]: {
desc: t('Username of the user'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.USER_SEGMENT]: {
desc: t('Segment of the user'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FieldKey.APP_IN_FOREGROUND]: {
desc: t('Indicates if the app is in the foreground or background'),
kind: FieldKind.FIELD,
valueType: FieldValueType.BOOLEAN,
},
[FieldKey.FUNCTION_DURATION]: {
desc: t('Duration of the function'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DURATION,
},
};
export const ISSUE_FIELDS = [
FieldKey.AGE,
FieldKey.ASSIGNED,
FieldKey.ASSIGNED_OR_SUGGESTED,
FieldKey.BOOKMARKS,
FieldKey.DEVICE_ARCH,
FieldKey.DEVICE_BRAND,
FieldKey.DEVICE_CLASS,
FieldKey.DEVICE_FAMILY,
FieldKey.DEVICE_LOCALE,
FieldKey.DEVICE_LOCALE,
FieldKey.DEVICE_MODEL_ID,
FieldKey.DEVICE_ORIENTATION,
FieldKey.DEVICE_UUID,
FieldKey.DIST,
FieldKey.ERROR_HANDLED,
FieldKey.ERROR_MECHANISM,
FieldKey.ERROR_TYPE,
FieldKey.ERROR_UNHANDLED,
FieldKey.ERROR_VALUE,
FieldKey.ERROR_MAIN_THREAD,
FieldKey.EVENT_TIMESTAMP,
FieldKey.EVENT_TYPE,
FieldKey.FIRST_RELEASE,
FieldKey.FIRST_SEEN,
FieldKey.GEO_CITY,
FieldKey.GEO_COUNTRY_CODE,
FieldKey.GEO_REGION,
FieldKey.GEO_SUBDIVISION,
FieldKey.HAS,
FieldKey.HTTP_METHOD,
FieldKey.HTTP_REFERER,
FieldKey.HTTP_STATUS_CODE,
FieldKey.HTTP_URL,
FieldKey.ID,
FieldKey.IS,
FieldKey.ISSUE,
FieldKey.ISSUE_CATEGORY,
FieldKey.ISSUE_TYPE,
FieldKey.LAST_SEEN,
FieldKey.LOCATION,
FieldKey.MESSAGE,
FieldKey.OS_BUILD,
FieldKey.OS_KERNEL_VERSION,
FieldKey.PLATFORM,
FieldKey.RELEASE,
FieldKey.RELEASE_BUILD,
FieldKey.RELEASE_PACKAGE,
FieldKey.RELEASE_STAGE,
FieldKey.RELEASE_VERSION,
FieldKey.SDK_NAME,
FieldKey.SDK_VERSION,
FieldKey.STACK_ABS_PATH,
FieldKey.STACK_FILENAME,
FieldKey.STACK_FUNCTION,
FieldKey.STACK_MODULE,
FieldKey.STACK_PACKAGE,
FieldKey.STACK_STACK_LEVEL,
FieldKey.TIMESTAMP,
FieldKey.TIMES_SEEN,
FieldKey.TITLE,
FieldKey.TRACE,
FieldKey.TRANSACTION,
FieldKey.UNREAL_CRASH_TYPE,
FieldKey.USER_EMAIL,
FieldKey.USER_ID,
FieldKey.USER_IP,
FieldKey.USER_USERNAME,
FieldKey.APP_IN_FOREGROUND,
];
/**
* Refer to src/sentry/snuba/events.py, search for Columns
*/
export const DISCOVER_FIELDS = [
FieldKey.ID,
// issue.id and project.id are omitted on purpose.
// Customers should use `issue` and `project` instead.
FieldKey.TIMESTAMP,
// time is omitted on purpose.
// Customers should use `timestamp` or `timestamp.to_hour`.
FieldKey.TIMESTAMP_TO_HOUR,
FieldKey.TIMESTAMP_TO_DAY,
FieldKey.CULPRIT,
FieldKey.LOCATION,
FieldKey.MESSAGE,
FieldKey.PLATFORM_NAME,
FieldKey.ENVIRONMENT,
FieldKey.RELEASE,
FieldKey.DIST,
FieldKey.TITLE,
FieldKey.EVENT_TYPE,
// tags.key and tags.value are omitted on purpose as well.
FieldKey.TRANSACTION,
FieldKey.UNREAL_CRASH_TYPE,
FieldKey.USER,
FieldKey.USER_ID,
FieldKey.USER_EMAIL,
FieldKey.USER_USERNAME,
FieldKey.USER_IP,
FieldKey.SDK_NAME,
FieldKey.SDK_VERSION,
FieldKey.HTTP_METHOD,
FieldKey.HTTP_REFERER,
FieldKey.HTTP_STATUS_CODE,
FieldKey.HTTP_URL,
FieldKey.OS_BUILD,
FieldKey.OS_KERNEL_VERSION,
FieldKey.DEVICE_NAME,
FieldKey.DEVICE_BRAND,
FieldKey.DEVICE_LOCALE,
FieldKey.DEVICE_UUID,
FieldKey.DEVICE_ARCH,
FieldKey.DEVICE_FAMILY,
FieldKey.DEVICE_BATTERY_LEVEL,
FieldKey.DEVICE_ORIENTATION,
FieldKey.DEVICE_SCREEN_DENSITY,
FieldKey.DEVICE_SCREEN_DPI,
FieldKey.DEVICE_SCREEN_HEIGHT_PIXELS,
FieldKey.DEVICE_SCREEN_WIDTH_PIXELS,
FieldKey.DEVICE_SIMULATOR,
FieldKey.DEVICE_ONLINE,
FieldKey.DEVICE_CHARGING,
FieldKey.DEVICE_CLASS,
FieldKey.GEO_COUNTRY_CODE,
FieldKey.GEO_REGION,
FieldKey.GEO_CITY,
FieldKey.GEO_SUBDIVISION,
FieldKey.ERROR_TYPE,
FieldKey.ERROR_VALUE,
FieldKey.ERROR_MECHANISM,
FieldKey.ERROR_HANDLED,
FieldKey.ERROR_UNHANDLED,
FieldKey.ERROR_RECEIVED,
FieldKey.ERROR_MAIN_THREAD,
FieldKey.LEVEL,
FieldKey.STACK_ABS_PATH,
FieldKey.STACK_FILENAME,
FieldKey.STACK_PACKAGE,
FieldKey.STACK_MODULE,
FieldKey.STACK_FUNCTION,
FieldKey.STACK_IN_APP,
FieldKey.STACK_COLNO,
FieldKey.STACK_LINENO,
FieldKey.STACK_STACK_LEVEL,
// contexts.key and contexts.value omitted on purpose.
// App context fields
FieldKey.APP_IN_FOREGROUND,
// Transaction event fields.
FieldKey.TRANSACTION_DURATION,
FieldKey.TRANSACTION_OP,
FieldKey.TRANSACTION_STATUS,
FieldKey.TRACE,
FieldKey.TRACE_SPAN,
FieldKey.TRACE_PARENT_SPAN,
FieldKey.PROFILE_ID,
// Meta field that returns total count, usually for equations
FieldKey.TOTAL_COUNT,
// Field alises defined in src/sentry/api/event_search.py
FieldKey.PROJECT,
FieldKey.ISSUE,
FieldKey.USER_DISPLAY,
// Span Op fields
SpanOpBreakdown.SPANS_BROWSER,
SpanOpBreakdown.SPANS_DB,
SpanOpBreakdown.SPANS_HTTP,
SpanOpBreakdown.SPANS_RESOURCE,
SpanOpBreakdown.SPANS_UI,
];
export enum ReplayFieldKey {
ACTIVITY = 'activity',
BROWSER_NAME = 'browser.name',
BROWSER_VERSION = 'browser.version',
COUNT_DEAD_CLICKS = 'count_dead_clicks',
COUNT_RAGE_CLICKS = 'count_rage_clicks',
COUNT_ERRORS = 'count_errors',
COUNT_SEGMENTS = 'count_segments',
COUNT_URLS = 'count_urls',
DURATION = 'duration',
ERROR_IDS = 'error_ids',
OS_NAME = 'os.name',
OS_VERSION = 'os.version',
URLS = 'urls',
}
export enum ReplayClickFieldKey {
CLICK_ALT = 'click.alt',
CLICK_CLASS = 'click.class',
CLICK_ID = 'click.id',
CLICK_LABEL = 'click.label',
CLICK_ROLE = 'click.role',
CLICK_SELECTOR = 'click.selector',
DEAD_SELECTOR = 'dead.selector',
RAGE_SELECTOR = 'rage.selector',
CLICK_TAG = 'click.tag',
CLICK_TESTID = 'click.testid',
CLICK_TEXT_CONTENT = 'click.textContent',
CLICK_TITLE = 'click.title',
CLICK_COMPONENT_NAME = 'click.component_name',
}
/**
* Some fields inside the ReplayRecord type are intentionally omitted:
* `environment` -> Not backend support, omitted because we have a dropdown for it
* `finishedAt` -> No backend support, omitted because we StartDate dropdown and duration field support
* `startedAt` -> No backend support, Omitted because we have StartDate dropdown
* `longestTransaction` -> value is always zero
* `title` -> value is always the empty string
*/
export const REPLAY_FIELDS = [
ReplayFieldKey.ACTIVITY,
ReplayFieldKey.BROWSER_NAME,
ReplayFieldKey.BROWSER_VERSION,
ReplayFieldKey.COUNT_DEAD_CLICKS,
ReplayFieldKey.COUNT_RAGE_CLICKS,
ReplayFieldKey.COUNT_ERRORS,
ReplayFieldKey.COUNT_SEGMENTS,
ReplayFieldKey.COUNT_URLS,
FieldKey.DEVICE_BRAND,
FieldKey.DEVICE_FAMILY,
FieldKey.DEVICE_MODEL_ID,
FieldKey.DEVICE_NAME,
FieldKey.DIST,
ReplayFieldKey.DURATION,
ReplayFieldKey.ERROR_IDS,
FieldKey.ID,
ReplayFieldKey.OS_NAME,
ReplayFieldKey.OS_VERSION,
FieldKey.PLATFORM,
FieldKey.RELEASE,
FieldKey.SDK_NAME,
FieldKey.SDK_VERSION,
FieldKey.TRACE,
ReplayFieldKey.URLS,
FieldKey.USER_EMAIL,
FieldKey.USER_ID,
FieldKey.USER_IP,
FieldKey.USER_USERNAME,
];
const REPLAY_FIELD_DEFINITIONS: Record<ReplayFieldKey, FieldDefinition> = {
[ReplayFieldKey.ACTIVITY]: {
desc: t('Amount of activity in the replay from 0 to 10'),
kind: FieldKind.FIELD,
valueType: FieldValueType.INTEGER,
},
[ReplayFieldKey.BROWSER_NAME]: {
desc: t('Name of the browser'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayFieldKey.BROWSER_VERSION]: {
desc: t('Version number of the browser'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayFieldKey.COUNT_DEAD_CLICKS]: {
desc: t('Number of dead clicks in the replay'),
kind: FieldKind.FIELD,
valueType: FieldValueType.INTEGER,
},
[ReplayFieldKey.COUNT_RAGE_CLICKS]: {
desc: t('Number of rage clicks in the replay'),
kind: FieldKind.FIELD,
valueType: FieldValueType.INTEGER,
},
[ReplayFieldKey.COUNT_ERRORS]: {
desc: t('Number of errors in the replay'),
kind: FieldKind.FIELD,
valueType: FieldValueType.INTEGER,
},
[ReplayFieldKey.COUNT_SEGMENTS]: {
desc: t('Number of segments in the replay'),
kind: FieldKind.FIELD,
valueType: FieldValueType.INTEGER,
},
[ReplayFieldKey.COUNT_URLS]: {
desc: t('Number of urls visited within the replay'),
kind: FieldKind.FIELD,
valueType: FieldValueType.INTEGER,
},
[ReplayFieldKey.DURATION]: {
desc: t('Duration of the replay, in seconds'),
kind: FieldKind.FIELD,
valueType: FieldValueType.DURATION,
},
[ReplayFieldKey.ERROR_IDS]: {
desc: t('Error instance'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayFieldKey.OS_NAME]: {
desc: t('Name of the Operating System'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayFieldKey.OS_VERSION]: {
desc: t('Version number of the Operating System'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayFieldKey.URLS]: {
desc: t('List of urls that were visited within the Replay'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
};
export const REPLAY_CLICK_FIELDS = [
ReplayClickFieldKey.CLICK_ALT,
ReplayClickFieldKey.CLICK_CLASS,
ReplayClickFieldKey.CLICK_ID,
ReplayClickFieldKey.CLICK_LABEL,
ReplayClickFieldKey.CLICK_ROLE,
ReplayClickFieldKey.CLICK_SELECTOR,
ReplayClickFieldKey.DEAD_SELECTOR,
ReplayClickFieldKey.RAGE_SELECTOR,
ReplayClickFieldKey.CLICK_TAG,
ReplayClickFieldKey.CLICK_TEXT_CONTENT,
ReplayClickFieldKey.CLICK_TITLE,
ReplayClickFieldKey.CLICK_TESTID,
ReplayClickFieldKey.CLICK_COMPONENT_NAME,
];
// This is separated out from REPLAY_FIELD_DEFINITIONS so that it is feature-flaggable
const REPLAY_CLICK_FIELD_DEFINITIONS: Record<ReplayClickFieldKey, FieldDefinition> = {
[ReplayClickFieldKey.CLICK_ALT]: {
desc: t('`alt` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_CLASS]: {
desc: t('`class` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_ID]: {
desc: t('`id` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_LABEL]: {
desc: t('`aria-label` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_ROLE]: {
desc: t('`role` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_SELECTOR]: {
desc: t(
'query using CSS selector-like syntax, supports class, id, and attribute selectors'
),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.DEAD_SELECTOR]: {
desc: t(
'query using CSS selector-like syntax, supports class, id, and attribute selectors'
),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.RAGE_SELECTOR]: {
desc: t(
'query using CSS selector-like syntax, supports class, id, and attribute selectors'
),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_TAG]: {
desc: t('`tag` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_TESTID]: {
desc: t('`data-testid` or `data-test-id` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_TEXT_CONTENT]: {
desc: t('textContent of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_TITLE]: {
desc: t('`title` of an element that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[ReplayClickFieldKey.CLICK_COMPONENT_NAME]: {
desc: t('the name of the frontend component that was clicked'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
};
export enum FeedbackFieldKey {
BROWSER_NAME = 'browser.name',
BROWSER_VERSION = 'browser.version',
EMAIL = 'contact_email',
LOCALE_LANG = 'locale.lang',
LOCALE_TIMEZONE = 'locale.timezone',
MESSAGE = 'message',
NAME = 'name',
OS_NAME = 'os.name',
OS_VERSION = 'os.version',
URL = 'url',
}
export const FEEDBACK_FIELDS = [
FieldKey.ASSIGNED,
FeedbackFieldKey.BROWSER_NAME,
FeedbackFieldKey.BROWSER_VERSION,
FieldKey.DEVICE_BRAND,
FieldKey.DEVICE_FAMILY,
FieldKey.DEVICE_MODEL_ID,
FieldKey.DEVICE_NAME,
FieldKey.DIST,
FeedbackFieldKey.EMAIL,
FieldKey.ENVIRONMENT,
FieldKey.ID,
FieldKey.IS,
FieldKey.LEVEL,
FeedbackFieldKey.LOCALE_LANG,
FeedbackFieldKey.LOCALE_TIMEZONE,
FeedbackFieldKey.MESSAGE,
FeedbackFieldKey.NAME,
FeedbackFieldKey.OS_NAME,
FeedbackFieldKey.OS_VERSION,
FieldKey.PLATFORM,
FieldKey.SDK_NAME,
FieldKey.SDK_VERSION,
FieldKey.TIMESTAMP,
FieldKey.TRANSACTION,
FeedbackFieldKey.URL,
FieldKey.USER_EMAIL,
FieldKey.USER_ID,
FieldKey.USER_IP,
FieldKey.USER_USERNAME,
];
const FEEDBACK_FIELD_DEFINITIONS: Record<FeedbackFieldKey, FieldDefinition> = {
[FeedbackFieldKey.BROWSER_NAME]: {
desc: t('Name of the browser'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.BROWSER_VERSION]: {
desc: t('Version number of the browser'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.EMAIL]: {
desc: t('Contact email of the user writing the feedback'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.LOCALE_LANG]: {
desc: t('Language preference of the user'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.LOCALE_TIMEZONE]: {
desc: t('Timezone the feedback was submitted from'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.MESSAGE]: {
desc: t('Message written by the user providing feedback'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.NAME]: {
desc: t('Name of the user writing feedback'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.OS_NAME]: {
desc: t('Name of the operating system'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.OS_VERSION]: {
desc: t('Version number of the operating system'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
[FeedbackFieldKey.URL]: {
desc: t('URL of the page that the feedback is triggered on'),
kind: FieldKind.FIELD,
valueType: FieldValueType.STRING,
},
};
export const getFieldDefinition = (
key: string,
type: 'event' | 'replay' | 'replay_click' | 'feedback' = 'event'
): FieldDefinition | null => {
switch (type) {
case 'replay':
if (key in REPLAY_FIELD_DEFINITIONS) {
return REPLAY_FIELD_DEFINITIONS[key];
}
if (key in REPLAY_CLICK_FIELD_DEFINITIONS) {
return REPLAY_CLICK_FIELD_DEFINITIONS[key];
}
if (REPLAY_FIELDS.includes(key as FieldKey)) {
return EVENT_FIELD_DEFINITIONS[key];
}
return null;
case 'feedback':
if (key in FEEDBACK_FIELD_DEFINITIONS) {
return FEEDBACK_FIELD_DEFINITIONS[key];
}
if (FEEDBACK_FIELDS.includes(key as FieldKey)) {
return EVENT_FIELD_DEFINITIONS[key];
}
return null;
case 'event':
default:
return EVENT_FIELD_DEFINITIONS[key] ?? null;
}
};
export function makeTagCollection(fieldKeys: FieldKey[]): TagCollection {
return Object.fromEntries(
fieldKeys.map(fieldKey => [
fieldKey,
{
key: fieldKey,
name: fieldKey,
kind: getFieldDefinition(fieldKey)?.kind,
},
])
);
}
export function isDeviceClass(key): boolean {
return key === FieldKey.DEVICE_CLASS;
}
export const DEVICE_CLASS_TAG_VALUES = ['high', 'medium', 'low'];