Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = {
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', 'json', '.tsx'],
extensions: ['.js', '.jsx', 'json', '.tsx', ".ts"],
},
},
},
Expand Down
24 changes: 4 additions & 20 deletions packages/jaeger-ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,10 @@
window.global = {};
</script>
<script>
// Variables for injection by VS Code extension
var VS_CODE_SETTINGS = {
apiBaseUrl: "",
startPath: "",
staticPath: "",
embeddedMode: false,
};

// Store list of trace spans with resolved location globally
var spansWithResolvedLocation = {};
var pendingOperationsCount = 0;

window.addEventListener("message", (e) => {
const message = e.data;
switch (message.command) {
case "setSpansWithResolvedLocation":
spansWithResolvedLocation = message.data;
pendingOperationsCount--;
}
});
window.apiBaseUrl;
window.initialRoutePath;
window.embeddedMode;
window.staticPath;
</script>
</head>
<body>
Expand Down
35 changes: 35 additions & 0 deletions packages/jaeger-ui/src/api/digma/ActionDispatcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ActionListener } from "./types";

export class ActionDispatcher {
private actions: {
[key: string]: ActionListener[];
};

constructor() {
this.actions = {};
}

public addActionListener(type: string, listener: ActionListener) {
if (!this.actions[type]) {
this.actions[type] = [listener];
} else {
this.actions[type].push(listener);
}
}

public removeActionListener(type: string, listener: ActionListener) {
if (this.actions[type]) {
this.actions[type] = this.actions[type].filter((x) => x !== listener);
}

if (this.actions[type].length === 0) {
delete this.actions[type];
}
}

public dispatch(type: string, data?: unknown): void {
if (this.actions[type]) {
this.actions[type].forEach(fn => fn(data));
}
}
}
5 changes: 5 additions & 0 deletions packages/jaeger-ui/src/api/digma/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const actions = {
GO_TO_SPAN: "GO_TO_SPAN",
GET_SPANS_WITH_RESOLVED_LOCATION: "GET_SPANS_WITH_RESOLVED_LOCATION",
SET_SPANS_WITH_RESOLVED_LOCATION:"SET_SPANS_WITH_RESOLVED_LOCATION"
}
3 changes: 3 additions & 0 deletions packages/jaeger-ui/src/api/digma/dispatcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ActionDispatcher } from "./ActionDispatcher";

export const dispatcher = new ActionDispatcher();
58 changes: 58 additions & 0 deletions packages/jaeger-ui/src/api/digma/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { isObject } from "../../utils/ts/typeGuards/isObject";
import { ActionDispatcher } from "./ActionDispatcher";
import { updateState } from "./state";
import { DigmaMessageEvent, IDigmaOutgoingMessageData } from "./types";

const isDigmaMessageEvent = (e: MessageEvent): e is DigmaMessageEvent =>
isObject(e.data) && e.data.type === "digma";

export const initializeDigmaMessageListener = (
dispatcher: ActionDispatcher
) => {
window.addEventListener("message", e => {
if (isDigmaMessageEvent(e)) {
console.info("Digma message received: ", e);

updateState(e.data.action, e.data.payload);

dispatcher.dispatch(e.data.action, e.data.payload);
}
});
};

export const sendMessage = (
message: IDigmaOutgoingMessageData
): string | undefined => {
console.info("Message to send:", message);

updateState(message.action, message.payload);

if (window.sendMessageToVSCode) {
window.sendMessageToVSCode(message);
console.info("Message has been sent to VS Code: ", message);
}

if (window.cefQuery) {
return window.cefQuery({
request: JSON.stringify(message),
onSuccess (response) {
console.info("cefQuery has been successfully sent: %s", response);
},
onFailure (errorCode, errorMessage) {
console.error(
"Failed to send cefQuery: %d, %s",
errorCode,
errorMessage
);
}
});
}

return undefined;
};

export const cancelMessage = (messageId: string) => {
if (window.cefQueryCancel) {
window.cefQueryCancel(messageId);
}
};
24 changes: 24 additions & 0 deletions packages/jaeger-ui/src/api/digma/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { actions } from "./actions";
import { SetSpansWithResolvedLocationsData } from "./types";

export const state: {
pendingOperationsCount: number,
spansWithResolvedLocation: SetSpansWithResolvedLocationsData
} = {
pendingOperationsCount: 0,
spansWithResolvedLocation: {}
};

export const updateState = (action: string, payload: any) => {
switch(action) {
case (actions.GET_SPANS_WITH_RESOLVED_LOCATION):
state.pendingOperationsCount++;
break;
case (actions.SET_SPANS_WITH_RESOLVED_LOCATION):
state.spansWithResolvedLocation = payload;
state.pendingOperationsCount--;
break;
default:
}
}

