mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tracing: Span link feature tracking (#61022)
* Span link feature tracking * Update interaction name
This commit is contained in:
parent
28dbbe9f5f
commit
2b6a5e2b3d
@ -328,6 +328,7 @@ export type SpanBarRowProps = {
|
|||||||
clippingLeft?: boolean;
|
clippingLeft?: boolean;
|
||||||
clippingRight?: boolean;
|
clippingRight?: boolean;
|
||||||
createSpanLink?: SpanLinkFunc;
|
createSpanLink?: SpanLinkFunc;
|
||||||
|
datasourceType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -377,6 +378,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
|||||||
clippingRight,
|
clippingRight,
|
||||||
theme,
|
theme,
|
||||||
createSpanLink,
|
createSpanLink,
|
||||||
|
datasourceType,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {
|
const {
|
||||||
duration,
|
duration,
|
||||||
@ -515,7 +517,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
|||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (links && count > 1) {
|
} else if (links && count > 1) {
|
||||||
return <SpanLinksMenu links={links} />;
|
return <SpanLinksMenu links={links} datasourceType={datasourceType} />;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import React from 'react';
|
|||||||
import IoLink from 'react-icons/lib/io/link';
|
import IoLink from 'react-icons/lib/io/link';
|
||||||
|
|
||||||
import { dateTimeFormat, GrafanaTheme2, LinkModel, TimeZone } from '@grafana/data';
|
import { dateTimeFormat, GrafanaTheme2, LinkModel, TimeZone } from '@grafana/data';
|
||||||
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { DataLinkButton, TextArea, useStyles2 } from '@grafana/ui';
|
import { DataLinkButton, TextArea, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { autoColor } from '../../Theme';
|
import { autoColor } from '../../Theme';
|
||||||
@ -121,6 +122,7 @@ export type SpanDetailProps = {
|
|||||||
focusedSpanId?: string;
|
focusedSpanId?: string;
|
||||||
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
||||||
topOfViewRefType?: TopOfViewRefType;
|
topOfViewRefType?: TopOfViewRefType;
|
||||||
|
datasourceType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SpanDetail(props: SpanDetailProps) {
|
export default function SpanDetail(props: SpanDetailProps) {
|
||||||
@ -140,6 +142,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
|||||||
createSpanLink,
|
createSpanLink,
|
||||||
createFocusSpanLink,
|
createFocusSpanLink,
|
||||||
topOfViewRefType,
|
topOfViewRefType,
|
||||||
|
datasourceType,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
isTagsOpen,
|
isTagsOpen,
|
||||||
@ -193,6 +196,19 @@ export default function SpanDetail(props: SpanDetailProps) {
|
|||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const links = createSpanLink?.(span);
|
const links = createSpanLink?.(span);
|
||||||
const focusSpanLink = createFocusSpanLink(traceID, spanID);
|
const focusSpanLink = createFocusSpanLink(traceID, spanID);
|
||||||
|
const logLink = links?.logLinks?.[0]
|
||||||
|
? {
|
||||||
|
...links?.logLinks?.[0],
|
||||||
|
onClick: (event: React.MouseEvent) => {
|
||||||
|
reportInteraction('grafana_traces_trace_view_span_link_clicked', {
|
||||||
|
datasourceType: datasourceType,
|
||||||
|
type: 'log',
|
||||||
|
location: 'spanDetails',
|
||||||
|
});
|
||||||
|
links?.logLinks?.[0].onClick!(event);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="span-detail-component">
|
<div data-testid="span-detail-component">
|
||||||
@ -203,10 +219,9 @@ export default function SpanDetail(props: SpanDetailProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{links?.logLinks?.[0] ? (
|
{links?.logLinks?.[0] ? (
|
||||||
<DataLinkButton
|
<>
|
||||||
link={{ ...links?.logLinks?.[0], title: 'Logs for this span' } as any}
|
<DataLinkButton link={{ ...logLink, title: 'Logs for this span' } as any} buttonProps={{ icon: 'gf-logs' }} />
|
||||||
buttonProps={{ icon: 'gf-logs' }}
|
</>
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
<Divider className={ubMy1} type={'horizontal'} />
|
<Divider className={ubMy1} type={'horizontal'} />
|
||||||
<div>
|
<div>
|
||||||
|
@ -96,6 +96,7 @@ export type SpanDetailRowProps = {
|
|||||||
focusedSpanId?: string;
|
focusedSpanId?: string;
|
||||||
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
||||||
topOfViewRefType?: TopOfViewRefType;
|
topOfViewRefType?: TopOfViewRefType;
|
||||||
|
datasourceType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProps> {
|
export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProps> {
|
||||||
@ -132,6 +133,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
|
|||||||
focusedSpanId,
|
focusedSpanId,
|
||||||
createFocusSpanLink,
|
createFocusSpanLink,
|
||||||
topOfViewRefType,
|
topOfViewRefType,
|
||||||
|
datasourceType,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const styles = getStyles(theme);
|
const styles = getStyles(theme);
|
||||||
return (
|
return (
|
||||||
@ -172,6 +174,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
|
|||||||
focusedSpanId={focusedSpanId}
|
focusedSpanId={focusedSpanId}
|
||||||
createFocusSpanLink={createFocusSpanLink}
|
createFocusSpanLink={createFocusSpanLink}
|
||||||
topOfViewRefType={topOfViewRefType}
|
topOfViewRefType={topOfViewRefType}
|
||||||
|
datasourceType={datasourceType}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TimelineRow.Cell>
|
</TimelineRow.Cell>
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { useStyles2, MenuGroup, MenuItem, Icon, ContextMenu } from '@grafana/ui';
|
import { useStyles2, MenuGroup, MenuItem, Icon, ContextMenu } from '@grafana/ui';
|
||||||
|
|
||||||
import { SpanLinks } from '../types/links';
|
import { SpanLinks } from '../types/links';
|
||||||
|
|
||||||
interface SpanLinksProps {
|
interface SpanLinksProps {
|
||||||
links: SpanLinks;
|
links: SpanLinks;
|
||||||
|
datasourceType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderMenuItems = (links: SpanLinks, styles: ReturnType<typeof getStyles>, closeMenu: () => void) => {
|
const renderMenuItems = (
|
||||||
|
links: SpanLinks,
|
||||||
|
styles: ReturnType<typeof getStyles>,
|
||||||
|
closeMenu: () => void,
|
||||||
|
datasourceType: string
|
||||||
|
) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!!links.logLinks?.length ? (
|
{!!links.logLinks?.length ? (
|
||||||
@ -21,6 +28,11 @@ const renderMenuItems = (links: SpanLinks, styles: ReturnType<typeof getStyles>,
|
|||||||
onClick={
|
onClick={
|
||||||
link.onClick
|
link.onClick
|
||||||
? (event) => {
|
? (event) => {
|
||||||
|
reportInteraction('grafana_traces_trace_view_span_link_clicked', {
|
||||||
|
datasourceType: datasourceType,
|
||||||
|
type: 'log',
|
||||||
|
location: 'menu',
|
||||||
|
});
|
||||||
event?.preventDefault();
|
event?.preventDefault();
|
||||||
link.onClick!(event);
|
link.onClick!(event);
|
||||||
closeMenu();
|
closeMenu();
|
||||||
@ -42,6 +54,11 @@ const renderMenuItems = (links: SpanLinks, styles: ReturnType<typeof getStyles>,
|
|||||||
onClick={
|
onClick={
|
||||||
link.onClick
|
link.onClick
|
||||||
? (event) => {
|
? (event) => {
|
||||||
|
reportInteraction('grafana_traces_trace_view_span_link_clicked', {
|
||||||
|
datasourceType: datasourceType,
|
||||||
|
type: 'metric',
|
||||||
|
location: 'menu',
|
||||||
|
});
|
||||||
event?.preventDefault();
|
event?.preventDefault();
|
||||||
link.onClick!(event);
|
link.onClick!(event);
|
||||||
closeMenu();
|
closeMenu();
|
||||||
@ -63,6 +80,11 @@ const renderMenuItems = (links: SpanLinks, styles: ReturnType<typeof getStyles>,
|
|||||||
onClick={
|
onClick={
|
||||||
link.onClick
|
link.onClick
|
||||||
? (event) => {
|
? (event) => {
|
||||||
|
reportInteraction('grafana_traces_trace_view_span_link_clicked', {
|
||||||
|
datasourceType: datasourceType,
|
||||||
|
type: 'trace',
|
||||||
|
location: 'menu',
|
||||||
|
});
|
||||||
event?.preventDefault();
|
event?.preventDefault();
|
||||||
link.onClick!(event);
|
link.onClick!(event);
|
||||||
closeMenu();
|
closeMenu();
|
||||||
@ -79,7 +101,7 @@ const renderMenuItems = (links: SpanLinks, styles: ReturnType<typeof getStyles>,
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SpanLinksMenu = ({ links }: SpanLinksProps) => {
|
export const SpanLinksMenu = ({ links, datasourceType }: SpanLinksProps) => {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
|
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
|
||||||
@ -104,7 +126,7 @@ export const SpanLinksMenu = ({ links }: SpanLinksProps) => {
|
|||||||
{isMenuOpen ? (
|
{isMenuOpen ? (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
onClose={() => setIsMenuOpen(false)}
|
onClose={() => setIsMenuOpen(false)}
|
||||||
renderMenuItems={() => renderMenuItems(links, styles, closeMenu)}
|
renderMenuItems={() => renderMenuItems(links, styles, closeMenu, datasourceType)}
|
||||||
focusOnOpen={true}
|
focusOnOpen={true}
|
||||||
x={menuPosition.x}
|
x={menuPosition.x}
|
||||||
y={menuPosition.y}
|
y={menuPosition.y}
|
||||||
|
@ -115,6 +115,7 @@ type TVirtualizedTraceViewOwnProps = {
|
|||||||
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
|
||||||
topOfViewRef?: RefObject<HTMLDivElement>;
|
topOfViewRef?: RefObject<HTMLDivElement>;
|
||||||
topOfViewRefType?: TopOfViewRefType;
|
topOfViewRefType?: TopOfViewRefType;
|
||||||
|
datasourceType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VirtualizedTraceViewProps = TVirtualizedTraceViewOwnProps & TExtractUiFindFromStateReturn & TTraceTimeline;
|
export type VirtualizedTraceViewProps = TVirtualizedTraceViewOwnProps & TExtractUiFindFromStateReturn & TTraceTimeline;
|
||||||
@ -396,6 +397,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
|||||||
focusedSpanId,
|
focusedSpanId,
|
||||||
focusedSpanIdForSearch,
|
focusedSpanIdForSearch,
|
||||||
theme,
|
theme,
|
||||||
|
datasourceType,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
// to avert flow error
|
// to avert flow error
|
||||||
if (!trace) {
|
if (!trace) {
|
||||||
@ -461,6 +463,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
|||||||
addHoverIndentGuideId={addHoverIndentGuideId}
|
addHoverIndentGuideId={addHoverIndentGuideId}
|
||||||
removeHoverIndentGuideId={removeHoverIndentGuideId}
|
removeHoverIndentGuideId={removeHoverIndentGuideId}
|
||||||
createSpanLink={createSpanLink}
|
createSpanLink={createSpanLink}
|
||||||
|
datasourceType={datasourceType}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -492,6 +495,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
|||||||
createFocusSpanLink,
|
createFocusSpanLink,
|
||||||
topOfViewRefType,
|
topOfViewRefType,
|
||||||
theme,
|
theme,
|
||||||
|
datasourceType,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const detailState = detailStates.get(spanID);
|
const detailState = detailStates.get(spanID);
|
||||||
if (!trace || !detailState) {
|
if (!trace || !detailState) {
|
||||||
@ -525,6 +529,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
|||||||
focusedSpanId={focusedSpanId}
|
focusedSpanId={focusedSpanId}
|
||||||
createFocusSpanLink={createFocusSpanLink}
|
createFocusSpanLink={createFocusSpanLink}
|
||||||
topOfViewRefType={topOfViewRefType}
|
topOfViewRefType={topOfViewRefType}
|
||||||
|
datasourceType={datasourceType}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user