diff --git a/src/components/Insights/InsightList/index.tsx b/src/components/Insights/InsightList/index.tsx
index 65b346ef7..82a791264 100644
--- a/src/components/Insights/InsightList/index.tsx
+++ b/src/components/Insights/InsightList/index.tsx
@@ -26,6 +26,7 @@ import { ScalingIssueInsight } from "../ScalingIssueInsight";
import { SessionInViewInsight } from "../SessionInViewInsight";
import { SlowEndpointInsight } from "../SlowEndpointInsight";
import { SpanBottleneckInsight } from "../SpanBottleneckInsight";
+import { SpanNexusInsight } from "../SpanNexusInsight";
import { TopUsageInsight } from "../TopUsageInsight";
import { TrafficInsight } from "../TrafficInsight";
import { actions } from "../actions";
@@ -50,6 +51,7 @@ import {
isSpanEndpointBottleneckInsight,
isSpanInsight,
isSpanNPlusOneInsight,
+ isSpanNexusInsight,
isSpanScalingBadlyInsight,
isSpanScalingInsufficientDataInsight,
isSpanScalingWellInsight,
@@ -561,6 +563,17 @@ const renderInsightCard = (
/>
);
}
+
+ if (isSpanNexusInsight(insight)) {
+ return (
+
+ );
+ }
};
export const InsightList = (props: InsightListProps) => {
diff --git a/src/components/Insights/Insights.stories.tsx b/src/components/Insights/Insights.stories.tsx
index aeccb97d9..d0f5b9a3c 100644
--- a/src/components/Insights/Insights.stories.tsx
+++ b/src/components/Insights/Insights.stories.tsx
@@ -4,6 +4,7 @@ import { InsightType } from "../../types";
import { mockedBottleneckInsight } from "./BottleneckInsight/mockData";
import { mockedEndpointNPlusOneInsight } from "./EndpointNPlusOneInsight/mockData";
import { mockedHighNumberOfQueriesInsight } from "./HighNumberOfQueriesInsight/mockData";
+import { mockedSpanNexusInsight } from "./SpanNexusInsight/mockData";
import {
CodeObjectErrorsInsight,
ComponentType,
@@ -707,7 +708,8 @@ export const Default: Story = {
},
mockedEndpointNPlusOneInsight,
mockedBottleneckInsight,
- mockedHighNumberOfQueriesInsight
+ mockedHighNumberOfQueriesInsight,
+ mockedSpanNexusInsight
]
}
}
diff --git a/src/components/Insights/SpanNexusInsight/SpanNexusInsight.stories.tsx b/src/components/Insights/SpanNexusInsight/SpanNexusInsight.stories.tsx
new file mode 100644
index 000000000..82cc28a9d
--- /dev/null
+++ b/src/components/Insights/SpanNexusInsight/SpanNexusInsight.stories.tsx
@@ -0,0 +1,23 @@
+import { Meta, StoryObj } from "@storybook/react";
+import { SpanNexusInsight } from ".";
+import { mockedSpanNexusInsight } from "./mockData";
+
+// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
+const meta: Meta = {
+ title: "Insights/SpanNexusInsight",
+ component: SpanNexusInsight,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
+ layout: "fullscreen"
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ insight: mockedSpanNexusInsight
+ }
+};
diff --git a/src/components/Insights/SpanNexusInsight/index.tsx b/src/components/Insights/SpanNexusInsight/index.tsx
new file mode 100644
index 000000000..48422d2f0
--- /dev/null
+++ b/src/components/Insights/SpanNexusInsight/index.tsx
@@ -0,0 +1,44 @@
+import { Tag } from "../../common/Tag";
+import { InsightCard } from "../InsightCard";
+import { Description } from "../styles";
+import * as s from "./styles";
+import { SpanNexusInsightProps, } from "./types";
+
+export const SpanNexusInsight = (
+ props: SpanNexusInsightProps
+) => {
+ const { insight } = props;
+ const { entries, flows, usage, services } = insight;
+ return (
+
+
+ Multiple code flows depend on this location
+
+
+
+ Services
+
+
+
+ Edpoints
+
+
+
+ Flows
+
+
+
+ Usage
+
+
+
+
+ }
+ onRecalculate={props.onRecalculate}
+ onRefresh={props.onRefresh}
+ />
+ );
+};
diff --git a/src/components/Insights/SpanNexusInsight/mockData.ts b/src/components/Insights/SpanNexusInsight/mockData.ts
new file mode 100644
index 000000000..00f55d922
--- /dev/null
+++ b/src/components/Insights/SpanNexusInsight/mockData.ts
@@ -0,0 +1,62 @@
+import { InsightType } from "../../../types";
+import {
+ InsightCategory,
+ InsightScope,
+ SpanNexusInsight
+} from "../types";
+
+export const mockedSpanNexusInsight: SpanNexusInsight =
+ {
+ firstDetected: "2023-12-05T17:25:47.010Z",
+ lastDetected: "2024-01-05T13:14:47.010Z",
+ criticality: 0,
+ impact: 0,
+ firstCommitId: "b3f7b3f",
+ lastCommitId: "a1b2c3d",
+ deactivatedCommitId: null,
+ reopenCount: 0,
+ ticketLink: null,
+ name: "Code Nexus Point",
+ type: InsightType.SpanNexus,
+ category: InsightCategory.Usage,
+ specifity: 2,
+ importance: 3,
+ scope: InsightScope.Span,
+ spanInfo: {
+ name: "HTTP POST /owners/{ownerId}/pets/new",
+ displayName: "HTTP POST /owners/{ownerId}/pets/new",
+ instrumentationLibrary: "io.opentelemetry.tomcat-10.0",
+ spanCodeObjectId:
+ "span:io.opentelemetry.tomcat-10.0$_$HTTP POST /owners/{ownerId}/pets/new",
+ methodCodeObjectId:
+ "method:org.springframework.samples.petclinic.owner.PetController$_$processCreationForm",
+ kind: "Server",
+ codeObjectId:
+ "org.springframework.samples.petclinic.owner.PetController$_$processCreationForm"
+ },
+ shortDisplayInfo: {
+ title: "",
+ targetDisplayName: "",
+ subtitle: "",
+ description: ""
+ },
+ codeObjectId:
+ "org.springframework.samples.petclinic.owner.PetController$_$processCreationForm",
+ decorators: [
+ {
+ title: "Excessive HTTP Calls",
+ description: "Numerous Http calls to the same endpoint detected "
+ }
+ ],
+ environment: "BOB-LAPTOP[LOCAL]",
+ severity: 0.0,
+ isRecalculateEnabled: false,
+ prefixedCodeObjectId:
+ "method:org.springframework.samples.petclinic.owner.PetController$_$processCreationForm",
+ customStartTime: null,
+ actualStartTime: "2023-08-10T08:04:00Z",
+ flows :4,
+ services: 3,
+ usage: 'High',
+ entries: 5,
+ };
diff --git a/src/components/Insights/SpanNexusInsight/styles.ts b/src/components/Insights/SpanNexusInsight/styles.ts
new file mode 100644
index 000000000..5f6c54d93
--- /dev/null
+++ b/src/components/Insights/SpanNexusInsight/styles.ts
@@ -0,0 +1,29 @@
+import styled from "styled-components";
+
+export const ContentContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+`;
+
+export const Stats = styled.div`
+ display: flex;
+ border-radius: 4px;
+ gap: 20px;
+ justify-content: space-between;
+`;
+
+export const Stat = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ overflow: hidden;
+`;
+
+export const Key = styled.span`
+ font-size: 14px;
+ font-weight: 510;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+`;
diff --git a/src/components/Insights/SpanNexusInsight/types.ts b/src/components/Insights/SpanNexusInsight/types.ts
new file mode 100644
index 000000000..ee5a3f7f9
--- /dev/null
+++ b/src/components/Insights/SpanNexusInsight/types.ts
@@ -0,0 +1,9 @@
+
+import {
+ InsightProps,
+ SpanNexusInsight,
+} from "../types";
+
+export interface SpanNexusInsightProps extends InsightProps {
+ insight: SpanNexusInsight;
+}
diff --git a/src/components/Insights/typeGuards.ts b/src/components/Insights/typeGuards.ts
index a18a2ce5f..54eded626 100644
--- a/src/components/Insights/typeGuards.ts
+++ b/src/components/Insights/typeGuards.ts
@@ -21,6 +21,7 @@ import {
SpanEndpointBottleneckInsight,
SpanInsight,
SpanNPlusOneInsight,
+ SpanNexusInsight,
SpanScalingBadlyInsight,
SpanScalingInsufficientDataInsight,
SpanScalingWellInsight,
@@ -133,3 +134,8 @@ export const isEndpointHighNumberOfQueriesInsight = (
insight: CodeObjectInsight
): insight is EndpointHighNumberOfQueriesInsight =>
insight.type === InsightType.EndpointHighNumberOfQueries;
+
+export const isSpanNexusInsight = (
+ insight: CodeObjectInsight
+): insight is SpanNexusInsight =>
+ insight.type === InsightType.SpanNexus;
diff --git a/src/components/Insights/types.ts b/src/components/Insights/types.ts
index 6d78f2a5e..d6ff4875d 100644
--- a/src/components/Insights/types.ts
+++ b/src/components/Insights/types.ts
@@ -682,3 +682,12 @@ export interface EndpointHighNumberOfQueriesInsight extends EndpointInsight {
requestFraction: number;
quantile?: number;
}
+
+export interface SpanNexusInsight extends SpanInsight {
+ type: InsightType.SpanNexus;
+ services: number;
+ entries: number;
+ flows: number;
+ usage: string | null;
+}
+
diff --git a/src/types.ts b/src/types.ts
index 5807c044e..da8ad573d 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -31,7 +31,8 @@ export enum InsightType {
SpanScalingInsufficientData = "SpanScalingInsufficientData",
EndpointSessionInView = "EndpointSessionInView",
EndpointChattyApi = "EndpointChattyApi",
- EndpointHighNumberOfQueries = "EndpointHighNumberOfQueries"
+ EndpointHighNumberOfQueries = "EndpointHighNumberOfQueries",
+ SpanNexus = "SpanNexus",
}
export type PercentileKey = "p50" | "p95";
diff --git a/src/utils/getInsightTypeInfo.ts b/src/utils/getInsightTypeInfo.ts
index eba165ac2..76f7f4197 100644
--- a/src/utils/getInsightTypeInfo.ts
+++ b/src/utils/getInsightTypeInfo.ts
@@ -113,6 +113,10 @@ export const getInsightTypeInfo = (
[InsightType.EndpointHighNumberOfQueries]: {
icon: SQLDatabaseIcon,
label: "High number of queries"
+ },
+ [InsightType.SpanNexus]: {
+ icon: BottleneckIcon, // todo changes
+ label: "Code Nexus Point"
}
};