20 changes: 20 additions & 0 deletions packages/jaeger-ui/src/api/digma/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export type ActionListener = (data: unknown) => void;

export interface IDigmaIncomingMessageData {
type: "digma";
action: string;
payload?: unknown;
}

export interface IDigmaOutgoingMessageData {
action: string;
payload?: Record<string, unknown>;
}

export type DigmaMessageEvent = MessageEvent<IDigmaIncomingMessageData>;

interface ISpanInfo {
importance?: number
}

export type SetSpansWithResolvedLocationsData = Record<string, ISpanInfo>
3 changes: 2 additions & 1 deletion packages/jaeger-ui/src/api/jaeger.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import moment from 'moment';
import queryString from 'query-string';

import prefixUrl from '../utils/prefix-url';
import { isString } from '../utils/ts/typeGuards/isString';

// export for tests
export function getMessageFromError(errData, status) {
Expand Down Expand Up @@ -76,7 +77,7 @@ function getJSON(url, options = {}) {
});
}

export const DEFAULT_API_ROOT = window.VS_CODE_SETTINGS.apiBaseUrl ? `${window.VS_CODE_SETTINGS.apiBaseUrl}/api/` : prefixUrl('/api/');
export const DEFAULT_API_ROOT = isString(window.apiBaseUrl) ? `${window.apiBaseUrl}/api/` : prefixUrl('/api/');
export const ANALYTICS_ROOT = prefixUrl('/analytics/');
export const DEFAULT_DEPENDENCY_LOOKBACK = moment.duration(1, 'weeks').asMilliseconds();

Expand Down
9 changes: 5 additions & 4 deletions packages/jaeger-ui/src/components/App/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import JaegerAPI, { DEFAULT_API_ROOT } from '../../api/jaeger';
import configureStore from '../../utils/configure-store';
import processScripts from '../../utils/config/process-scripts';
import prefixUrl from '../../utils/prefix-url';
import { isString } from '../../utils/ts/typeGuards/isString';

import '../common/vars.css';
import '../common/utils.css';
Expand All @@ -54,10 +55,10 @@ export default class JaegerUIApp extends Component {
}

