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" } };