Skip to content

Commit

Permalink
Add error icon to errored services in trace list view (#927)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jono Yan committed Apr 13, 2022
1 parent 5d05a79 commit 60f1bc8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,15 @@ limitations under the License.
.ResultItem--serviceTag {
border-left-width: 15px;
margin: 0;
display: flex;
align-items: center;
}

.ResultItem--errorIcon {
background: #db2828;
border-radius: 6.5px;
color: #fff;
font-size: 0.85em;
margin-right: 0.25rem;
padding: 1px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@ it('<ResultItem /> should not render any ServiceTags when there are no services'
const serviceTags = wrapper.find(`[data-test="${markers.SERVICE_TAGS}"]`).find(Tag);
expect(serviceTags).toHaveLength(0);
});

it('<ResultItem /> should render error icon on ServiceTags that have an error tag', () => {
trace.spans[0].tags.push({ key: 'error', value: true });
const wrapper = shallow(<ResultItem trace={trace} durationPercent={50} linkTo="" />);
const errorServiceTags = wrapper.find('.ResultItem--errorIcon').getElements();
expect(errorServiceTags).toHaveLength(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { Link } from 'react-router-dom';
import { sortBy } from 'lodash';
import moment from 'moment';

import IoAlert from 'react-icons/lib/io/alert';

import { trackConversions, EAltViewActions } from './index.track';
import * as markers from './ResultItem.markers';
import ResultItemTitle from './ResultItemTitle';
Expand All @@ -38,10 +40,43 @@ type Props = {
disableComparision: boolean;
};

type State = {
erroredServices: Set<string>;
numSpans: number;
numErredSpans: number;
timeStr: string;
fromNow: string | boolean;
};

const isErrorTag = ({ key, value }: KeyValuePair) => key === 'error' && (value === true || value === 'true');
const trackTraceConversions = () => trackConversions(EAltViewActions.Traces);

export default class ResultItem extends React.PureComponent<Props> {
export default class ResultItem extends React.PureComponent<Props, State> {
constructor(props: Props, state: State) {
super(props, state);
const { startTime, spans } = props.trace;

const mDate = moment(startTime / 1000);

const erroredServices: Set<string> = new Set<string>();

const numErredSpans = spans.filter(sp => {
const hasError = sp.tags.some(isErrorTag);
if (hasError) {
erroredServices.add(sp.process.serviceName);
}
return hasError;
}).length;

this.state = {
numSpans: spans.length,
timeStr: mDate.format('h:mm:ss a'),
fromNow: mDate.fromNow(),
numErredSpans,
erroredServices,
};
}

render() {
const {
disableComparision,
Expand All @@ -51,12 +86,7 @@ export default class ResultItem extends React.PureComponent<Props> {
toggleComparison,
trace,
} = this.props;
const { duration, services, startTime, spans, traceName, traceID } = trace;
const mDate = moment(startTime / 1000);
const timeStr = mDate.format('h:mm:ss a');
const fromNow = mDate.fromNow();
const numSpans = spans.length;
const numErredSpans = spans.filter(sp => sp.tags.some(isErrorTag)).length;
const { duration, services, startTime, traceName, traceID } = trace;
return (
<div className="ResultItem" onClick={trackTraceConversions} role="button">
<ResultItemTitle
Expand All @@ -73,11 +103,11 @@ export default class ResultItem extends React.PureComponent<Props> {
<Row>
<Col span={4} className="ub-p2">
<Tag className="ub-m1" data-test={markers.NUM_SPANS}>
{numSpans} Span{numSpans > 1 && 's'}
{this.state.numSpans} Span{this.state.numSpans > 1 && 's'}
</Tag>
{Boolean(numErredSpans) && (
{Boolean(this.state.numErredSpans) && (
<Tag className="ub-m1" color="red">
{numErredSpans} Error{numErredSpans > 1 && 's'}
{this.state.numErredSpans} Error{this.state.numErredSpans > 1 && 's'}
</Tag>
)}
</Col>
Expand All @@ -91,6 +121,9 @@ export default class ResultItem extends React.PureComponent<Props> {
className="ResultItem--serviceTag"
style={{ borderLeftColor: colorGenerator.getColorByKey(name) }}
>
{this.state.erroredServices.has(name) && (
<IoAlert className="ResultItem--errorIcon" />
)}
{name} ({count})
</Tag>
</li>
Expand All @@ -101,9 +134,9 @@ export default class ResultItem extends React.PureComponent<Props> {
<Col span={4} className="ub-p3 ub-tx-right-align">
{formatRelativeDate(startTime / 1000)}
<Divider type="vertical" />
{timeStr.slice(0, -3)}&nbsp;{timeStr.slice(-2)}
{this.state.timeStr.slice(0, -3)}&nbsp;{this.state.timeStr.slice(-2)}
<br />
<small>{fromNow}</small>
<small>{this.state.fromNow}</small>
</Col>
</Row>
</Link>
Expand Down

0 comments on commit 60f1bc8

Please sign in to comment.