render() {
// Navigate to URL provided by VS Code
if (window.VS_CODE_SETTINGS.startPath) {
const urlToNavigate = window.VS_CODE_SETTINGS.startPath;
window.VS_CODE_SETTINGS.startPath = "";
// Navigate to URL provided on app start
if (isString(window.initialRoutePath) && window.initialRoutePath) {
const urlToNavigate = window.initialRoutePath;
window.initialRoutePath = "";
history.push(urlToNavigate);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ import { Row, Col, Button, Alert } from 'antd';
import './index.css';
import { MonitorEmptyStateConfig } from '../../../types/config';
import { getConfigValue } from '../../../utils/config/get-config';
import { getStaticAssetPath } from '../../../utils/getStaticAssetPath';
import monitorImg from './media/monitor.png';

const monitorImgUrl = getStaticAssetPath(monitorImg);

export default class MonitorATMEmptyState extends React.PureComponent {
config: MonitorEmptyStateConfig;

Expand All @@ -29,8 +32,6 @@ export default class MonitorATMEmptyState extends React.PureComponent {
}

render() {
const monitorImgUrl = window.VS_CODE_SETTINGS.staticPath ? new URL(monitorImg, window.VS_CODE_SETTINGS.staticPath).href : monitorImg;

return (
<Col>
<Row justify="center">
Expand Down
8 changes: 5 additions & 3 deletions packages/jaeger-ui/src/components/SearchTracePage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ import { actions as traceDiffActions } from '../TraceDiff/duck';
import { fetchedState } from '../../constants';
import { sortTraces } from '../../model/search';
import { stripEmbeddedState } from '../../utils/embedded-url';
import { getStaticAssetPath } from '../../utils/getStaticAssetPath';
import FileLoader from './FileLoader';

import './index.css';
import JaegerLogo from '../../img/jaeger-logo.svg';

const TabPane = Tabs.TabPane;

const logoUrl = getStaticAssetPath(JaegerLogo);

// Sanitize query params to filter out ones provided by VS Code
const sanitizeQueryParams = (params) => {
const sanitizeQueryParams = params => {
const VS_CODE_PARAMS = [
"id",
"origin",
Expand All @@ -55,7 +58,7 @@ const sanitizeQueryParams = (params) => {

const filteredParams = {};

Object.keys(params).forEach((key) => {
Object.keys(params).forEach(key => {
if (!VS_CODE_PARAMS.includes(key)) {
filteredParams[key] = params[key]
}
Expand Down Expand Up @@ -121,7 +124,6 @@ export class SearchTracePageImpl extends Component {
const hasTraceResults = traceResults && traceResults.length > 0;
const showErrors = errors && !loadingTraces;
const showLogo = isHomepage && !hasTraceResults && !loadingTraces && !errors;
const logoUrl = window.VS_CODE_SETTINGS.staticPath ? new URL(JaegerLogo, window.VS_CODE_SETTINGS.staticPath).href : JaegerLogo;
return (
<Row className="SearchTracePage--row">
{!embedded && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ import { formatDuration, ViewedBoundsFunctionType } from './utils';
import SpanTreeOffset from './SpanTreeOffset';
import SpanBar from './SpanBar';
import Ticks from './Ticks';

import { dispatcher } from '../../../api/digma/dispatcher';
import { actions } from '../../../api/digma/actions';
import { state as globalState } from '../../../api/digma/state';
import { getStaticAssetPath } from '../../../utils/getStaticAssetPath';
import { TNil } from '../../../types';
import { Span } from '../../../types/trace';

import codeIcon from '../../../img/code.svg';

import './SpanBarRow.css';

type SpanInfo = {
importance?: number
}
import { SetSpansWithResolvedLocationsData } from '../../../api/digma/types';

type SpanBarRowProps = {
className?: string;
Expand Down Expand Up @@ -72,6 +72,8 @@ type SpanBarRowState = {
importance?: number;
}

const codeIconUrl = getStaticAssetPath(codeIcon);

/**
* This was originally a stateless function, but changing to a PureComponent
* reduced the render time of expanding a span row detail by ~50%. This is
Expand All @@ -83,7 +85,7 @@ type SpanBarRowState = {
export default class SpanBarRow extends React.PureComponent<SpanBarRowProps, SpanBarRowState> {
constructor(props: SpanBarRowProps) {
super(props);
const span = window.spansWithResolvedLocation[props.span.spanID];
const span = globalState.spansWithResolvedLocation[props.span.spanID];
this.state = {
hasResolvedLocation: Boolean(span),
importance: span && span.importance,
Expand All @@ -103,23 +105,20 @@ export default class SpanBarRow extends React.PureComponent<SpanBarRowProps, Spa
this.props.onChildrenToggled(this.props.span.spanID);
};

updateSpanInfo = (e: { data: { command: string, data: Record<string, SpanInfo> }}) => {
const message = e.data;
if (message.command === "setSpansWithResolvedLocation") {
const span = message.data[this.props.span.spanID];
updateSpanInfo = (data: unknown) => {
const span = (data as SetSpansWithResolvedLocationsData)[this.props.span.spanID];
this.setState({
hasResolvedLocation: Boolean(span),
importance: span && span.importance
});
}
}

componentDidMount(): void {
window.addEventListener('message', this.updateSpanInfo);
dispatcher.addActionListener(actions.SET_SPANS_WITH_RESOLVED_LOCATION, this.updateSpanInfo);
}

componentWillUnmount(): void {
window.removeEventListener('message', this.updateSpanInfo);
dispatcher.removeActionListener(actions.SET_SPANS_WITH_RESOLVED_LOCATION, this.updateSpanInfo);
}

getImportanceAltText(importance?: number): string {
Expand Down Expand Up @@ -172,7 +171,6 @@ export default class SpanBarRow extends React.PureComponent<SpanBarRowProps, Spa
hintSide = 'right';
}

const codeIconUrl = window.VS_CODE_SETTINGS.staticPath ? new URL(codeIcon, window.VS_CODE_SETTINGS.staticPath).href : codeIcon;

return (
<TimelineRow
Expand Down Expand Up @@ -226,7 +224,7 @@ export default class SpanBarRow extends React.PureComponent<SpanBarRowProps, Spa
typeof this.state.importance === "number" && [1,2].includes(this.state.importance) && this.state.hasResolvedLocation &&
<span title={this.getImportanceAltText(this.state.importance)} className="importance-marker">❗️</span>
}
{this.state.hasResolvedLocation && <img className="code-location-icon" src={codeIconUrl} />}
{this.state.hasResolvedLocation && <img alt="Code location available" className="code-location-icon" src={codeIconUrl} />}
</a>
{span.references && span.references.length > 1 && (
<ReferencesButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ describe('<SpanDetail>', () => {
props.logsToggle.mockReset();
props.logItemToggle.mockReset();
wrapper = shallow(<SpanDetail {...props} />);
jest.spyOn(window, 'sendMessageToDigma').mockImplementation(jest.fn());
});

it('renders without exploding', () => {
Expand Down
Loading