123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- import compact from 'lodash/compact';
- import moment from 'moment';
- import {
- DateTimeObject,
- getDiffInMinutes,
- ONE_WEEK,
- TWO_WEEKS,
- } from 'app/components/charts/utils';
- import {SessionApiResponse, SessionField} from 'app/types';
- import {SeriesDataUnit} from 'app/types/echarts';
- import {defined, percent} from 'app/utils';
- import {getCrashFreePercent} from 'app/views/releases/utils';
- export function getCount(groups: SessionApiResponse['groups'] = [], field: SessionField) {
- return groups.reduce((acc, group) => acc + group.totals[field], 0);
- }
- export function getCrashCount(
- groups: SessionApiResponse['groups'] = [],
- field: SessionField
- ) {
- return getCount(
- groups.filter(({by}) => by['session.status'] === 'crashed'),
- field
- );
- }
- export function getCrashFreeRate(
- groups: SessionApiResponse['groups'] = [],
- field: SessionField
- ) {
- const totalCount = groups.reduce((acc, group) => acc + group.totals[field], 0);
- const crashedCount = getCrashCount(groups, field);
- return !defined(totalCount) || totalCount === 0
- ? null
- : getCrashFreePercent(100 - percent(crashedCount ?? 0, totalCount ?? 0));
- }
- export function getCrashFreeSeries(
- groups: SessionApiResponse['groups'] = [],
- intervals: SessionApiResponse['intervals'] = [],
- field: SessionField
- ): SeriesDataUnit[] {
- return compact(
- intervals.map((interval, i) => {
- const intervalTotalSessions = groups.reduce(
- (acc, group) => acc + group.series[field][i],
- 0
- );
- const intervalCrashedSessions =
- groups.find(group => group.by['session.status'] === 'crashed')?.series[field][
- i
- ] ?? 0;
- const crashedSessionsPercent = percent(
- intervalCrashedSessions,
- intervalTotalSessions
- );
- if (intervalTotalSessions === 0) {
- return null;
- }
- return {
- name: interval,
- value: getCrashFreePercent(100 - crashedSessionsPercent),
- };
- })
- );
- }
- export function getAdoptionSeries(
- releaseGroups: SessionApiResponse['groups'] = [],
- allGroups: SessionApiResponse['groups'] = [],
- intervals: SessionApiResponse['intervals'] = [],
- field: SessionField
- ): SeriesDataUnit[] {
- return intervals.map((interval, i) => {
- const intervalReleaseSessions = releaseGroups.reduce(
- (acc, group) => acc + group.series[field][i],
- 0
- );
- const intervalTotalSessions = allGroups.reduce(
- (acc, group) => acc + group.series[field][i],
- 0
- );
- const intervalAdoption = percent(intervalReleaseSessions, intervalTotalSessions);
- return {
- name: interval,
- value: Math.round(intervalAdoption),
- };
- });
- }
- type GetSessionsIntervalOptions = {
- highFidelity?: boolean;
- };
- export function getSessionsInterval(
- datetimeObj: DateTimeObject,
- {highFidelity}: GetSessionsIntervalOptions = {}
- ) {
- const diffInMinutes = getDiffInMinutes(datetimeObj);
- if (diffInMinutes > TWO_WEEKS) {
- return '1d';
- }
- if (diffInMinutes > ONE_WEEK) {
- return '6h';
- }
- // limit on backend for sub-hour session resolution is set to six hours
- if (highFidelity && diffInMinutes < 360) {
- if (diffInMinutes <= 30) {
- return '1m';
- }
- return '5m';
- }
- return '1h';
- }
- // Sessions API can only round intervals to the closest hour - this is especially problematic when using sub-hour resolution.
- // We filter out results that are out of bounds on frontend and recalculate totals.
- export function filterSessionsInTimeWindow(
- sessions: SessionApiResponse,
- start?: string,
- end?: string
- ) {
- if (!start || !end) {
- return sessions;
- }
- const filteredIndexes: number[] = [];
- const intervals = sessions.intervals.filter((interval, index) => {
- const isBetween = moment(interval).isBetween(start, end, undefined, '[]');
- if (isBetween) {
- filteredIndexes.push(index);
- }
- return isBetween;
- });
- const groups = sessions.groups.map(group => {
- const series = {};
- const totals = {};
- Object.keys(group.series).forEach(field => {
- series[field] = group.series[field].filter((value, index) => {
- const isBetween = filteredIndexes.includes(index);
- if (isBetween) {
- totals[field] = (totals[field] ?? 0) + value;
- }
- return isBetween;
- });
- });
- return {...group, series, totals};
- });
- return {
- start: intervals[0],
- end: intervals[intervals.length - 1],
- query: sessions.query,
- intervals,
- groups,
- };
- }
|