diff --git a/packages/jaeger-ui/src/components/common/InsightIcon/index.tsx b/packages/jaeger-ui/src/components/common/InsightIcon/index.tsx
new file mode 100644
index 0000000000..58326954b7
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/InsightIcon/index.tsx
@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { IInsightIconProps } from './types';
+import { getInsightImportanceColor, getInsightTypeInfo } from './utils';
+
+export const InsightIcon = (props: IInsightIconProps) => {
+ const insightTypeInfo = getInsightTypeInfo(props.insight.type);
+ return insightTypeInfo ? (
+
+ ) : null;
+};
diff --git a/packages/jaeger-ui/src/components/common/InsightIcon/types.ts b/packages/jaeger-ui/src/components/common/InsightIcon/types.ts
new file mode 100644
index 0000000000..d153e213fc
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/InsightIcon/types.ts
@@ -0,0 +1,28 @@
+export interface IInsightIconProps {
+ insight: {
+ type: InsightType;
+ importance: number;
+ };
+ size?: number;
+}
+
+export enum InsightType {
+ TopErrorFlows = 'TopErrorFlows',
+ SpanDurationChange = 'SpanDurationChange',
+ SpanUsageStatus = 'SpanUsageStatus',
+ HotSpot = 'HotSpot',
+ Errors = 'Errors',
+ SlowEndpoint = 'SlowEndpoint',
+ LowUsage = 'LowUsage',
+ NormalUsage = 'NormalUsage',
+ HighUsage = 'HighUsage',
+ SlowestSpans = 'SlowestSpans',
+ EndpointSpanNPlusOne = 'EndpointSpaNPlusOne',
+ SpanUsages = 'SpanUsages',
+ SpanNPlusOne = 'SpaNPlusOne',
+ SpanEndpointBottleneck = 'SpanEndpointBottleneck',
+ SpanDurations = 'SpanDurations',
+ SpanScaling = 'SpanScaling',
+ SpanScalingRootCause = 'SpanScalingRootCause',
+ SpanDurationBreakdown = 'SpanDurationBreakdown',
+}
diff --git a/packages/jaeger-ui/src/components/common/InsightIcon/utils.ts b/packages/jaeger-ui/src/components/common/InsightIcon/utils.ts
new file mode 100644
index 0000000000..a4ec2b86aa
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/InsightIcon/utils.ts
@@ -0,0 +1,111 @@
+import * as React from 'react';
+import { AlarmClockIcon } from '../icons/AlarmClockIcon';
+import { BottleneckIcon } from '../icons/BottleneckIcon';
+import { MeterHighIcon } from '../icons/MeterHighIcon';
+import { MeterLowIcon } from '../icons/MeterLowIcon';
+import { MeterMediumIcon } from '../icons/MeterMediumIcon';
+import { SQLDatabaseIcon } from '../icons/SQLDatabaseIcon';
+import { ScalesIcon } from '../icons/ScalesIcon';
+import { SineIcon } from '../icons/SineIcon';
+import { SnailIcon } from '../icons/SnailIcon';
+import { SpotIcon } from '../icons/SpotIcon';
+import { WarningCircleIcon } from '../icons/WarningCircleIcon';
+import { IIconProps } from '../icons/types';
+import { InsightType } from './types';
+
+export const getInsightTypeInfo = (
+ type: InsightType
+):
+ | {
+ icon: React.MemoExoticComponent<(props: IIconProps) => React.ReactElement>;
+ label: string;
+ }
+ | undefined => {
+ const insightInfoMap: Record<
+ string,
+ {
+ icon: React.MemoExoticComponent<(props: IIconProps) => React.ReactElement>;
+ label: string;
+ }
+ > = {
+ [InsightType.Errors]: {
+ icon: WarningCircleIcon,
+ label: 'Errors',
+ },
+ [InsightType.HotSpot]: {
+ icon: SpotIcon,
+ label: 'Error Hotspot',
+ },
+ [InsightType.SlowEndpoint]: {
+ icon: SnailIcon,
+ label: 'Slow Endpoint',
+ },
+ [InsightType.LowUsage]: {
+ icon: MeterLowIcon,
+ label: 'Endpoint Low Traffic',
+ },
+ [InsightType.NormalUsage]: {
+ icon: MeterMediumIcon,
+ label: 'Endpoint Normal Level of Traffic',
+ },
+ [InsightType.HighUsage]: {
+ icon: MeterHighIcon,
+ label: 'Endpoint High Traffic',
+ },
+ [InsightType.SlowestSpans]: {
+ icon: BottleneckIcon,
+ label: 'Span Bottleneck',
+ },
+ [InsightType.EndpointSpanNPlusOne]: {
+ icon: SQLDatabaseIcon,
+ label: 'Suspected N-Plus-1',
+ },
+ [InsightType.SpanNPlusOne]: {
+ icon: SQLDatabaseIcon,
+ label: 'Suspected N-Plus-1',
+ },
+ [InsightType.SpanEndpointBottleneck]: {
+ icon: BottleneckIcon,
+ label: 'Bottleneck',
+ },
+ [InsightType.SpanScaling]: {
+ icon: ScalesIcon,
+ label: 'Scaling Issue Found',
+ },
+ [InsightType.SpanScalingRootCause]: {
+ icon: ScalesIcon,
+ label: 'Scaling Issue Root Cause Found',
+ },
+ [InsightType.SpanUsages]: {
+ icon: SineIcon,
+ label: 'Top Usage',
+ },
+ [InsightType.SpanDurations]: {
+ icon: AlarmClockIcon,
+ label: 'Duration',
+ },
+ [InsightType.SpanDurationBreakdown]: {
+ icon: AlarmClockIcon,
+ label: 'Duration Breakdown',
+ },
+ };
+
+ return insightInfoMap[type];
+};
+
+export const getInsightImportanceColor = (importance: number): string | undefined => {
+ if (importance === 0) {
+ return undefined;
+ }
+ if (importance < 3) {
+ return '#f93967';
+ }
+ if (importance < 5) {
+ return '#e06c00';
+ }
+ if (importance < 7) {
+ return '#e8b500';
+ }
+
+ return '#1dc693';
+};
diff --git a/packages/jaeger-ui/src/components/common/icons/AlarmClockIcon.tsx b/packages/jaeger-ui/src/components/common/icons/AlarmClockIcon.tsx
new file mode 100644
index 0000000000..fb49cbfd9b
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/AlarmClockIcon.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const AlarmClockIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const AlarmClockIcon = React.memo(AlarmClockIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/BottleneckIcon.tsx b/packages/jaeger-ui/src/components/common/icons/BottleneckIcon.tsx
new file mode 100644
index 0000000000..3b41f28ce4
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/BottleneckIcon.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const BottleneckIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const BottleneckIcon = React.memo(BottleneckIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/BrokenLinkCircleIcon.tsx b/packages/jaeger-ui/src/components/common/icons/BrokenLinkCircleIcon.tsx
new file mode 100644
index 0000000000..c3f0a3f627
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/BrokenLinkCircleIcon.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const BrokenLinkCircleIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+ );
+};
+
+export const BrokenLinkCircleIcon = React.memo(BrokenLinkCircleIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/CrossedCrosshairCircleIcon.tsx b/packages/jaeger-ui/src/components/common/icons/CrossedCrosshairCircleIcon.tsx
new file mode 100644
index 0000000000..c23dd3011e
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/CrossedCrosshairCircleIcon.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const CrossedCrosshairCircleIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+
+ );
+};
+
+export const CrossedCrosshairCircleIcon = React.memo(CrossedCrosshairCircleIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/CrosshairIcon.tsx b/packages/jaeger-ui/src/components/common/icons/CrosshairIcon.tsx
new file mode 100644
index 0000000000..c7a6839910
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/CrosshairIcon.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const CrosshairIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const CrosshairIcon = React.memo(CrosshairIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/LightBulbIcon.tsx b/packages/jaeger-ui/src/components/common/icons/LightBulbIcon.tsx
new file mode 100644
index 0000000000..4bbb889beb
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/LightBulbIcon.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const LightBulbIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+ );
+};
+
+export const LightBulbIcon = React.memo(LightBulbIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/MeterHighIcon.tsx b/packages/jaeger-ui/src/components/common/icons/MeterHighIcon.tsx
new file mode 100644
index 0000000000..5e90f7503e
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/MeterHighIcon.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const MeterHighIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+ );
+};
+
+export const MeterHighIcon = React.memo(MeterHighIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/MeterLowIcon.tsx b/packages/jaeger-ui/src/components/common/icons/MeterLowIcon.tsx
new file mode 100644
index 0000000000..a54d05f59f
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/MeterLowIcon.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const MeterLowIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+ );
+};
+
+export const MeterLowIcon = React.memo(MeterLowIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/MeterMediumIcon.tsx b/packages/jaeger-ui/src/components/common/icons/MeterMediumIcon.tsx
new file mode 100644
index 0000000000..7b834d1f9e
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/MeterMediumIcon.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const MeterMediumIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+ );
+};
+
+export const MeterMediumIcon = React.memo(MeterMediumIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/SQLDatabaseIcon.tsx b/packages/jaeger-ui/src/components/common/icons/SQLDatabaseIcon.tsx
new file mode 100644
index 0000000000..de362b7ccf
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/SQLDatabaseIcon.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const SQLDatabaseIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const SQLDatabaseIcon = React.memo(SQLDatabaseIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/ScalesIcon.tsx b/packages/jaeger-ui/src/components/common/icons/ScalesIcon.tsx
new file mode 100644
index 0000000000..2dc643798e
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/ScalesIcon.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const ScalesIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const ScalesIcon = React.memo(ScalesIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/SineIcon.tsx b/packages/jaeger-ui/src/components/common/icons/SineIcon.tsx
new file mode 100644
index 0000000000..03a3c7a4cb
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/SineIcon.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const SineIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const SineIcon = React.memo(SineIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/SlackLogoIcon.tsx b/packages/jaeger-ui/src/components/common/icons/SlackLogoIcon.tsx
new file mode 100644
index 0000000000..0b98b3b60c
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/SlackLogoIcon.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const SlackLogoIconComponent = (props: IIconProps) => {
+ const { size } = useIconProps(props);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export const SlackLogoIcon = React.memo(SlackLogoIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/SnailIcon.tsx b/packages/jaeger-ui/src/components/common/icons/SnailIcon.tsx
new file mode 100644
index 0000000000..39f372f032
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/SnailIcon.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const SnailIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+
+ );
+};
+
+export const SnailIcon = React.memo(SnailIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/SpotIcon.tsx b/packages/jaeger-ui/src/components/common/icons/SpotIcon.tsx
new file mode 100644
index 0000000000..201e7e0d5a
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/SpotIcon.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const SpotIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const SpotIcon = React.memo(SpotIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/WarningCircleIcon.tsx b/packages/jaeger-ui/src/components/common/icons/WarningCircleIcon.tsx
new file mode 100644
index 0000000000..3f75c2a1ca
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/WarningCircleIcon.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import { useIconProps } from './hooks';
+import { IIconProps } from './types';
+
+const WarningCircleIconComponent = (props: IIconProps) => {
+ const { size, color } = useIconProps(props);
+
+ return (
+
+
+
+ );
+};
+
+export const WarningCircleIcon = React.memo(WarningCircleIconComponent);
diff --git a/packages/jaeger-ui/src/components/common/icons/hooks.ts b/packages/jaeger-ui/src/components/common/icons/hooks.ts
new file mode 100644
index 0000000000..321bbcb8ac
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/hooks.ts
@@ -0,0 +1,11 @@
+import { useMemo } from 'react';
+import { IIconProps } from './types';
+
+const DEFAULT_ICON_COLOR = '#828797';
+export const DEFAULT_ICON_SIZE = 12;
+
+export const useIconProps = (props: IIconProps): IIconProps => {
+ const color: string = useMemo(() => props.color || DEFAULT_ICON_COLOR, [props.color]);
+ const size: number = useMemo(() => props.size || DEFAULT_ICON_SIZE, [props.size]);
+ return { color, size };
+};
diff --git a/packages/jaeger-ui/src/components/common/icons/types.ts b/packages/jaeger-ui/src/components/common/icons/types.ts
new file mode 100644
index 0000000000..0d3c127b02
--- /dev/null
+++ b/packages/jaeger-ui/src/components/common/icons/types.ts
@@ -0,0 +1,5 @@
+export interface IIconProps {
+ color?: string;
+ size?: number;
+ className?: string;
+}
diff --git a/packages/jaeger-ui/typings/custom.d.ts b/packages/jaeger-ui/typings/custom.d.ts
index 292a3ff98b..17340d95cf 100644
--- a/packages/jaeger-ui/typings/custom.d.ts
+++ b/packages/jaeger-ui/typings/custom.d.ts
@@ -37,6 +37,7 @@ declare interface Window {
apiBaseUrl?: unknown;
initialRoutePath?: unknown;
embeddedMode?: unknown;
+ isUserDefinedJaegerQueryURL?: unknown;
staticPath?: unknown;
}