Skip to content

Commit

Permalink
Improve trace page title with data and unique emoji (fixes #2256) (#2275
Browse files Browse the repository at this point in the history
)

## Which problem is this PR solving?
- This solves #2256.

## Description of the changes
- Trace page titles are changed to `<unique emoji> <short trace id>:
<operation name> (<service name>) — Jaeger UI`.

## How was this change tested?
- Page titles are checked in tests.

## Checklist
- [x] I have read
https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md
- [x] I have signed all commits
- [ ] I have added unit tests for the new functionality
- [x] I have run lint and test steps successfully
  - for `jaeger`: `make lint test`
  - for `jaeger-ui`: `yarn lint` and `yarn test`

---------

Signed-off-by: Anthony Ramine <[email protected]>
  • Loading branch information
nox authored Apr 30, 2024
1 parent c4402ca commit b5e61f5
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import _values from 'lodash/values';
import { IoArrowBack, IoFileTrayFull, IoChevronForward } from 'react-icons/io5';
import { Link } from 'react-router-dom';

import { Helmet } from 'react-helmet';
import AltViewOptions from './AltViewOptions';
import KeyboardShortcutsHelp from './KeyboardShortcutsHelp';
import SpanGraph from './SpanGraph';
Expand All @@ -28,7 +29,6 @@ import { TUpdateViewRangeTimeFunction, IViewRange, ViewRangeTimeUpdate, ETraceVi
import LabeledList from '../../common/LabeledList';
import NewWindowIcon from '../../common/NewWindowIcon';
import TraceName from '../../common/TraceName';
import { getTraceName } from '../../../model/trace-viewer';
import { TNil } from '../../../types';
import { Trace } from '../../../types/trace';
import { formatDatetime, formatDuration } from '../../../utils/date';
Expand Down Expand Up @@ -149,15 +149,17 @@ export function TracePageHeaderFn(props: TracePageHeaderEmbedProps & { forwarded
return { ...rest, value: renderer(trace) };
});

const traceShortID = trace.traceID.slice(0, 7);

const title = (
<h1 className={`TracePageHeader--title ${canCollapse ? 'is-collapsible' : ''}`}>
<TraceName traceName={getTraceName(trace.spans)} />{' '}
<small className="u-tx-muted">{trace.traceID.slice(0, 7)}</small>
<TraceName traceName={trace.traceName} /> <small className="u-tx-muted">{traceShortID}</small>
</h1>
);

return (
<header className="TracePageHeader">
<Helmet title={`${trace.traceEmoji} ${traceShortID}: ${trace.tracePageTitle} — Jaeger UI`} />
<div className="TracePageHeader--titleRow">
{toSearch && (
<Link className="TracePageHeader--back" to={toSearch}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { _getTraceNameImpl as getTraceName } from './trace-viewer';
import { _getTracePageHeaderPartsImpl as getTracePageHeaderParts } from './trace-viewer';

describe('getTraceName', () => {
describe('getTracePageHeaderParts', () => {
const firstSpanId = 'firstSpanId';
const secondSpanId = 'secondSpanId';
const thirdSpanId = 'thirdSpanId';
Expand Down Expand Up @@ -220,25 +220,29 @@ describe('getTraceName', () => {
},
];

const fullTraceName = `${serviceName}: ${operationName}`;
const fullTracePageHeaderParts = { serviceName, operationName };

it('returns an empty string if given spans with no root among them', () => {
expect(getTraceName(spansWithNoRoots)).toEqual('');
expect(getTracePageHeaderParts(spansWithNoRoots)).toEqual(null);
});

it('returns an id of root span with the earliest startTime', () => {
expect(getTraceName(spansWithMultipleRootsDifferentByStartTime)).toEqual(fullTraceName);
expect(getTracePageHeaderParts(spansWithMultipleRootsDifferentByStartTime)).toEqual(
fullTracePageHeaderParts
);
});

it('returns an id of root span without any refs', () => {
expect(getTraceName(spansWithMultipleRootsWithOneWithoutRefs)).toEqual(fullTraceName);
expect(getTracePageHeaderParts(spansWithMultipleRootsWithOneWithoutRefs)).toEqual(
fullTracePageHeaderParts
);
});

it('returns an id of root span with remote ref', () => {
expect(getTraceName(spansWithOneRootWithRemoteRef)).toEqual(fullTraceName);
expect(getTracePageHeaderParts(spansWithOneRootWithRemoteRef)).toEqual(fullTracePageHeaderParts);
});

it('returns an id of root span with no refs', () => {
expect(getTraceName(spansWithOneRootWithNoRefs)).toEqual(fullTraceName);
expect(getTracePageHeaderParts(spansWithOneRootWithNoRefs)).toEqual(fullTracePageHeaderParts);
});
});
57 changes: 54 additions & 3 deletions packages/jaeger-ui/src/model/trace-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import _memoize from 'lodash/memoize';

import { Span } from '../types/trace';

export function _getTraceNameImpl(spans: Span[]) {
export type TracePageHeaderParts = {
serviceName: string;
operationName: string;
};

export function _getTracePageHeaderPartsImpl(spans: Span[]): TracePageHeaderParts | null {
// Use a span with no references to another span in given array
// prefering the span with the fewest references
// using start time as a tie breaker
Expand Down Expand Up @@ -44,10 +49,56 @@ export function _getTraceNameImpl(spans: Span[]) {
candidateSpan = spans[i];
}
}
return candidateSpan ? `${candidateSpan.process.serviceName}: ${candidateSpan.operationName}` : '';

if (!candidateSpan) {
return null;
}

return {
serviceName: candidateSpan.process.serviceName,
operationName: candidateSpan.operationName,
};
}

export const getTraceName = _memoize(_getTraceNameImpl, (spans: Span[]) => {
export const getTracePageHeaderParts = _memoize(_getTracePageHeaderPartsImpl, (spans: Span[]) => {
if (!spans.length) return 0;
return spans[0].traceID;
});

export function getTraceName(spans: Span[]): string {
const parts = getTracePageHeaderParts(spans);

return parts ? `${parts.serviceName}: ${parts.operationName}` : '';
}

export function getTracePageTitle(spans: Span[]): string {
const parts = getTracePageHeaderParts(spans);

return parts ? `${parts.operationName} (${parts.serviceName})` : '';
}

export function getTraceEmoji(spans: Span[]): string {
if (!spans.length) return '';

// prettier-ignore
const emojiSet = [
'🐶', '🐱', '🐭', '🦊', '🐨', '🐮', '🐷', '🐸', '🐵', '🐔', '🐤', '🦆',
'🦉', '🐝', '🦋', '🐢', '🦀', '🐳', '🐊', '🦒', '🪶', '🦩', '🐉', '🍄',
'🌸', '🌜', '🔥', '🌪️', '💧', '🍏', '🍊', '🍉', '🍒', '🥦', '🌽', '🍠',
'🥐', '🥖', '🥚', '🧀', '🍗', '🍟', '🍕', '🍣', '🍤', '🍙', '🍪', '⚽️',
'🏀', '🥎', '🎹', '🎲', '🎮', '🧩', '🚗', '🚲', '🚂', '⛺️', '📞', '⏰',
'🔌', '💎', '🪚', '🧲', '🧬', '🎀', '📬', '📘', '🩷', '🎵', '🏴', '🚩',
];

const traceID = spans[0].traceID;
let index = 0;

if (traceID) {
for (let i = 0; i < traceID.length; i++) {
const hexChar = traceID.slice(i, i + 1);
index = (index * 16 + parseInt(hexChar, 16)) % emojiSet.length;
}
}

return emojiSet[index];
}
6 changes: 5 additions & 1 deletion packages/jaeger-ui/src/model/transform-trace-data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import _isEqual from 'lodash/isEqual';

import { getTraceSpanIdsAsTree, TREE_ROOT_ID } from '../selectors/trace';
import { getConfigValue } from '../utils/config/get-config';
import { getTraceName } from './trace-viewer';
import { getTraceEmoji, getTraceName, getTracePageTitle } from './trace-viewer';
import { KeyValuePair, Span, SpanData, Trace, TraceData } from '../types/trace';
import TreeNode from '../utils/TreeNode';

Expand Down Expand Up @@ -170,12 +170,16 @@ export default function transformTraceData(data: TraceData & { spans: SpanData[]
spans.push(span);
});
const traceName = getTraceName(spans);
const tracePageTitle = getTracePageTitle(spans);
const traceEmoji = getTraceEmoji(spans);
const services = Object.keys(svcCounts).map(name => ({ name, numberOfSpans: svcCounts[name] }));
return {
services,
spans,
traceID,
traceName,
tracePageTitle,
traceEmoji,
// TODO why not store `tree` here for easier access to tree structure?
// ...
// Can't use spread operator for intersection types
Expand Down
2 changes: 2 additions & 0 deletions packages/jaeger-ui/src/types/trace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ export type Trace = TraceData & {
spans: Span[];
startTime: number;
traceName: string;
tracePageTitle: string;
traceEmoji: string;
services: { name: string; numberOfSpans: number }[];
};

Expand Down

0 comments on commit b5e61f5

Please sign in to comment.