TraceView: Resource attributes links extension point (#104680)
* TraceView: Resource attributes links extension point * Add data source info to context * Remove console log * Removing unused linkGetters and more * More tests * Fixing last todos * Fixing * Fixing * Change link style * Rename extension context * Fix lint error
This commit is contained in:
@@ -563,6 +563,7 @@ export {
|
||||
type PluginExtensionAddedComponentConfig,
|
||||
type PluginExtensionAddedLinkConfig,
|
||||
type PluginExtensionAddedFunctionConfig,
|
||||
type PluginExtensionResourceAttributesContext,
|
||||
} from './types/pluginExtensions';
|
||||
export {
|
||||
type ScopeDashboardBindingSpec,
|
||||
|
||||
@@ -192,6 +192,7 @@ export enum PluginExtensionPoints {
|
||||
UserProfileTab = 'grafana/user/profile/tab',
|
||||
TraceViewDetails = 'grafana/traceview/details',
|
||||
QueryEditorRowAdaptiveTelemetryV1 = 'grafana/query-editor-row/adaptivetelemetry/v1',
|
||||
TraceViewResourceAttributes = 'grafana/traceview/resource-attributes',
|
||||
}
|
||||
|
||||
export type PluginExtensionPanelContext = {
|
||||
@@ -236,6 +237,15 @@ export type PluginExtensionDataSourceConfigContext<
|
||||
|
||||
export type PluginExtensionCommandPaletteContext = {};
|
||||
|
||||
export type PluginExtensionResourceAttributesContext = {
|
||||
// Key-value pairs of resource attributes, attribute name is the key
|
||||
attributes: Record<string, string[]>;
|
||||
datasource: {
|
||||
type: string;
|
||||
uid: string;
|
||||
};
|
||||
};
|
||||
|
||||
type Dashboard = {
|
||||
uid: string;
|
||||
title: string;
|
||||
|
||||
@@ -169,6 +169,7 @@ export function TraceView(props: Props) {
|
||||
);
|
||||
const timeZone = useSelector((state) => getTimeZone(state.user));
|
||||
const datasourceType = datasource ? datasource?.type : 'unknown';
|
||||
const datasourceUid = datasource ? datasource?.uid : '';
|
||||
const scrollElement = props.scrollElement
|
||||
? props.scrollElement
|
||||
: document.getElementsByClassName(props.scrollElementClass ?? '')[0];
|
||||
@@ -204,6 +205,7 @@ export function TraceView(props: Props) {
|
||||
trace={traceProp}
|
||||
traceToProfilesOptions={traceToProfilesOptions}
|
||||
datasourceType={datasourceType}
|
||||
datasourceUid={datasourceUid}
|
||||
spanBarOptions={spanBarOptions?.spanBar}
|
||||
traceTimeline={traceTimeline}
|
||||
updateNextViewRangeTime={updateNextViewRangeTime}
|
||||
@@ -227,7 +229,6 @@ export function TraceView(props: Props) {
|
||||
detailToggle={toggleDetail}
|
||||
addHoverIndentGuideId={addHoverIndentGuideId}
|
||||
removeHoverIndentGuideId={removeHoverIndentGuideId}
|
||||
linksGetter={() => []}
|
||||
createSpanLink={createSpanLink}
|
||||
scrollElement={scrollElement}
|
||||
focusedSpanId={focusedSpanId}
|
||||
|
||||
+3
-3
@@ -20,10 +20,10 @@ import { GrafanaTheme2, TraceKeyValuePair } from '@grafana/data';
|
||||
import { Icon, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { autoColor } from '../../Theme';
|
||||
import { TraceLink, TNil } from '../../types';
|
||||
import { TNil } from '../../types';
|
||||
|
||||
import * as markers from './AccordianKeyValues.markers';
|
||||
import KeyValuesTable from './KeyValuesTable';
|
||||
import KeyValuesTable, { KeyValuesTableLink } from './KeyValuesTable';
|
||||
|
||||
import { alignIcon } from '.';
|
||||
|
||||
@@ -94,7 +94,7 @@ export type AccordianKeyValuesProps = {
|
||||
interactive?: boolean;
|
||||
isOpen: boolean;
|
||||
label: string | React.ReactNode;
|
||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => TraceLink[]) | TNil;
|
||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => KeyValuesTableLink[]) | TNil;
|
||||
onToggle?: null | (() => void);
|
||||
};
|
||||
|
||||
|
||||
+1
-6
@@ -16,13 +16,11 @@ import { css } from '@emotion/css';
|
||||
import { sortBy as _sortBy } from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { GrafanaTheme2, TraceKeyValuePair, TraceLog } from '@grafana/data';
|
||||
import { GrafanaTheme2, TraceLog } from '@grafana/data';
|
||||
import { Trans } from '@grafana/i18n';
|
||||
import { Icon, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { autoColor } from '../../Theme';
|
||||
import { TNil } from '../../types';
|
||||
import { TraceLink } from '../../types/trace';
|
||||
import { formatDuration } from '../utils';
|
||||
|
||||
import AccordianKeyValues from './AccordianKeyValues';
|
||||
@@ -69,7 +67,6 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
export type AccordianLogsProps = {
|
||||
interactive?: boolean;
|
||||
isOpen: boolean;
|
||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => TraceLink[]) | TNil;
|
||||
logs: TraceLog[];
|
||||
onItemToggle?: (log: TraceLog) => void;
|
||||
onToggle?: () => void;
|
||||
@@ -80,7 +77,6 @@ export type AccordianLogsProps = {
|
||||
export default function AccordianLogs({
|
||||
interactive = true,
|
||||
isOpen,
|
||||
linksGetter,
|
||||
logs,
|
||||
openedItems,
|
||||
onItemToggle,
|
||||
@@ -138,7 +134,6 @@ export default function AccordianLogs({
|
||||
interactive={interactive}
|
||||
isOpen={openedItems ? openedItems.has(log) : false}
|
||||
label={label}
|
||||
linksGetter={linksGetter}
|
||||
onToggle={interactive && onItemToggle ? () => onItemToggle(log) : null}
|
||||
/>
|
||||
);
|
||||
|
||||
-1
@@ -176,7 +176,6 @@ export function References(props: ReferenceItemProps) {
|
||||
interactive={interactive}
|
||||
isOpen={openedItems ? openedItems.has(reference) : false}
|
||||
label={t('explore.references.label-attributes', 'attributes')}
|
||||
linksGetter={null}
|
||||
onToggle={interactive && onItemToggle ? () => onItemToggle(reference) : null}
|
||||
/>
|
||||
</div>
|
||||
|
||||
+7
-9
@@ -33,14 +33,12 @@ const setup = (propOverrides?: Partial<KeyValuesTableProps>) => {
|
||||
|
||||
describe('LinkValue', () => {
|
||||
it('renders as expected', () => {
|
||||
const title = 'titleValue';
|
||||
const href = 'hrefValue';
|
||||
const link = {
|
||||
title: 'titleValue',
|
||||
path: 'hrefValue',
|
||||
};
|
||||
const childrenText = 'childrenTextValue';
|
||||
render(
|
||||
<LinkValue href={href} title={title}>
|
||||
{childrenText}
|
||||
</LinkValue>
|
||||
);
|
||||
render(<LinkValue link={link}>{childrenText}</LinkValue>);
|
||||
expect(screen.getByRole('link', { name: 'titleValue' })).toBeInTheDocument();
|
||||
expect(screen.getByText(/^childrenTextValue$/)).toBeInTheDocument();
|
||||
});
|
||||
@@ -73,8 +71,8 @@ describe('KeyValuesTable tests', () => {
|
||||
array[i].key === 'span.kind'
|
||||
? [
|
||||
{
|
||||
url: `http://example.com/?kind=${encodeURIComponent(array[i].value)}`,
|
||||
text: `More info about ${array[i].value}`,
|
||||
path: `http://example.com/?kind=${encodeURIComponent(array[i].value)}`,
|
||||
title: `More info about ${array[i].value}`,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
|
||||
+19
-14
@@ -15,14 +15,13 @@
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { GrafanaTheme2, TraceKeyValuePair } from '@grafana/data';
|
||||
import { GrafanaTheme2, PluginExtensionLink, TraceKeyValuePair } from '@grafana/data';
|
||||
import { Icon, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { autoColor } from '../../Theme';
|
||||
import CopyIcon from '../../common/CopyIcon';
|
||||
import { TraceLink, TNil } from '../../types';
|
||||
import { TNil } from '../../types';
|
||||
|
||||
import jsonMarkup from './jsonMarkup';
|
||||
|
||||
@@ -57,6 +56,12 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
||||
[`&:not(:hover) .${copyIconClassName}`]: {
|
||||
visibility: 'hidden',
|
||||
},
|
||||
'a span': {
|
||||
color: `${theme.colors.text.link} !important`,
|
||||
},
|
||||
'a:hover span': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}),
|
||||
keyColumn: css({
|
||||
label: 'keyColumn',
|
||||
@@ -94,23 +99,25 @@ function parseIfComplexJson(value: unknown) {
|
||||
return value;
|
||||
}
|
||||
|
||||
export type KeyValuesTableLink = Pick<PluginExtensionLink, 'path' | 'title' | 'onClick' | 'icon'>;
|
||||
|
||||
interface LinkValueProps {
|
||||
href: string;
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
link: KeyValuesTableLink;
|
||||
}
|
||||
|
||||
export const LinkValue = ({ href, title = '', children }: PropsWithChildren<LinkValueProps>) => {
|
||||
export const LinkValue = ({ link, children }: PropsWithChildren<LinkValueProps>) => {
|
||||
const { path, title = '', onClick, icon = 'external-link-alt' } = link;
|
||||
|
||||
return (
|
||||
<a href={href} title={title} target="_blank" rel="noopener noreferrer">
|
||||
{children} <Icon name="external-link-alt" />
|
||||
<a href={path} title={title} onClick={onClick} target="_blank" rel="noopener noreferrer">
|
||||
{children} <Icon name={icon} />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export type KeyValuesTableProps = {
|
||||
data: TraceKeyValuePair[];
|
||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => TraceLink[]) | TNil;
|
||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => KeyValuesTableLink[]) | TNil;
|
||||
};
|
||||
|
||||
export default function KeyValuesTable(props: KeyValuesTableProps) {
|
||||
@@ -125,15 +132,13 @@ export default function KeyValuesTable(props: KeyValuesTableProps) {
|
||||
__html: jsonMarkup(parseIfComplexJson(row.value)),
|
||||
};
|
||||
const jsonTable = <div className={styles.jsonTable} dangerouslySetInnerHTML={markup} />;
|
||||
const links = linksGetter ? linksGetter(data, i) : null;
|
||||
const links = linksGetter?.(data, i);
|
||||
let valueMarkup;
|
||||
if (links && links.length) {
|
||||
// TODO: handle multiple items
|
||||
valueMarkup = (
|
||||
<div>
|
||||
<LinkValue href={links[0].url} title={links[0].text}>
|
||||
{jsonTable}
|
||||
</LinkValue>
|
||||
<LinkValue link={links[0]}>{jsonTable}</LinkValue>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
|
||||
+23
@@ -76,6 +76,8 @@ describe('<SpanDetail>', () => {
|
||||
to: 1000000000000,
|
||||
},
|
||||
},
|
||||
datasourceType: 'tempo',
|
||||
datasourceUid: 'grafanacloud-traces',
|
||||
};
|
||||
|
||||
span.tags = [
|
||||
@@ -258,4 +260,25 @@ describe('<SpanDetail>', () => {
|
||||
expect(screen.getByText(/(Count)/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should load plugin links for resource attributes', () => {
|
||||
const usePluginLinksMock = jest.fn().mockReturnValue({ links: [] });
|
||||
setPluginLinksHook(usePluginLinksMock);
|
||||
jest.requireMock('@grafana/runtime').usePluginLinks = usePluginLinksMock;
|
||||
|
||||
render(<SpanDetail {...(props as unknown as SpanDetailProps)} />);
|
||||
expect(usePluginLinksMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
context: expect.objectContaining({
|
||||
attributes: expect.objectContaining({
|
||||
'http.url': expect.arrayContaining([expect.any(String)]),
|
||||
}),
|
||||
datasource: {
|
||||
type: 'tempo',
|
||||
uid: 'grafanacloud-traces',
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+49
-7
@@ -15,6 +15,7 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { SpanStatusCode } from '@opentelemetry/api';
|
||||
import cx from 'classnames';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import {
|
||||
CoreApp,
|
||||
@@ -25,9 +26,12 @@ import {
|
||||
TimeRange,
|
||||
TraceKeyValuePair,
|
||||
TraceLog,
|
||||
PluginExtensionResourceAttributesContext,
|
||||
PluginExtensionPoints,
|
||||
} from '@grafana/data';
|
||||
import { Trans, useTranslate } from '@grafana/i18n';
|
||||
import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend';
|
||||
import { usePluginLinks } from '@grafana/runtime';
|
||||
import { TimeZone } from '@grafana/schema';
|
||||
import { Divider, Icon, TextArea, useStyles2 } from '@grafana/ui';
|
||||
|
||||
@@ -35,8 +39,8 @@ import { pyroscopeProfileIdTagKey } from '../../../createSpanLink';
|
||||
import { autoColor } from '../../Theme';
|
||||
import LabeledList from '../../common/LabeledList';
|
||||
import { KIND, LIBRARY_NAME, LIBRARY_VERSION, STATUS, STATUS_MESSAGE, TRACE_STATE } from '../../constants/span';
|
||||
import { SpanLinkFunc, TNil } from '../../types';
|
||||
import { TraceLink, TraceSpan, TraceSpanReference } from '../../types/trace';
|
||||
import { SpanLinkFunc } from '../../types';
|
||||
import { TraceProcess, TraceSpan, TraceSpanReference } from '../../types/trace';
|
||||
import { formatDuration } from '../utils';
|
||||
|
||||
import AccordianKeyValues from './AccordianKeyValues';
|
||||
@@ -47,6 +51,44 @@ import DetailState from './DetailState';
|
||||
import { getSpanDetailLinkButtons } from './SpanDetailLinkButtons';
|
||||
import SpanFlameGraph from './SpanFlameGraph';
|
||||
|
||||
const useResourceAttributesExtensionLinks = (process: TraceProcess, datasourceType: string, datasourceUid: string) => {
|
||||
// Stable context for useMemo inside usePluginLinks
|
||||
const context: PluginExtensionResourceAttributesContext = useMemo(() => {
|
||||
const attributes = (process.tags ?? []).reduce<Record<string, string[]>>((acc, tag) => {
|
||||
if (acc[tag.key]) {
|
||||
acc[tag.key].push(tag.value);
|
||||
} else {
|
||||
acc[tag.key] = [tag.value];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
attributes,
|
||||
datasource: {
|
||||
type: datasourceType,
|
||||
uid: datasourceUid,
|
||||
},
|
||||
};
|
||||
}, [process.tags, datasourceType, datasourceUid]);
|
||||
|
||||
const { links } = usePluginLinks({
|
||||
extensionPointId: PluginExtensionPoints.TraceViewResourceAttributes,
|
||||
limitPerPlugin: 10,
|
||||
context,
|
||||
});
|
||||
|
||||
const resourceLinksGetter = useCallback(
|
||||
(pairs: TraceKeyValuePair[], index: number) => {
|
||||
const { key } = pairs[index] ?? {};
|
||||
return links.filter((link) => link.category === key);
|
||||
},
|
||||
[links]
|
||||
);
|
||||
|
||||
return resourceLinksGetter;
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
header: css({
|
||||
@@ -145,7 +187,6 @@ export type TraceFlameGraphs = {
|
||||
|
||||
export type SpanDetailProps = {
|
||||
detailState: DetailState;
|
||||
linksGetter: ((links: TraceKeyValuePair[], index: number) => TraceLink[]) | TNil;
|
||||
logItemToggle: (spanID: string, log: TraceLog) => void;
|
||||
logsToggle: (spanID: string) => void;
|
||||
processToggle: (spanID: string) => void;
|
||||
@@ -164,6 +205,7 @@ export type SpanDetailProps = {
|
||||
focusedSpanId?: string;
|
||||
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
||||
datasourceType: string;
|
||||
datasourceUid: string;
|
||||
traceFlameGraphs: TraceFlameGraphs;
|
||||
setTraceFlameGraphs: (flameGraphs: TraceFlameGraphs) => void;
|
||||
setRedrawListView: (redraw: {}) => void;
|
||||
@@ -174,7 +216,6 @@ export type SpanDetailProps = {
|
||||
export default function SpanDetail(props: SpanDetailProps) {
|
||||
const {
|
||||
detailState,
|
||||
linksGetter,
|
||||
logItemToggle,
|
||||
logsToggle,
|
||||
processToggle,
|
||||
@@ -190,6 +231,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
createSpanLink,
|
||||
createFocusSpanLink,
|
||||
datasourceType,
|
||||
datasourceUid,
|
||||
traceFlameGraphs,
|
||||
setTraceFlameGraphs,
|
||||
traceToProfilesOptions,
|
||||
@@ -302,6 +344,8 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
});
|
||||
|
||||
const focusSpanLink = createFocusSpanLink(traceID, spanID);
|
||||
const resourceLinksGetter = useResourceAttributesExtensionLinks(process, datasourceType, datasourceUid);
|
||||
|
||||
return (
|
||||
<div data-testid="span-detail-component">
|
||||
<div className={styles.header}>
|
||||
@@ -319,7 +363,6 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
<AccordianKeyValues
|
||||
data={tags}
|
||||
label={t('explore.span-detail.label-span-attributes', 'Span attributes')}
|
||||
linksGetter={linksGetter}
|
||||
isOpen={isTagsOpen}
|
||||
onToggle={() => tagsToggle(spanID)}
|
||||
/>
|
||||
@@ -328,7 +371,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
className={styles.AccordianKeyValuesItem}
|
||||
data={process.tags}
|
||||
label={t('explore.span-detail.label-resource-attributes', 'Resource attributes')}
|
||||
linksGetter={linksGetter}
|
||||
linksGetter={resourceLinksGetter}
|
||||
isOpen={isProcessOpen}
|
||||
onToggle={() => processToggle(spanID)}
|
||||
/>
|
||||
@@ -336,7 +379,6 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
</div>
|
||||
{logs && logs.length > 0 && (
|
||||
<AccordianLogs
|
||||
linksGetter={linksGetter}
|
||||
logs={logs}
|
||||
isOpen={logsState.isOpen}
|
||||
openedItems={logsState.openedItems}
|
||||
|
||||
+5
-9
@@ -16,14 +16,14 @@ import { css } from '@emotion/css';
|
||||
import classNames from 'classnames';
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
import { CoreApp, GrafanaTheme2, LinkModel, TimeRange, TraceKeyValuePair, TraceLog } from '@grafana/data';
|
||||
import { CoreApp, GrafanaTheme2, LinkModel, TimeRange, TraceLog } from '@grafana/data';
|
||||
import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend';
|
||||
import { TimeZone } from '@grafana/schema';
|
||||
import { Button, clearButtonStyles, stylesFactory, withTheme2 } from '@grafana/ui';
|
||||
|
||||
import { autoColor } from '../Theme';
|
||||
import { SpanLinkFunc } from '../types';
|
||||
import { TraceSpan, TraceLink, TraceSpanReference } from '../types/trace';
|
||||
import { TraceSpan, TraceSpanReference } from '../types/trace';
|
||||
|
||||
import SpanDetail, { TraceFlameGraphs } from './SpanDetail';
|
||||
import DetailState from './SpanDetail/DetailState';
|
||||
@@ -76,7 +76,6 @@ export type SpanDetailRowProps = {
|
||||
columnDivision: number;
|
||||
detailState: DetailState;
|
||||
onDetailToggled: (spanID: string) => void;
|
||||
linksGetter: (span: TraceSpan, links: TraceKeyValuePair[], index: number) => TraceLink[];
|
||||
logItemToggle: (spanID: string, log: TraceLog) => void;
|
||||
logsToggle: (spanID: string) => void;
|
||||
processToggle: (spanID: string) => void;
|
||||
@@ -99,6 +98,7 @@ export type SpanDetailRowProps = {
|
||||
focusedSpanId?: string;
|
||||
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
||||
datasourceType: string;
|
||||
datasourceUid: string;
|
||||
visibleSpanIds: string[];
|
||||
traceFlameGraphs: TraceFlameGraphs;
|
||||
setTraceFlameGraphs: (flameGraphs: TraceFlameGraphs) => void;
|
||||
@@ -112,11 +112,6 @@ export class UnthemedSpanDetailRow extends PureComponent<SpanDetailRowProps> {
|
||||
this.props.onDetailToggled(this.props.span.spanID);
|
||||
};
|
||||
|
||||
_linksGetter = (items: TraceKeyValuePair[], itemIndex: number) => {
|
||||
const { linksGetter, span } = this.props;
|
||||
return linksGetter(span, items, itemIndex);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
color,
|
||||
@@ -144,6 +139,7 @@ export class UnthemedSpanDetailRow extends PureComponent<SpanDetailRowProps> {
|
||||
focusedSpanId,
|
||||
createFocusSpanLink,
|
||||
datasourceType,
|
||||
datasourceUid,
|
||||
visibleSpanIds,
|
||||
traceFlameGraphs,
|
||||
setTraceFlameGraphs,
|
||||
@@ -175,7 +171,6 @@ export class UnthemedSpanDetailRow extends PureComponent<SpanDetailRowProps> {
|
||||
<div className={styles.infoWrapper} style={{ borderTopColor: color }}>
|
||||
<SpanDetail
|
||||
detailState={detailState}
|
||||
linksGetter={this._linksGetter}
|
||||
logItemToggle={logItemToggle}
|
||||
logsToggle={logsToggle}
|
||||
processToggle={processToggle}
|
||||
@@ -194,6 +189,7 @@ export class UnthemedSpanDetailRow extends PureComponent<SpanDetailRowProps> {
|
||||
focusedSpanId={focusedSpanId}
|
||||
createFocusSpanLink={createFocusSpanLink}
|
||||
datasourceType={datasourceType}
|
||||
datasourceUid={datasourceUid}
|
||||
traceFlameGraphs={traceFlameGraphs}
|
||||
setTraceFlameGraphs={setTraceFlameGraphs}
|
||||
setRedrawListView={setRedrawListView}
|
||||
|
||||
+5
-5
@@ -18,7 +18,7 @@ import memoizeOne from 'memoize-one';
|
||||
import * as React from 'react';
|
||||
import { RefObject } from 'react';
|
||||
|
||||
import { CoreApp, GrafanaTheme2, LinkModel, TimeRange, TraceKeyValuePair, TraceLog } from '@grafana/data';
|
||||
import { CoreApp, GrafanaTheme2, LinkModel, TimeRange, TraceLog } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n/internal';
|
||||
import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend';
|
||||
import { config, reportInteraction } from '@grafana/runtime';
|
||||
@@ -28,7 +28,7 @@ import { stylesFactory, withTheme2, ToolbarButton } from '@grafana/ui';
|
||||
import { PEER_SERVICE } from '../constants/tag-keys';
|
||||
import { CriticalPathSection, SpanBarOptions, SpanLinkFunc, TNil } from '../types';
|
||||
import TTraceTimeline from '../types/TTraceTimeline';
|
||||
import { TraceSpan, Trace, TraceLink, TraceSpanReference } from '../types/trace';
|
||||
import { TraceSpan, Trace, TraceSpanReference } from '../types/trace';
|
||||
import { getColorByKey } from '../utils/color-generator';
|
||||
|
||||
import ListView from './ListView';
|
||||
@@ -79,7 +79,6 @@ type TVirtualizedTraceViewOwnProps = {
|
||||
trace: Trace;
|
||||
traceToProfilesOptions?: TraceToProfilesOptions;
|
||||
spanBarOptions: SpanBarOptions | undefined;
|
||||
linksGetter: (span: TraceSpan, items: TraceKeyValuePair[], itemIndex: number) => TraceLink[];
|
||||
childrenToggle: (spanID: string) => void;
|
||||
detailLogItemToggle: (spanID: string, log: TraceLog) => void;
|
||||
detailLogsToggle: (spanID: string) => void;
|
||||
@@ -104,6 +103,7 @@ type TVirtualizedTraceViewOwnProps = {
|
||||
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
||||
topOfViewRef?: RefObject<HTMLDivElement>;
|
||||
datasourceType: string;
|
||||
datasourceUid: string;
|
||||
headerHeight: number;
|
||||
criticalPath: CriticalPathSection[];
|
||||
traceFlameGraphs: TraceFlameGraphs;
|
||||
@@ -551,12 +551,12 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
hoverIndentGuideIds,
|
||||
addHoverIndentGuideId,
|
||||
removeHoverIndentGuideId,
|
||||
linksGetter,
|
||||
createSpanLink,
|
||||
focusedSpanId,
|
||||
createFocusSpanLink,
|
||||
theme,
|
||||
datasourceType,
|
||||
datasourceUid,
|
||||
traceFlameGraphs,
|
||||
setTraceFlameGraphs,
|
||||
setRedrawListView,
|
||||
@@ -577,7 +577,6 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
columnDivision={spanNameColumnWidth}
|
||||
onDetailToggled={detailToggle}
|
||||
detailState={detailState}
|
||||
linksGetter={linksGetter}
|
||||
logItemToggle={detailLogItemToggle}
|
||||
logsToggle={detailLogsToggle}
|
||||
processToggle={detailProcessToggle}
|
||||
@@ -599,6 +598,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
focusedSpanId={focusedSpanId}
|
||||
createFocusSpanLink={createFocusSpanLink}
|
||||
datasourceType={datasourceType}
|
||||
datasourceUid={datasourceUid}
|
||||
visibleSpanIds={visibleSpanIds}
|
||||
traceFlameGraphs={traceFlameGraphs}
|
||||
setTraceFlameGraphs={setTraceFlameGraphs}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { PureComponent, RefObject } from 'react';
|
||||
|
||||
import { CoreApp, GrafanaTheme2, LinkModel, TimeRange, TraceKeyValuePair, TraceLog } from '@grafana/data';
|
||||
import { CoreApp, GrafanaTheme2, LinkModel, TimeRange, TraceLog } from '@grafana/data';
|
||||
import { SpanBarOptions, TraceToProfilesOptions } from '@grafana/o11y-ds-frontend';
|
||||
import { config, reportInteraction } from '@grafana/runtime';
|
||||
import { TimeZone } from '@grafana/schema';
|
||||
@@ -25,7 +25,7 @@ import { autoColor } from '../Theme';
|
||||
import { merge as mergeShortcuts } from '../keyboard-shortcuts';
|
||||
import { CriticalPathSection, SpanLinkFunc, TNil } from '../types';
|
||||
import TTraceTimeline from '../types/TTraceTimeline';
|
||||
import { TraceSpan, Trace, TraceLink, TraceSpanReference } from '../types/trace';
|
||||
import { TraceSpan, Trace, TraceSpanReference } from '../types/trace';
|
||||
|
||||
import { TraceFlameGraphs } from './SpanDetail';
|
||||
import TimelineHeaderRow from './TimelineHeaderRow';
|
||||
@@ -72,6 +72,7 @@ export type TProps = {
|
||||
trace: Trace;
|
||||
traceToProfilesOptions?: TraceToProfilesOptions;
|
||||
datasourceType: string;
|
||||
datasourceUid: string;
|
||||
spanBarOptions: SpanBarOptions | undefined;
|
||||
updateNextViewRangeTime: (update: ViewRangeTimeUpdate) => void;
|
||||
updateViewRangeTime: TUpdateViewRangeTimeFunction;
|
||||
@@ -96,7 +97,6 @@ export type TProps = {
|
||||
detailToggle: (spanID: string) => void;
|
||||
addHoverIndentGuideId: (spanID: string) => void;
|
||||
removeHoverIndentGuideId: (spanID: string) => void;
|
||||
linksGetter: (span: TraceSpan, items: TraceKeyValuePair[], itemIndex: number) => TraceLink[];
|
||||
theme: GrafanaTheme2;
|
||||
createSpanLink?: SpanLinkFunc;
|
||||
scrollElement?: Element;
|
||||
@@ -222,6 +222,7 @@ export class UnthemedTraceTimelineViewer extends PureComponent<TProps, State> {
|
||||
topOfViewRef={topOfViewRef}
|
||||
focusedSpanIdForSearch={focusedSpanIdForSearch}
|
||||
datasourceType={this.props.datasourceType}
|
||||
datasourceUid={this.props.datasourceUid}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user