Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions static/app/components/events/interfaces/threads/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,25 @@ describe('Threads', () => {
userEvent.click(screen.getByText('ViewController.captureNSException (RUNNABLE)'));
expect(screen.getByText('State')).toBeInTheDocument();
});

it('maps android vm states to java vm states', () => {
const threadsEntry = entries[1];
threadsEntry.data.values[0].state = 'kWaitingPerformingGc';
render(
<Threads
data={threadsEntry.data}
projectSlug="project-id"
event={event}
hasHierarchicalGrouping={false}
/>
);

// kWaitingPerformingGc maps to WAITING
expect(
screen.getByText('ViewController.captureNSException (WAITING)')
).toBeInTheDocument();
userEvent.click(screen.getByText('ViewController.captureNSException (WAITING)'));
expect(screen.getByText('State')).toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import {trimPackage} from 'sentry/components/events/interfaces/frame/utils';
import {
getMappedThreadState,
ThreadStates,
} from 'sentry/components/events/interfaces/threads/threadSelector/threadStates';
import {
EntryData,
Event,
Expand All @@ -17,7 +21,7 @@ type ThreadInfo = {
crashedInfo?: EntryData;
filename?: string;
label?: string;
state?: Thread['state'];
state?: ThreadStates;
};

function filterThreadInfo(
Expand All @@ -26,7 +30,7 @@ function filterThreadInfo(
exception?: Required<ExceptionType>
): ThreadInfo {
const threadInfo: ThreadInfo = {};
threadInfo.state = thread.state;
threadInfo.state = getMappedThreadState(thread.state);

let stacktrace: StacktraceType | undefined = getThreadStacktrace(false, thread);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import partition from 'lodash/partition';

import DropdownAutoComplete from 'sentry/components/dropdownAutoComplete';
import DropdownButton from 'sentry/components/dropdownButton';
import {getMappedThreadState} from 'sentry/components/events/interfaces/threads/threadSelector/threadStates';
import {t} from 'sentry/locale';
import {Event, ExceptionType, Thread} from 'sentry/types';
import {defined} from 'sentry/utils';
Expand Down Expand Up @@ -33,13 +34,19 @@ const ThreadSelector = ({
onChange,
fullWidth = false,
}: Props) => {
const hasThreadStates = threads.some(thread => defined(thread.state));
const hasThreadStates = threads.some(thread =>
defined(getMappedThreadState(thread.state))
);

const getDropDownItem = (thread: Thread) => {
const {label, filename, crashedInfo} = filterThreadInfo(event, thread, exception);
const threadInfo = {label, filename, state: thread.state};
const {label, filename, crashedInfo, state} = filterThreadInfo(
event,
thread,
exception
);
const threadInfo = {label, filename, state};
return {
value: `#${thread.id}: ${thread.name} ${label} ${filename} (${thread.state})`,
value: `#${thread.id}: ${thread.name} ${label} ${filename}`,
threadInfo,
thread,
label: (
Expand All @@ -49,7 +56,6 @@ const ThreadSelector = ({
name={thread.name}
crashed={thread.crashed}
crashedInfo={crashedInfo}
state={thread.state}
hasThreadStates={hasThreadStates}
/>
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import styled from '@emotion/styled';

import {ThreadStates} from 'sentry/components/events/interfaces/threads/threadSelector/threadStates';
import TextOverflow from 'sentry/components/textOverflow';
import {Tooltip} from 'sentry/components/tooltip';
import {IconFire} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
import {EntryData, Thread} from 'sentry/types';
import {EntryData} from 'sentry/types';
import {ColorOrAlias} from 'sentry/utils/theme';

import {Grid, GridCell} from './styles';
Expand All @@ -16,23 +17,15 @@ type Props = {
crashed?: boolean;
crashedInfo?: EntryData;
name?: string | null;
state?: Thread['state'];
};

type ThreadInfo = {
filename?: string;
label?: string;
state?: ThreadStates;
};

const Option = ({
id,
details,
name,
crashed,
crashedInfo,
state,
hasThreadStates,
}: Props) => {
const Option = ({id, details, name, crashed, crashedInfo, hasThreadStates}: Props) => {
const label = details.label ?? `<${t('unknown')}>`;
const optionName = name || `<${t('unknown')}>`;

Expand Down Expand Up @@ -82,8 +75,8 @@ const Option = ({
{hasThreadStates && (
<GridCell>
<InnerCell>
<Tooltip title={state} position="top">
<TextOverflow>{state}</TextOverflow>
<Tooltip title={details.state} position="top">
<TextOverflow>{details.state}</TextOverflow>
</Tooltip>
</InnerCell>
</GridCell>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import styled from '@emotion/styled';

import {ThreadStates} from 'sentry/components/events/interfaces/threads/threadSelector/threadStates';
import TextOverflow from 'sentry/components/textOverflow';
import {t, tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import {Thread} from 'sentry/types';

type Props = {
details: ThreadInfo;
Expand All @@ -13,7 +13,7 @@ type Props = {
type ThreadInfo = {
filename?: string;
label?: string;
state?: Thread['state'];
state?: ThreadStates;
};

function getThreadLabel(details: ThreadInfo) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {defined} from 'sentry/utils';

export enum ThreadStates {
RUNNABLE = 'RUNNABLE',
TIMED_WAITING = 'TIMED_WAITING',
BLOCKED = 'BLOCKED',
WAITING = 'WAITING',
NEW = 'NEW',
TERMINATED = 'TERMINATED',
}

type ThreadStatesMap = Record<string, ThreadStates>;

export const javaThreadStatesMap: ThreadStatesMap = {
RUNNABLE: ThreadStates.RUNNABLE,
TIMED_WAITING: ThreadStates.TIMED_WAITING,
BLOCKED: ThreadStates.BLOCKED,
WAITING: ThreadStates.WAITING,
NEW: ThreadStates.NEW,
TERMINATED: ThreadStates.TERMINATED,
// Android VM thread states https://cs.android.com/android/platform/superproject/+/master:art/runtime/thread_state.h
kTerminated: ThreadStates.TERMINATED, // Thread.run has returned, but Thread* still around
kRunnable: ThreadStates.RUNNABLE, // runnable
kTimedWaiting: ThreadStates.TIMED_WAITING, // in Object.wait() with a timeout
kSleeping: ThreadStates.TIMED_WAITING, // in Thread.sleep()
kBlocked: ThreadStates.BLOCKED, // blocked on a monitor
kWaiting: ThreadStates.WAITING, // in Object.wait()
kWaitingForLockInflation: ThreadStates.WAITING, // blocked inflating a thin-lock
kWaitingForTaskProcessor: ThreadStates.WAITING, // blocked waiting for taskProcessor
kWaitingForGcToComplete: ThreadStates.WAITING, // blocked waiting for GC
kWaitingForCheckPointsToRun: ThreadStates.WAITING, // GC waiting for checkpoints to run
kWaitingPerformingGc: ThreadStates.WAITING, // performing GC
kWaitingForDebuggerSend: ThreadStates.WAITING, // blocked waiting for events to be sent
kWaitingForDebuggerToAttach: ThreadStates.WAITING, // blocked waiting for debugger to attach
kWaitingInMainDebuggerLoop: ThreadStates.WAITING, // blocking/reading/processing debugger events
kWaitingForDebuggerSuspension: ThreadStates.WAITING, // waiting for debugger suspend all
kWaitingForJniOnLoad: ThreadStates.WAITING, // waiting for execution of dlopen and JNI on load code
kWaitingForSignalCatcherOutput: ThreadStates.WAITING, // waiting for signal catcher IO to complete
kWaitingInMainSignalCatcherLoop: ThreadStates.WAITING, // blocking/reading/processing signals
kWaitingForDeoptimization: ThreadStates.WAITING, // waiting for deoptimization suspend all
kWaitingForMethodTracingStart: ThreadStates.WAITING, // waiting for method tracing to start
kWaitingForVisitObjects: ThreadStates.WAITING, // waiting for visiting objects
kWaitingForGetObjectsAllocated: ThreadStates.WAITING, // waiting for getting the number of allocated objects
kWaitingWeakGcRootRead: ThreadStates.WAITING, // waiting on the GC to read a weak root
kWaitingForGcThreadFlip: ThreadStates.WAITING, // waiting on the GC thread flip (CC collector) to finish
kNativeForAbort: ThreadStates.WAITING, // checking other threads are not run on abort.
kStarting: ThreadStates.NEW, // native thread started, not yet ready to run managed code
kNative: ThreadStates.RUNNABLE, // running in a JNI native method
kSuspended: ThreadStates.RUNNABLE, // suspended by GC or debugger
};

export function getMappedThreadState(
state: string | undefined | null
): ThreadStates | undefined {
if (defined(state)) {
return javaThreadStatesMap[state];
}
return undefined;
}