Trace View: Copy Trace ID action button (#64416)

* Added button to trace view to copy trace ID

* Added dummy Export button
pull/64602/head
Andre Pereira 2 years ago committed by GitHub
parent 6cbc956b5c
commit 1667ea118f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 59
      public/app/features/explore/TraceView/components/TracePageHeader/Actions/ActionButton.tsx
  2. 51
      public/app/features/explore/TraceView/components/TracePageHeader/Actions/TracePageActions.tsx
  3. 23
      public/app/features/explore/TraceView/components/TracePageHeader/NewTracePageHeader.tsx

@ -0,0 +1,59 @@
import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2, IconName } from '@grafana/data';
import { Button, useStyles2 } from '@grafana/ui';
export const getStyles = (theme: GrafanaTheme2) => {
return {
ActionButton: css`
label: ActionButton;
overflow: hidden;
position: relative;
width: 110px;
justify-content: center;
&:after {
content: '';
background: ${theme.colors.primary.main};
display: block;
position: absolute;
right: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: all 0.8s;
}
&:active:after {
margin: 0;
opacity: 0.3;
transition: 0s;
}
`,
};
};
export type ActionButtonProps = {
onClick: () => void;
ariaLabel: string;
label: string;
icon: IconName;
};
export default function ActionButton(props: ActionButtonProps) {
const { onClick, ariaLabel, label, icon } = props;
const styles = useStyles2(getStyles);
return (
<Button
className={styles.ActionButton}
variant="secondary"
fill={'outline'}
type="button"
icon={icon}
aria-label={ariaLabel}
onClick={onClick}
>
{label}
</Button>
);
}

@ -0,0 +1,51 @@
import { css } from '@emotion/css';
import React, { useState } from 'react';
import { useStyles2 } from '@grafana/ui';
import ActionButton from './ActionButton';
export const getStyles = () => {
return {
TracePageActions: css`
label: TracePageActions;
display: flex;
gap: 4px;
`,
};
};
export type TracePageActionsProps = {
traceId: string;
};
export default function TracePageActions(props: TracePageActionsProps) {
const { traceId } = props;
const styles = useStyles2(getStyles);
const [copyTraceIdClicked, setCopyTraceIdClicked] = useState(false);
const copyTraceId = () => {
navigator.clipboard.writeText(traceId);
setCopyTraceIdClicked(true);
setTimeout(() => {
setCopyTraceIdClicked(false);
}, 5000);
};
return (
<div className={styles.TracePageActions}>
<ActionButton
onClick={copyTraceId}
ariaLabel={'Copy Trace ID'}
label={copyTraceIdClicked ? 'Copied!' : 'Trace ID'}
icon={'copy'}
/>
<ActionButton
onClick={() => alert('not implemented')}
ariaLabel={'Export Trace'}
label={'Export'}
icon={'save'}
/>
</div>
);
}

@ -26,15 +26,29 @@ import { getTraceLinks } from '../model/link-patterns';
import { getHeaderTags, getTraceName } from '../model/trace-viewer';
import { formatDuration } from '../utils/date';
import TracePageActions from './Actions/TracePageActions';
import SpanGraph from './SpanGraph';
import { TracePageHeaderEmbedProps, timestamp, getStyles } from './TracePageHeader';
const getNewStyles = (theme: GrafanaTheme2) => {
return {
titleRow: css`
label: TracePageHeaderTitleRow;
align-items: center;
display: flex;
padding: 0 0.5em 0 0.5em;
`,
title: css`
label: TracePageHeaderTitle;
color: inherit;
flex: 1;
font-size: 1.7em;
line-height: 1em;
`,
subtitle: css`
flex: 1;
line-height: 1em;
margin: -0.5em 0 1.5em 0.5em;
margin: -0.5em 0.5em 1.5em 0.5em;
`,
tag: css`
margin: 0 0.5em 0 0;
@ -56,7 +70,7 @@ const getNewStyles = (theme: GrafanaTheme2) => {
position: sticky;
top: 0;
z-index: 5;
padding: 10px 5px 0 5px;
padding: 0.5em 0.25em 0 0.25em;
& > :last-child {
border-bottom: 1px solid ${autoColor(theme, '#ccc')};
}
@ -82,7 +96,7 @@ export function NewTracePageHeader(props: TracePageHeaderEmbedProps) {
const { method, status, url } = getHeaderTags(trace.spans);
const title = (
<h1 className={cx(styles.TracePageHeaderTitle)}>
<h1 className={cx(styles.title)}>
<TraceName traceName={getTraceName(trace.spans)} />
<small>
<span className={styles.divider}>|</span>
@ -102,9 +116,10 @@ export function NewTracePageHeader(props: TracePageHeaderEmbedProps) {
return (
<header className={styles.header}>
<div className={styles.TracePageHeaderTitleRow}>
<div className={styles.titleRow}>
{links && links.length > 0 && <ExternalLinks links={links} className={styles.TracePageHeaderBack} />}
{title}
<TracePageActions traceId={trace.traceID} />
</div>
<div className={styles.subtitle}>

Loading…
Cancel
Save