Skip to content

Commit

Permalink
feat(threads): Display closest lock reason as a thread tag (#50472)
Browse files Browse the repository at this point in the history
  • Loading branch information
romtsn authored Jun 12, 2023
1 parent 7528f45 commit 28505c0
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
14 changes: 12 additions & 2 deletions static/app/components/events/interfaces/threads.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,15 @@ describe('Threads', function () {
},
rawStacktrace: null,
state: 'BLOCKED',
lockReason: 'waiting on tid=1',
heldLocks: {
'0x0d3a2f0a': {
type: 8,
address: '0x0d3a2f0a',
package_name: 'java.lang',
class_name: 'Object',
thread_id: 11,
},
},
},
{
id: 1,
Expand Down Expand Up @@ -903,7 +911,9 @@ describe('Threads', function () {
expect(screen.getByText('Threads')).toBeInTheDocument();
expect(screen.getByText('Thread State')).toBeInTheDocument();
expect(screen.getAllByText('Blocked')).toHaveLength(2);
expect(screen.getAllByText('waiting on tid=1')).toHaveLength(2);
expect(
screen.getAllByText('waiting to lock <0x0d3a2f0a> held by thread 11')
).toHaveLength(2);
expect(screen.getByText('Thread Tags')).toBeInTheDocument();

// Actions
Expand Down
9 changes: 6 additions & 3 deletions static/app/components/events/interfaces/threads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from '@emotion/styled';
import isNil from 'lodash/isNil';

import {EventDataSection} from 'sentry/components/events/eventDataSection';
import {getLockReason} from 'sentry/components/events/interfaces/threads/threadSelector/lockReason';
import {
getMappedThreadState,
getThreadStateHelpText,
Expand All @@ -26,6 +27,7 @@ import {
StackView,
Thread,
} from 'sentry/types';
import {defined} from 'sentry/utils';

import {PermalinkTitle, TraceEventDataSection} from '../traceEventDataSection';

Expand Down Expand Up @@ -150,14 +152,15 @@ export function Threads({
current,
crashed,
state: threadState,
lockReason,
heldLocks,
} = activeThread ?? {};

if (isNil(id) || !name) {
return null;
}

const threadStateDisplay = getMappedThreadState(threadState);
const lockReason = getLockReason(heldLocks);

return (
<Pills>
Expand All @@ -172,7 +175,7 @@ export function Threads({
{!isNil(threadStateDisplay) && (
<Pill name={t('state')} value={threadStateDisplay} />
)}
{!isNil(lockReason) && <Pill name={t('lock reason')} value={lockReason} />}
{defined(lockReason) && <Pill name={t('lock reason')} value={lockReason} />}
</Pills>
);
}
Expand Down Expand Up @@ -284,7 +287,7 @@ export function Threads({
title={getThreadStateHelpText(threadStateDisplay)}
/>
)}
{<LockReason>{activeThread?.lockReason}</LockReason>}
{<LockReason>{getLockReason(activeThread?.heldLocks)}</LockReason>}
</ThreadStateWrapper>
</EventDataSection>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {Lock, LockType} from 'sentry/types';
import {defined} from 'sentry/utils';

export function getLockReason(
heldLocks?: Record<string, Lock> | null
): string | undefined {
if (!defined(heldLocks)) {
return undefined;
}

const values = Object.values(heldLocks);
if (values.length === 0) {
return undefined;
}

const firstLock = values[0] as Lock;
if (!defined(firstLock)) {
return undefined;
}

const address = firstLock?.address ?? 'unknown object';
const tid = firstLock?.thread_id;
let reason: string | undefined;

switch (firstLock.type) {
case LockType.LOCKED:
reason = `locked <${address}>`;
break;
case LockType.WAITING:
reason = `waiting on <${address}>`;
break;
case LockType.SLEEPING:
reason = `sleeping on <${address}>`;
break;
case LockType.BLOCKED:
reason =
`waiting to lock <${address}>` + (defined(tid) ? ` held by thread ${tid}` : '');
break;
default:
reason = undefined;
}
return reason;
}
17 changes: 16 additions & 1 deletion static/app/types/event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,26 @@ export interface Thread {
id: number;
rawStacktrace: RawStacktrace;
stacktrace: StacktraceType | null;
lockReason?: string | null;
heldLocks?: Record<string, Lock> | null;
name?: string | null;
state?: string | null;
}

export type Lock = {
address: string | null;
class_name: string | null;
package_name: string | null;
thread_id: number | null;
type: LockType;
};

export enum LockType {
LOCKED = 1,
WAITING = 2,
SLEEPING = 4,
BLOCKED = 8,
}

export type Frame = {
absPath: string | null;
colNo: number | null;
Expand Down

0 comments on commit 28505c0

Please sign in to comment.