mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
281 lines
7.5 KiB
TypeScript
281 lines
7.5 KiB
TypeScript
import invert from 'lodash/invert';
|
|
|
|
import type {
|
|
SelectValue,
|
|
SessionAggregationColumn,
|
|
SessionsMeta,
|
|
SessionsOperation,
|
|
} from 'sentry/types';
|
|
import {SessionField, SessionStatus} from 'sentry/types';
|
|
import {defined} from 'sentry/utils';
|
|
import type {FieldValue} from 'sentry/views/discover/table/types';
|
|
import {FieldValueKind} from 'sentry/views/discover/table/types';
|
|
|
|
enum SessionMetric {
|
|
ANR_RATE = 'session.anr_rate',
|
|
FOREGROUND_ANR_RATE = 'session.foreground_anr_rate',
|
|
SESSION_COUNT = 'session.all',
|
|
SESSION_DURATION = 'sentry.sessions.session.duration',
|
|
SESSION_ERROR = 'sentry.sessions.session.error',
|
|
SESSION_CRASH_FREE_RATE = 'session.crash_free_rate',
|
|
USER_CRASH_FREE_RATE = 'session.crash_free_user_rate',
|
|
SESSION_CRASH_RATE = 'session.crash_rate',
|
|
USER_CRASH_RATE = 'session.crash_user_rate',
|
|
USER = 'sentry.sessions.user',
|
|
SESSION_HEALTHY = 'session.healthy',
|
|
USER_HEALTHY = 'session.healthy_user',
|
|
SESSION_ABNORMAL = 'session.abnormal',
|
|
USER_ABNORMAL = 'session.abnormal_user',
|
|
SESSION_CRASHED = 'session.crashed',
|
|
USER_CRASHED = 'session.crashed_user',
|
|
SESSION_ERRORED = 'session.errored',
|
|
USER_ERRORED = 'session.errored_user',
|
|
}
|
|
|
|
export const DERIVED_STATUS_METRICS_PATTERN =
|
|
/count_(abnormal|errored|crashed|healthy)\((user|session)\)/;
|
|
|
|
export enum DerivedStatusFields {
|
|
HEALTHY_SESSIONS = 'count_healthy(session)',
|
|
HEALTHY_USERS = 'count_healthy(user)',
|
|
ABNORMAL_SESSIONS = 'count_abnormal(session)',
|
|
ABNORMAL_USERS = 'count_abnormal(user)',
|
|
CRASHED_SESSIONS = 'count_crashed(session)',
|
|
CRASHED_USERS = 'count_crashed(user)',
|
|
ERRORED_SESSIONS = 'count_errored(session)',
|
|
ERRORED_USERS = 'count_errored(user)',
|
|
}
|
|
|
|
export const FIELD_TO_METRICS_EXPRESSION = {
|
|
'foreground_anr_rate()': SessionMetric.FOREGROUND_ANR_RATE,
|
|
'anr_rate()': SessionMetric.ANR_RATE,
|
|
'count_healthy(session)': SessionMetric.SESSION_HEALTHY,
|
|
'count_healthy(user)': SessionMetric.USER_HEALTHY,
|
|
'count_abnormal(session)': SessionMetric.SESSION_ABNORMAL,
|
|
'count_abnormal(user)': SessionMetric.USER_ABNORMAL,
|
|
'count_crashed(session)': SessionMetric.SESSION_CRASHED,
|
|
'count_crashed(user)': SessionMetric.USER_CRASHED,
|
|
'count_errored(session)': SessionMetric.SESSION_ERRORED,
|
|
'count_errored(user)': SessionMetric.USER_ERRORED,
|
|
'count_unique(user)': `count_unique(${SessionMetric.USER})`,
|
|
'sum(session)': SessionMetric.SESSION_COUNT,
|
|
'crash_free_rate(session)': SessionMetric.SESSION_CRASH_FREE_RATE,
|
|
'crash_free_rate(user)': SessionMetric.USER_CRASH_FREE_RATE,
|
|
'crash_rate(session)': SessionMetric.SESSION_CRASH_RATE,
|
|
'crash_rate(user)': SessionMetric.USER_CRASH_RATE,
|
|
project: 'project_id',
|
|
};
|
|
|
|
export const METRICS_EXPRESSION_TO_FIELD = invert(FIELD_TO_METRICS_EXPRESSION);
|
|
|
|
export const DISABLED_SORT = [
|
|
'count_errored(session)',
|
|
'count_errored(user)',
|
|
'count_healthy(session)',
|
|
'count_healthy(user)',
|
|
'session.status',
|
|
];
|
|
|
|
export const TAG_SORT_DENY_LIST = ['project', 'environment'];
|
|
|
|
export const SESSIONS_FIELDS: Readonly<Partial<Record<SessionField, SessionsMeta>>> = {
|
|
[SessionField.SESSION]: {
|
|
name: 'session',
|
|
operations: [
|
|
'sum',
|
|
'crash_rate',
|
|
'crash_free_rate',
|
|
'count_healthy',
|
|
'count_abnormal',
|
|
'count_crashed',
|
|
'count_errored',
|
|
'anr_rate',
|
|
'foreground_anr_rate',
|
|
],
|
|
type: 'integer',
|
|
},
|
|
[SessionField.USER]: {
|
|
name: 'user',
|
|
operations: [
|
|
'count_unique',
|
|
'crash_rate',
|
|
'crash_free_rate',
|
|
'count_healthy',
|
|
'count_abnormal',
|
|
'count_crashed',
|
|
'count_errored',
|
|
],
|
|
type: 'string',
|
|
},
|
|
[SessionField.SESSION_DURATION]: {
|
|
name: 'session.duration',
|
|
operations: [],
|
|
type: 'duration',
|
|
},
|
|
};
|
|
|
|
export const SESSIONS_OPERATIONS: Readonly<
|
|
Record<SessionsOperation, SessionAggregationColumn>
|
|
> = {
|
|
anr_rate: {
|
|
outputType: 'percentage',
|
|
parameters: [],
|
|
},
|
|
foreground_anr_rate: {
|
|
outputType: 'percentage',
|
|
parameters: [],
|
|
},
|
|
sum: {
|
|
outputType: 'integer',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
count_unique: {
|
|
outputType: 'integer',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['string'],
|
|
defaultValue: SessionField.USER,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
count_healthy: {
|
|
outputType: 'integer',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer', 'string'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
count_abnormal: {
|
|
outputType: 'integer',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer', 'string'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
count_crashed: {
|
|
outputType: 'integer',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer', 'string'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
count_errored: {
|
|
outputType: 'integer',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer', 'string'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
crash_rate: {
|
|
outputType: 'percentage',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer', 'string'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
crash_free_rate: {
|
|
outputType: 'percentage',
|
|
parameters: [
|
|
{
|
|
kind: 'column',
|
|
columnTypes: ['integer', 'string'],
|
|
defaultValue: SessionField.SESSION,
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
export const SESSIONS_TAGS = ['environment', 'project', 'release', 'session.status'];
|
|
export const SESSIONS_FILTER_TAGS = ['environment', 'project', 'release'];
|
|
export const SESSION_STATUSES = Object.values(SessionStatus);
|
|
|
|
export function generateReleaseWidgetFieldOptions(
|
|
fields: SessionsMeta[] = Object.values(SESSIONS_FIELDS),
|
|
tagKeys?: string[]
|
|
) {
|
|
const fieldOptions: Record<string, SelectValue<FieldValue>> = {};
|
|
|
|
const operations = new Set<SessionsOperation>();
|
|
const knownOperations = Object.keys(SESSIONS_OPERATIONS);
|
|
|
|
fields
|
|
.sort((a, b) => a.name.localeCompare(b.name))
|
|
.forEach(field => {
|
|
field.operations.forEach(operation => operations.add(operation));
|
|
|
|
fieldOptions[`field:${field.name}`] = {
|
|
label: field.name,
|
|
value: {
|
|
kind: FieldValueKind.METRICS,
|
|
meta: {
|
|
name: field.name,
|
|
dataType: field.type,
|
|
},
|
|
},
|
|
};
|
|
});
|
|
|
|
Array.from(operations)
|
|
.filter(operation => knownOperations.includes(operation))
|
|
.sort((a, b) => a.localeCompare(b))
|
|
.forEach(operation => {
|
|
fieldOptions[`function:${operation}`] = {
|
|
label: `${operation}(${'\u2026'})`,
|
|
value: {
|
|
kind: FieldValueKind.FUNCTION,
|
|
meta: {
|
|
name: operation,
|
|
parameters: SESSIONS_OPERATIONS[operation].parameters.map(param => param),
|
|
},
|
|
},
|
|
};
|
|
});
|
|
|
|
if (defined(tagKeys)) {
|
|
// Expose environment. session.status, project etc. as fields.
|
|
tagKeys
|
|
.sort((a, b) => a.localeCompare(b))
|
|
.forEach(tag => {
|
|
fieldOptions[`field:${tag}`] = {
|
|
label: tag,
|
|
value: {
|
|
kind: FieldValueKind.FIELD,
|
|
meta: {name: tag, dataType: 'string'},
|
|
},
|
|
};
|
|
});
|
|
}
|
|
|
|
return fieldOptions;
|
|
}
|