mirror of
https://github.com/grafana/grafana.git
synced 2024-12-27 17:31:18 -06:00
Jaeger: Add stack trace to span detail row (#26427)
* Add stack trace to span detail row * Modify accordian text not to have a whitespace * Modify stackTrace to stackTraces * Modify AccordianText ti get text component as prop * Fix typecheck and test failure * Span details text area do not wrap line
This commit is contained in:
parent
fabd879cbe
commit
ba50e96544
@ -57,6 +57,7 @@ export type TraceSpanData = {
|
||||
tags?: TraceKeyValuePair[];
|
||||
references?: TraceSpanReference[];
|
||||
warnings?: string[] | null;
|
||||
stackTraces?: string[];
|
||||
flags: number;
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@grafana/data": "7.2.0-pre.0",
|
||||
"@grafana/ui": "7.2.0-pre.0",
|
||||
"@types/classnames": "^2.2.7",
|
||||
"@types/deep-freeze": "^0.1.1",
|
||||
"@types/hoist-non-react-statics": "^3.3.1",
|
||||
@ -22,6 +23,7 @@
|
||||
"@types/moment": "^2.13.0",
|
||||
"@types/react-icons": "2.2.7",
|
||||
"@types/recompose": "^0.30.7",
|
||||
"@types/slate-react": "0.22.5",
|
||||
"chance": "^1.0.10",
|
||||
"classnames": "^2.2.5",
|
||||
"combokeys": "^3.0.0",
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { mount } from 'enzyme';
|
||||
import AccordianText from './AccordianText';
|
||||
import TextList from './TextList';
|
||||
|
||||
@ -32,7 +32,7 @@ describe('<AccordianText>', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<AccordianText {...props} />);
|
||||
wrapper = mount(<AccordianText {...props} />);
|
||||
});
|
||||
|
||||
it('renders without exploding', () => {
|
||||
|
@ -40,17 +40,31 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
|
||||
type AccordianTextProps = {
|
||||
className?: string | TNil;
|
||||
data: string[];
|
||||
headerClassName?: string | TNil;
|
||||
data: string[];
|
||||
highContrast?: boolean;
|
||||
interactive?: boolean;
|
||||
isOpen: boolean;
|
||||
label: React.ReactNode;
|
||||
label: React.ReactNode | string;
|
||||
onToggle?: null | (() => void);
|
||||
TextComponent?: React.ElementType<{ data: string[] }>;
|
||||
};
|
||||
|
||||
function DefaultTextComponent({ data }: { data: string[] }) {
|
||||
return <TextList data={data} />;
|
||||
}
|
||||
|
||||
export default function AccordianText(props: AccordianTextProps) {
|
||||
const { className, data, headerClassName, interactive, isOpen, label, onToggle } = props;
|
||||
const {
|
||||
className,
|
||||
data,
|
||||
headerClassName,
|
||||
interactive,
|
||||
isOpen,
|
||||
label,
|
||||
onToggle,
|
||||
TextComponent = DefaultTextComponent,
|
||||
} = props;
|
||||
const isEmpty = !Array.isArray(data) || !data.length;
|
||||
const accordianKeyValuesStyles = getAccordianKeyValuesStyles(useTheme());
|
||||
const iconCls = cx(uAlignIcon, { [accordianKeyValuesStyles.emptyIcon]: isEmpty });
|
||||
@ -68,9 +82,10 @@ export default function AccordianText(props: AccordianTextProps) {
|
||||
return (
|
||||
<div className={className || ''}>
|
||||
<div className={cx(styles.header, headerClassName)} {...headerProps} data-test-id="AccordianText--header">
|
||||
{arrow} <strong>{label}</strong> ({data.length})
|
||||
{arrow}
|
||||
<strong>{label}</strong> ({data.length})
|
||||
</div>
|
||||
{isOpen && <TextList data={data} />}
|
||||
{isOpen && <TextComponent data={data} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ export default class DetailState {
|
||||
isProcessOpen: boolean;
|
||||
logs: { isOpen: boolean; openedItems: Set<TraceLog> };
|
||||
isWarningsOpen: boolean;
|
||||
isStackTracesOpen: boolean;
|
||||
isReferencesOpen: boolean;
|
||||
|
||||
constructor(oldState?: DetailState) {
|
||||
@ -30,12 +31,14 @@ export default class DetailState {
|
||||
isProcessOpen,
|
||||
isReferencesOpen,
|
||||
isWarningsOpen,
|
||||
isStackTracesOpen,
|
||||
logs,
|
||||
}: DetailState | Record<string, undefined> = oldState || {};
|
||||
this.isTagsOpen = Boolean(isTagsOpen);
|
||||
this.isProcessOpen = Boolean(isProcessOpen);
|
||||
this.isReferencesOpen = Boolean(isReferencesOpen);
|
||||
this.isWarningsOpen = Boolean(isWarningsOpen);
|
||||
this.isStackTracesOpen = Boolean(isStackTracesOpen);
|
||||
this.logs = {
|
||||
isOpen: Boolean(logs && logs.isOpen),
|
||||
openedItems: logs && logs.openedItems ? new Set(logs.openedItems) : new Set(),
|
||||
@ -66,6 +69,12 @@ export default class DetailState {
|
||||
return next;
|
||||
}
|
||||
|
||||
toggleStackTraces() {
|
||||
const next = new DetailState(this);
|
||||
next.isStackTracesOpen = !this.isStackTracesOpen;
|
||||
return next;
|
||||
}
|
||||
|
||||
toggleLogs() {
|
||||
const next = new DetailState(this);
|
||||
next.logs.isOpen = !this.logs.isOpen;
|
||||
|
@ -30,6 +30,7 @@ import AccordianReferences from './AccordianReferences';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { UIDivider } from '../../uiElementsContext';
|
||||
import { ubFlex, ubFlexAuto, ubItemsCenter, ubM0, ubMb1, ubMy1, ubTxRightAlign } from '../../uberUtilityStyles';
|
||||
import { TextArea } from '@grafana/ui';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
return {
|
||||
@ -94,6 +95,10 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
label: AccordianWarningsLabel;
|
||||
color: ${autoColor(theme, '#d36c08')};
|
||||
`,
|
||||
Textarea: css`
|
||||
word-break: break-all;
|
||||
white-space: pre;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
@ -107,6 +112,7 @@ type SpanDetailProps = {
|
||||
tagsToggle: (spanID: string) => void;
|
||||
traceStartTime: number;
|
||||
warningsToggle: (spanID: string) => void;
|
||||
stackTracesToggle: (spanID: string) => void;
|
||||
referencesToggle: (spanID: string) => void;
|
||||
focusSpan: (uiFind: string) => void;
|
||||
};
|
||||
@ -122,11 +128,30 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
tagsToggle,
|
||||
traceStartTime,
|
||||
warningsToggle,
|
||||
stackTracesToggle,
|
||||
referencesToggle,
|
||||
focusSpan,
|
||||
} = props;
|
||||
const { isTagsOpen, isProcessOpen, logs: logsState, isWarningsOpen, isReferencesOpen } = detailState;
|
||||
const { operationName, process, duration, relativeStartTime, spanID, logs, tags, warnings, references } = span;
|
||||
const {
|
||||
isTagsOpen,
|
||||
isProcessOpen,
|
||||
logs: logsState,
|
||||
isWarningsOpen,
|
||||
isReferencesOpen,
|
||||
isStackTracesOpen,
|
||||
} = detailState;
|
||||
const {
|
||||
operationName,
|
||||
process,
|
||||
duration,
|
||||
relativeStartTime,
|
||||
spanID,
|
||||
logs,
|
||||
tags,
|
||||
warnings,
|
||||
references,
|
||||
stackTraces,
|
||||
} = span;
|
||||
const overviewItems = [
|
||||
{
|
||||
key: 'svc',
|
||||
@ -195,6 +220,24 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
onToggle={() => warningsToggle(spanID)}
|
||||
/>
|
||||
)}
|
||||
{stackTraces && stackTraces.length && (
|
||||
<AccordianText
|
||||
label="Stack trace"
|
||||
data={stackTraces}
|
||||
isOpen={isStackTracesOpen}
|
||||
TextComponent={textComponentProps => (
|
||||
<TextArea
|
||||
className={styles.Textarea}
|
||||
style={{ cursor: 'unset' }}
|
||||
readOnly
|
||||
cols={10}
|
||||
rows={10}
|
||||
value={textComponentProps.data}
|
||||
/>
|
||||
)}
|
||||
onToggle={() => stackTracesToggle(spanID)}
|
||||
/>
|
||||
)}
|
||||
{references && references.length > 1 && (
|
||||
<AccordianReferences
|
||||
data={references}
|
||||
|
@ -76,6 +76,7 @@ type SpanDetailRowProps = {
|
||||
processToggle: (spanID: string) => void;
|
||||
referencesToggle: (spanID: string) => void;
|
||||
warningsToggle: (spanID: string) => void;
|
||||
stackTracesToggle: (spanID: string) => void;
|
||||
span: TraceSpan;
|
||||
tagsToggle: (spanID: string) => void;
|
||||
traceStartTime: number;
|
||||
@ -106,6 +107,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
|
||||
processToggle,
|
||||
referencesToggle,
|
||||
warningsToggle,
|
||||
stackTracesToggle,
|
||||
span,
|
||||
tagsToggle,
|
||||
traceStartTime,
|
||||
@ -147,6 +149,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
|
||||
processToggle={processToggle}
|
||||
referencesToggle={referencesToggle}
|
||||
warningsToggle={warningsToggle}
|
||||
stackTracesToggle={stackTracesToggle}
|
||||
span={span}
|
||||
tagsToggle={tagsToggle}
|
||||
traceStartTime={traceStartTime}
|
||||
|
@ -68,6 +68,7 @@ type TVirtualizedTraceViewOwnProps = {
|
||||
detailLogItemToggle: (spanID: string, log: TraceLog) => void;
|
||||
detailLogsToggle: (spanID: string) => void;
|
||||
detailWarningsToggle: (spanID: string) => void;
|
||||
detailStackTracesToggle: (spanID: string) => void;
|
||||
detailReferencesToggle: (spanID: string) => void;
|
||||
detailProcessToggle: (spanID: string) => void;
|
||||
detailTagsToggle: (spanID: string) => void;
|
||||
@ -392,6 +393,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
detailProcessToggle,
|
||||
detailReferencesToggle,
|
||||
detailWarningsToggle,
|
||||
detailStackTracesToggle,
|
||||
detailStates,
|
||||
detailTagsToggle,
|
||||
detailToggle,
|
||||
@ -423,6 +425,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
processToggle={detailProcessToggle}
|
||||
referencesToggle={detailReferencesToggle}
|
||||
warningsToggle={detailWarningsToggle}
|
||||
stackTracesToggle={detailStackTracesToggle}
|
||||
span={span}
|
||||
tagsToggle={detailTagsToggle}
|
||||
traceStartTime={trace.startTime}
|
||||
|
@ -89,6 +89,7 @@ type TProps = TExtractUiFindFromStateReturn & {
|
||||
detailLogItemToggle: (spanID: string, log: TraceLog) => void;
|
||||
detailLogsToggle: (spanID: string) => void;
|
||||
detailWarningsToggle: (spanID: string) => void;
|
||||
detailStackTracesToggle: (spanID: string) => void;
|
||||
detailReferencesToggle: (spanID: string) => void;
|
||||
detailProcessToggle: (spanID: string) => void;
|
||||
detailTagsToggle: (spanID: string) => void;
|
||||
|
@ -1,8 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "node_modules/@types",
|
||||
"paths": {
|
||||
"@grafana/slate-react": ["slate-react"]
|
||||
},
|
||||
"typeRoots": ["node_modules/@types"]
|
||||
},
|
||||
"extends": "@grafana/tsconfig",
|
||||
"include": ["src/**/*.ts*", "typings", "../../public/app/types/jquery/*.ts"]
|
||||
"include": ["src/**/*.ts*", "typings", "../../public/app/types/jquery/*.ts", "../../public/app/types/svg.d.ts"]
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ export function TraceView(props: Props) {
|
||||
detailReferencesToggle,
|
||||
detailTagsToggle,
|
||||
detailWarningsToggle,
|
||||
detailStackTracesToggle,
|
||||
} = useDetailState();
|
||||
const { removeHoverIndentGuideId, addHoverIndentGuideId, hoverIndentGuideIds } = useHoverIndentGuide();
|
||||
const { viewRange, updateViewRangeTime, updateNextViewRangeTime } = useViewRange();
|
||||
@ -126,6 +127,7 @@ export function TraceView(props: Props) {
|
||||
detailLogItemToggle={detailLogItemToggle}
|
||||
detailLogsToggle={detailLogsToggle}
|
||||
detailWarningsToggle={detailWarningsToggle}
|
||||
detailStackTracesToggle={detailStackTracesToggle}
|
||||
detailReferencesToggle={detailReferencesToggle}
|
||||
detailProcessToggle={detailProcessToggle}
|
||||
detailTagsToggle={detailTagsToggle}
|
||||
|
@ -44,6 +44,9 @@ export function useDetailState() {
|
||||
detailWarningsToggle: useCallback(makeDetailSubsectionToggle('warnings', detailStates, setDetailStates), [
|
||||
detailStates,
|
||||
]),
|
||||
detailStackTracesToggle: useCallback(makeDetailSubsectionToggle('stackTraces', detailStates, setDetailStates), [
|
||||
detailStates,
|
||||
]),
|
||||
detailReferencesToggle: useCallback(makeDetailSubsectionToggle('references', detailStates, setDetailStates), [
|
||||
detailStates,
|
||||
]),
|
||||
@ -55,7 +58,7 @@ export function useDetailState() {
|
||||
}
|
||||
|
||||
function makeDetailSubsectionToggle(
|
||||
subSection: 'tags' | 'process' | 'logs' | 'warnings' | 'references',
|
||||
subSection: 'tags' | 'process' | 'logs' | 'warnings' | 'references' | 'stackTraces',
|
||||
detailStates: Map<string, DetailState>,
|
||||
setDetailStates: (detailStates: Map<string, DetailState>) => void
|
||||
) {
|
||||
@ -73,6 +76,8 @@ function makeDetailSubsectionToggle(
|
||||
detailState = old.toggleWarnings();
|
||||
} else if (subSection === 'references') {
|
||||
detailState = old.toggleReferences();
|
||||
} else if (subSection === 'stackTraces') {
|
||||
detailState = old.toggleStackTraces();
|
||||
} else {
|
||||
detailState = old.toggleLogs();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user