diff --git a/packages/jaeger-ui/index.html b/packages/jaeger-ui/index.html
index 580592276c..b1e4634d98 100644
--- a/packages/jaeger-ui/index.html
+++ b/packages/jaeger-ui/index.html
@@ -46,6 +46,7 @@
window.staticPath;
window.enableZoomControls;
window.platform;
+ window.isLoggingEnabled;
diff --git a/packages/jaeger-ui/src/api/digma/ActionDispatcher.ts b/packages/jaeger-ui/src/api/digma/ActionDispatcher.ts
index 5fa4513eed..1323d1b63e 100644
--- a/packages/jaeger-ui/src/api/digma/ActionDispatcher.ts
+++ b/packages/jaeger-ui/src/api/digma/ActionDispatcher.ts
@@ -1,6 +1,6 @@
import { ActionListener } from './types';
-export class ActionDispatcher {
+class ActionDispatcher {
private actions: {
[key: string]: ActionListener[];
};
@@ -27,9 +27,11 @@ export class ActionDispatcher {
}
}
- public dispatch(type: string, data?: unknown): void {
+ public dispatch(timeStamp: number, type: string, data?: unknown): void {
if (this.actions[type]) {
- this.actions[type].forEach(fn => fn(data));
+ this.actions[type].forEach(fn => fn(data, timeStamp));
}
}
}
+
+export default ActionDispatcher;
diff --git a/packages/jaeger-ui/src/api/digma/dispatcher.ts b/packages/jaeger-ui/src/api/digma/dispatcher.ts
index 6b3824a156..d14232ee4a 100644
--- a/packages/jaeger-ui/src/api/digma/dispatcher.ts
+++ b/packages/jaeger-ui/src/api/digma/dispatcher.ts
@@ -1,3 +1,5 @@
-import { ActionDispatcher } from './ActionDispatcher';
+import ActionDispatcher from './ActionDispatcher';
-export const dispatcher = new ActionDispatcher();
+const dispatcher = new ActionDispatcher();
+
+export default dispatcher;
diff --git a/packages/jaeger-ui/src/api/digma/index.ts b/packages/jaeger-ui/src/api/digma/index.ts
index 40d8bf80d2..f8541d118d 100644
--- a/packages/jaeger-ui/src/api/digma/index.ts
+++ b/packages/jaeger-ui/src/api/digma/index.ts
@@ -1,43 +1,96 @@
+import logger from '../../logging';
import { isObject } from '../../utils/ts/typeGuards/isObject';
-import { ActionDispatcher } from './ActionDispatcher';
+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';
+const OUTGOING_MESSAGE_ACTION_ID_CONSOLE_STYLE = 'color: blue; font-weight: bold';
+const FAILED_OUTGOING_MESSAGE_ACTION_ID_CONSOLE_STYLE = 'color: red; font-weight: bold';
+const INCOMING_MESSAGE_ACTION_ID_CONSOLE_STYLE = 'color: green; font-weight: bold';
+
export const initializeDigmaMessageListener = (dispatcher: ActionDispatcher) => {
- window.addEventListener('message', e => {
+ const handleDigmaMessage = (e: MessageEvent) => {
if (isDigmaMessageEvent(e)) {
- console.debug('Digma message received: ', e);
+ logger.debug(
+ `Message received: %c${e.data.action}
+%cRaw message: %O`,
+ INCOMING_MESSAGE_ACTION_ID_CONSOLE_STYLE,
+ null,
+ e.data
+ );
updateState(e.data.action, e.data.payload);
- dispatcher.dispatch(e.data.action, e.data.payload);
+ dispatcher.dispatch(e.timeStamp, e.data.action, e.data.payload);
}
- });
+ };
+
+ window.addEventListener('message', handleDigmaMessage);
+
+ return () => {
+ window.removeEventListener('message', handleDigmaMessage);
+ };
};
-export const sendMessage = (message: IDigmaOutgoingMessageData): string | undefined => {
- console.debug('Message to send:', message);
+export const sendMessage = (message: IDigmaOutgoingMessageData): string | undefined => {
+ logger.debug(
+ `Message to sent: ${message.action}
+Raw message: %O`,
+ message
+ );
updateState(message.action, message.payload);
- if (window.sendMessageToVSCode) {
- window.sendMessageToVSCode(message);
- console.debug('Message has been sent to VS Code: ', message);
- } else if (window.cefQuery) {
- return window.cefQuery({
- request: JSON.stringify(message),
- onSuccess(response) {
- console.debug('cefQuery has been successfully sent: %s', response);
- },
- onFailure(errorCode, errorMessage) {
- console.error('Failed to send cefQuery: %d, %s', errorCode, errorMessage);
- },
- });
- } else if (window.parent !== window) {
- window.parent.postMessage(message, '*');
+ switch (window.platform) {
+ case 'VS Code':
+ if (window.sendMessageToVSCode) {
+ window.sendMessageToVSCode(message);
+ logger.debug(
+ `Message has been successfully sent to VS Code: %c${message.action}
+%cRaw message: %O`,
+ OUTGOING_MESSAGE_ACTION_ID_CONSOLE_STYLE,
+ null,
+ message
+ );
+ }
+ break;
+ case 'JetBrains':
+ if (window.cefQuery) {
+ return window.cefQuery({
+ request: JSON.stringify(message),
+ onSuccess(response) {
+ logger.debug(
+ `Message has been successfully handled by JCEF: %c${message.action}
+%cRaw message: %O
+Response: %O`,
+ OUTGOING_MESSAGE_ACTION_ID_CONSOLE_STYLE,
+ null,
+ message,
+ response
+ );
+ },
+ onFailure(errorCode: number, errorMessage: string) {
+ logger.error(
+ `Failed to handle the message by JCEF: %c${message.action}
+%cRaw message: %O
+%cError code: %d
+Error message: %s`,
+ FAILED_OUTGOING_MESSAGE_ACTION_ID_CONSOLE_STYLE,
+ null,
+ errorCode,
+ errorMessage
+ );
+ },
+ });
+ }
+ break;
+ default:
+ if (window.parent !== window) {
+ window.parent.postMessage(message, '*');
+ }
}
return undefined;
diff --git a/packages/jaeger-ui/src/api/digma/types.ts b/packages/jaeger-ui/src/api/digma/types.ts
index f4f9393b28..29084d63fe 100644
--- a/packages/jaeger-ui/src/api/digma/types.ts
+++ b/packages/jaeger-ui/src/api/digma/types.ts
@@ -1,6 +1,6 @@
import { InsightType } from '../../components/common/InsightIcon/types';
-export type ActionListener = (data: unknown) => void;
+export type ActionListener = (data: unknown, timeStamp: number) => void;
export interface IDigmaIncomingMessageData {
type: 'digma';
@@ -8,9 +8,9 @@ export interface IDigmaIncomingMessageData {
payload?: unknown;
}
-export interface IDigmaOutgoingMessageData {
+export interface IDigmaOutgoingMessageData {
action: string;
- payload?: Record;
+ payload?: T;
}
export type DigmaMessageEvent = MessageEvent;
diff --git a/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.css b/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.css
index 55d07e07fe..95ffbc6033 100644
--- a/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.css
+++ b/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.css
@@ -18,6 +18,6 @@ limitations under the License.
border-radius: 4px;
height: 32px;
line-height: 30px;
- margin-right: 1rem;
+ margin: 0 1rem;
padding: 0 8px;
}
diff --git a/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.tsx b/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.tsx
index 1bdeba96c4..c6c41c5ffc 100644
--- a/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.tsx
+++ b/packages/jaeger-ui/src/components/TracePage/TracePageHeader/AltViewOptions.tsx
@@ -14,7 +14,6 @@
import * as React from 'react';
import { Dropdown, Icon, Menu, Button } from 'antd';
-import { Link } from 'react-router-dom';
import './AltViewOptions.css';
import {
@@ -25,7 +24,6 @@ import {
trackJsonView,
trackRawJsonView,
} from './TracePageHeader.track';
-import prefixUrl from '../../../utils/prefix-url';
import { ETraceViewType } from '../types';
type Props = {
@@ -83,24 +81,24 @@ export default function AltViewOptions(props: Props) {
))}
-
Trace JSON
-
+
-
Trace JSON (unadjusted)
-
+
);
diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx
index 5c22411313..8cae86d55c 100644
--- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx
+++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx
@@ -24,7 +24,7 @@ import { formatDuration, ViewedBoundsFunctionType } from './utils';
import SpanTreeOffset from './SpanTreeOffset';
import SpanBar from './SpanBar';
import Ticks from './Ticks';
-import { dispatcher } from '../../../api/digma/dispatcher';
+import dispatcher from '../../../api/digma/dispatcher';
import { actions } from '../../../api/digma/actions';
import { state as globalState } from '../../../api/digma/state';
import { ISpanInsight, SetSpansDataPayload } from '../../../api/digma/types';
diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx
index b4c9c83b5e..48d43eceab 100644
--- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx
+++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx
@@ -25,7 +25,7 @@ import { formatDuration } from '../utils';
import CopyIcon from '../../../common/CopyIcon';
import LabeledList from '../../../common/LabeledList';
import { actions } from '../../../../api/digma/actions';
-import { dispatcher } from '../../../../api/digma/dispatcher';
+import dispatcher from '../../../../api/digma/dispatcher';
import { state as globalState } from '../../../../api/digma/state';
import { ISpanInsight, SetSpansDataPayload } from '../../../../api/digma/types';
import { getInsightTypeInfo, getInsightTypeOrderPriority } from '../../../common/InsightIcon/utils';
@@ -77,7 +77,9 @@ export default class SpanDetail extends React.Component {
scrollBy,
scrollTo,
});
- dispatcher.dispatch(actions.CLEAR);
+ window.sendMessageToDigma({
+ action: actions.CLEAR,
+ });
}
getSpansWithResolvedLocations(trace: Trace) {
@@ -400,7 +401,7 @@ export class TracePageImpl extends React.PureComponent {
showArchiveButton: !isEmbedded && archiveEnabled,
showShortcutsHelp: !isEmbedded,
showStandaloneLink: isEmbedded,
- showViewOptions: !isEmbedded,
+ showViewOptions: true,
toSearch: (locationState && locationState.fromSearch) || null,
trace: data,
updateNextViewRangeTime: this.updateNextViewRangeTime,
diff --git a/packages/jaeger-ui/src/index.jsx b/packages/jaeger-ui/src/index.jsx
index af11e6b8ec..a491b4a5c2 100644
--- a/packages/jaeger-ui/src/index.jsx
+++ b/packages/jaeger-ui/src/index.jsx
@@ -25,7 +25,7 @@ import JaegerUIApp from './components/App';
import { context as trackingContext } from './utils/tracking';
import { cancelMessage, initializeDigmaMessageListener, sendMessage } from './api/digma';
-import { dispatcher } from './api/digma/dispatcher';
+import dispatcher from './api/digma/dispatcher';
// these need to go after the App import
/* eslint-disable import/first */
diff --git a/packages/jaeger-ui/src/logging/Logger.ts b/packages/jaeger-ui/src/logging/Logger.ts
new file mode 100644
index 0000000000..f66d29d6c6
--- /dev/null
+++ b/packages/jaeger-ui/src/logging/Logger.ts
@@ -0,0 +1,87 @@
+import moment from 'moment';
+import { LOG_LEVEL } from './types';
+
+class Logger {
+ private minLogLevel: number;
+ private showTimeStamp: boolean;
+ private showLogLevel: boolean;
+
+ constructor(minLogLevel: LOG_LEVEL, showTimeStamp = true, showLogLevel = true) {
+ this.minLogLevel = minLogLevel;
+ this.showTimeStamp = showTimeStamp;
+ this.showLogLevel = showLogLevel;
+ }
+
+ private getTimestampTag(): string {
+ return moment(new Date()).format('HH:mm:ss');
+ }
+
+ private getLogLevelTag(): string {
+ return LOG_LEVEL[this.minLogLevel];
+ }
+
+ private getFormattedMessage(tags: string[], message: unknown): string {
+ if (this.showLogLevel) {
+ tags.unshift(this.getLogLevelTag());
+ }
+
+ if (this.showTimeStamp) {
+ tags.unshift(this.getTimestampTag());
+ }
+
+ const tagsString = tags.map(x => `[${x}]`).join('');
+
+ return `${tagsString}: ${message as string}`;
+ }
+
+ public setLogLevel(logLevel: LOG_LEVEL): void {
+ this.minLogLevel = logLevel;
+ }
+
+ public log(level: LOG_LEVEL, tags: string[], message?: unknown, ...optionalParams: unknown[]): void {
+ const formattedMessage = this.getFormattedMessage(tags, message);
+
+ if (this.minLogLevel > level) {
+ return;
+ }
+
+ switch (level) {
+ case LOG_LEVEL.DEBUG:
+ // eslint-disable-next-line no-console
+ console.debug(formattedMessage, ...optionalParams);
+ break;
+ case LOG_LEVEL.INFO:
+ // eslint-disable-next-line no-console
+ console.info(formattedMessage, ...optionalParams);
+ break;
+ case LOG_LEVEL.WARN:
+ // eslint-disable-next-line no-console
+ console.warn(formattedMessage, ...optionalParams);
+ break;
+ case LOG_LEVEL.ERROR:
+ // eslint-disable-next-line no-console
+ console.error(formattedMessage, ...optionalParams);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public debug(message?: unknown, ...optionalParams: unknown[]): void {
+ this.log(LOG_LEVEL.DEBUG, [], message, ...optionalParams);
+ }
+
+ public info(message?: unknown, ...optionalParams: unknown[]): void {
+ this.log(LOG_LEVEL.INFO, [], message, ...optionalParams);
+ }
+
+ public warn(message?: unknown, ...optionalParams: unknown[]): void {
+ this.log(LOG_LEVEL.WARN, [], message, ...optionalParams);
+ }
+
+ public error(message?: unknown, ...optionalParams: unknown[]): void {
+ this.log(LOG_LEVEL.ERROR, [], message, ...optionalParams);
+ }
+}
+
+export default Logger;
diff --git a/packages/jaeger-ui/src/logging/index.ts b/packages/jaeger-ui/src/logging/index.ts
new file mode 100644
index 0000000000..7c4574e6ef
--- /dev/null
+++ b/packages/jaeger-ui/src/logging/index.ts
@@ -0,0 +1,6 @@
+import Logger from './Logger';
+import { LOG_LEVEL } from './types';
+
+const logger = new Logger(window.isLoggingEnabled === true ? LOG_LEVEL.DEBUG : LOG_LEVEL.NONE);
+
+export default logger;
diff --git a/packages/jaeger-ui/src/logging/types.ts b/packages/jaeger-ui/src/logging/types.ts
new file mode 100644
index 0000000000..0d36ddc8da
--- /dev/null
+++ b/packages/jaeger-ui/src/logging/types.ts
@@ -0,0 +1,7 @@
+export enum LOG_LEVEL {
+ DEBUG = 0,
+ INFO = 1,
+ WARN = 2,
+ ERROR = 3,
+ NONE = 4,
+}
diff --git a/packages/jaeger-ui/src/platform.ts b/packages/jaeger-ui/src/platform.ts
new file mode 100644
index 0000000000..f8e0ae2751
--- /dev/null
+++ b/packages/jaeger-ui/src/platform.ts
@@ -0,0 +1,12 @@
+import { isString } from './utils/ts/typeGuards/isString';
+
+type Platform = 'JetBrains' | 'VS Code' | 'Web';
+
+const PLATFORMS = ['JetBrains', 'VS Code', 'Web'];
+
+const isPlatform = (platform: unknown): platform is Platform =>
+ isString(platform) && PLATFORMS.includes(platform);
+
+export const getPlatform = (platform: unknown): Platform | null => (isPlatform(platform) ? platform : null);
+
+export const platform = getPlatform(window.platform);
diff --git a/packages/jaeger-ui/typings/custom.d.ts b/packages/jaeger-ui/typings/custom.d.ts
index ba948ed536..86bf133514 100644
--- a/packages/jaeger-ui/typings/custom.d.ts
+++ b/packages/jaeger-ui/typings/custom.d.ts
@@ -40,6 +40,7 @@ declare interface Window {
isUserDefinedJaegerQueryURL?: unknown;
staticPath?: unknown;
enableZoomControls?: unknown;
+ isLoggingEnabled?: boolean;
}
declare const __REACT_APP_GA_DEBUG__: string | undefined;