diff --git a/src/components/Insights/common/insights/SlowEndpointInsight/styles.ts b/src/components/Insights/common/insights/SlowEndpointInsight/styles.ts index 62399f5d1..7b6ffa5e6 100644 --- a/src/components/Insights/common/insights/SlowEndpointInsight/styles.ts +++ b/src/components/Insights/common/insights/SlowEndpointInsight/styles.ts @@ -2,8 +2,6 @@ import styled from "styled-components"; import { caption1RegularTypography } from "../../../../common/App/typographies"; export const ContentContainer = styled.div` - gap: 24px; - display: flex; padding: 8px 0; `; diff --git a/src/components/Insights/common/insights/TrafficInsight/TrafficInsight.stories.tsx b/src/components/Insights/common/insights/TrafficInsight/TrafficInsight.stories.tsx new file mode 100644 index 000000000..ff340ec39 --- /dev/null +++ b/src/components/Insights/common/insights/TrafficInsight/TrafficInsight.stories.tsx @@ -0,0 +1,133 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { TrafficInsight } from "."; +import { + InsightCategory, + InsightImportance, + InsightScope, + InsightSpecificity, + InsightType +} from "../../../types"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Insights/common/insights/TrafficInsight", + component: TrafficInsight, + 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; + +const BaseTrafficInsight = { + id: "60b55792-8262-3c5d-9628-7cce7979ad6d", + firstDetected: "2023-12-05T17:25:47.010Z", + lastDetected: "2024-01-05T13:14:47.010Z", + criticality: 0, + firstCommitId: "b3f7b3f", + lastCommitId: "a1b2c3d", + deactivatedCommitId: null, + reopenCount: 0, + ticketLink: null, + impact: 0, + name: "High Usage", + scope: InsightScope.EntrySpan, + endpointSpan: "HTTP GET SampleInsights/lock/{milisec}", + spanCodeObjectId: + "span:OpenTelemetry.Instrumentation.AspNetCore$_$HTTP GET SampleInsights/lock/{milisec}", + route: "epHTTP:HTTP GET SampleInsights/lock/{milisec}", + serviceName: "Sample.MoneyTransfer.API", + spanInfo: { + name: "HTTP GET SampleInsights/lock/{milisec}", + displayName: "HTTP GET SampleInsights/lock/{milisec}", + instrumentationLibrary: "OpenTelemetry.Instrumentation.AspNetCore", + spanCodeObjectId: + "span:OpenTelemetry.Instrumentation.AspNetCore$_$HTTP GET SampleInsights/lock/{milisec}", + methodCodeObjectId: + "method:Sample.MoneyTransfer.API.Controllers.SampleInsightsController$_$Lock(Double)", + kind: "Server", + codeObjectId: + "Sample.MoneyTransfer.API.Controllers.SampleInsightsController$_$Lock(Double)" + }, + shortDisplayInfo: { + title: "", + targetDisplayName: "", + subtitle: "", + description: "" + }, + codeObjectId: + "Sample.MoneyTransfer.API.Controllers.SampleInsightsController$_$Lock(Double)", + environment: "BOB-LAPTOP[LOCAL]", + severity: 0, + isRecalculateEnabled: false, + prefixedCodeObjectId: + "method:Sample.MoneyTransfer.API.Controllers.SampleInsightsController$_$Lock(Double)", + customStartTime: null, + actualStartTime: "2023-06-16T11:10:22.773Z", + decorators: null, + category: "", + importance: InsightImportance.NotInteresting +}; + +export const NormalTraffic: Story = { + args: { + insight: { + ...BaseTrafficInsight, + decorators: [ + { + title: "Normal Usage", + description: "Normal level of usage for this endpoint" + } + ], + category: InsightCategory.Usage, + type: InsightType.NormalUsage, + importance: InsightImportance.NotInteresting, + name: "Normal Usage", + maxCallsIn1Min: 0, + specifity: InsightSpecificity.OwnInsight + } + } +}; + +export const LowTraffic: Story = { + args: { + insight: { + ...BaseTrafficInsight, + decorators: [ + { + title: "Low Usage", + description: "Low level of usage for this endpoint" + } + ], + category: InsightCategory.Usage, + type: InsightType.LowUsage, + importance: InsightImportance.Info, + name: "Low Usage", + maxCallsIn1Min: 0, + specifity: InsightSpecificity.OwnInsight + } + } +}; + +export const HighTraffic: Story = { + args: { + insight: { + ...BaseTrafficInsight, + decorators: [ + { + title: "High Usage", + description: "High level of usage for this endpoint" + } + ], + category: InsightCategory.Usage, + type: InsightType.HighUsage, + importance: InsightImportance.Interesting, + name: "High Usage", + maxCallsIn1Min: 0, + specifity: InsightSpecificity.OwnInsight + } + } +}; diff --git a/src/components/Insights/common/insights/TrafficInsight/index.tsx b/src/components/Insights/common/insights/TrafficInsight/index.tsx new file mode 100644 index 000000000..fab8f9545 --- /dev/null +++ b/src/components/Insights/common/insights/TrafficInsight/index.tsx @@ -0,0 +1,65 @@ +import { roundTo } from "../../../../../utils/roundTo"; +import { Tag } from "../../../../common/v3/Tag"; +import { TrafficInsightProps } from "../../../TrafficInsight/types"; +import { InsightType } from "../../../types"; +import { InsightCard } from "../../InsightCard"; +import { ColumnsContainer } from "../../InsightCard/ColumnsContainer"; +import { KeyValue } from "../../InsightCard/KeyValue"; +import * as s from "./styles"; + +const suffixes = [ + { value: 1, symbol: "" }, + { value: 1e3, symbol: "k" }, + { value: 1e6, symbol: "M" }, + { value: 1e9, symbol: "G" }, + { value: 1e12, symbol: "T" }, + { value: 1e15, symbol: "P" }, + { value: 1e18, symbol: "E" } +]; + +const getValueString = (requestCount: number): string => { + const suffix = [...suffixes] + .reverse() + .find((suffix) => requestCount >= suffix.value); + + if (suffix) { + return `~${roundTo(requestCount / suffix.value, 2)}${suffix.symbol}`; + } + + return `~${roundTo(requestCount, 2)}`; +}; + +const getDescription = (insightType: InsightType): string => { + switch (insightType) { + case InsightType.LowUsage: + return "Servicing a low number of requests"; + case InsightType.NormalUsage: + return "Servicing an average number of requests"; + case InsightType.HighUsage: + return "Servicing a high number of requests"; + default: + return ""; + } +}; + +export const TrafficInsight = (props: TrafficInsightProps) => { + const valueString = getValueString(props.insight.maxCallsIn1Min); + + return ( + + + {getDescription(props.insight.type)} + + + + + + } + onRecalculate={props.onRecalculate} + onRefresh={props.onRefresh} + /> + ); +}; diff --git a/src/components/Insights/common/insights/TrafficInsight/styles.ts b/src/components/Insights/common/insights/TrafficInsight/styles.ts new file mode 100644 index 000000000..3fe430d93 --- /dev/null +++ b/src/components/Insights/common/insights/TrafficInsight/styles.ts @@ -0,0 +1,12 @@ +import styled from "styled-components"; +import { caption1RegularTypography } from "../../../../common/App/typographies"; + +export const ContentContainer = styled.div` + gap: 24px; + padding: 8px 0; +`; + +export const Description = styled.div` + color: ${({ theme }) => theme.colors.v3.text.secondary}; + ${caption1RegularTypography} +`; diff --git a/src/components/Insights/common/insights/TrafficInsight/types.ts b/src/components/Insights/common/insights/TrafficInsight/types.ts new file mode 100644 index 000000000..9c8088746 --- /dev/null +++ b/src/components/Insights/common/insights/TrafficInsight/types.ts @@ -0,0 +1,13 @@ +import { + EndpointHighUsageInsight, + EndpointLowUsageInsight, + EndpointNormalUsageInsight, + InsightProps +} from "../../../types"; + +export interface TrafficInsightProps extends InsightProps { + insight: + | EndpointLowUsageInsight + | EndpointNormalUsageInsight + | EndpointHighUsageInsight; +}