diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html index 2379489d7..f19bc5768 100644 --- a/.storybook/preview-body.html +++ b/.storybook/preview-body.html @@ -19,8 +19,6 @@ window.isDigmathonModeEnabled = true; window.assetsRefreshInterval; - window.assetsSearch = true; - window.assetsSelectedServices = []; window.dashboardEnvironment = "SAMPLE_ENV"; window.dashboardRefreshInterval; @@ -35,7 +33,6 @@ window.recentActivityExpirationLimit; window.recentActivityDocumentationURL = "https://github.com/digma-ai/digma-vscode-plugin#%EF%B8%8F-extension-settings"; - window.recentActivityIsEnvironmentManagementEnabled = true; window.testsRefreshInterval; diff --git a/package-lock.json b/package-lock.json index 1d21909d9..776f04ff8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,8 @@ "react-transition-group": "^4.4.5", "recharts": "^2.6.2", "semver": "^7.5.4", - "styled-components": "^6.1.0" + "styled-components": "^6.1.0", + "uuid": "^9.0.1" }, "devDependencies": { "@babel/core": "^7.23.2", @@ -48,6 +49,7 @@ "@types/react-syntax-highlighter": "^15.5.7", "@types/react-transition-group": "^4.4.5", "@types/semver": "^7.5.6", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.49.0", "@typescript-eslint/parser": "^5.49.0", "babel-loader": "^9.1.3", @@ -6644,6 +6646,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -18611,7 +18619,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -23675,6 +23682,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -32395,8 +32408,7 @@ "uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-compile-cache-lib": { "version": "3.0.1", diff --git a/package.json b/package.json index 2c41f8871..14c8d23d8 100644 --- a/package.json +++ b/package.json @@ -11,29 +11,23 @@ "test": "echo \"Error: no test specified\" && exit 1", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", - "build:assets:dev": "webpack --config webpack.dev.ts --env app=assets", "build:dashboard:dev": "webpack --config webpack.dev.ts --env app=dashboard", "build:documentation:dev": "webpack --config webpack.dev.ts --env app=documentation", - "build:insights:dev": "webpack --config webpack.dev.ts --env app=insights", "build:installation-wizard:dev": "webpack --config webpack.dev.ts --env app=installationWizard", "build:main:dev": "webpack --config webpack.dev.ts --env app=main", "build:navigation:dev": "webpack --config webpack.dev.ts --env app=navigation", "build:notifications:dev": "webpack --config webpack.dev.ts --env app=notifications", "build:recentActivity:dev": "webpack --config webpack.dev.ts --env app=recentActivity", - "build:tests:dev": "webpack --config webpack.dev.ts --env app=tests", "build:troubleshooting:dev": "webpack --config webpack.dev.ts --env app=troubleshooting", "build:dev": "webpack --config webpack.dev.ts", "build:dev:web": "webpack --config webpack.dev.ts --env platform=Web", - "build:assets:prod": "webpack --config webpack.prod.ts --env app=assets", "build:dashboard:prod": "webpack --config webpack.prod.ts --env app=dashboard", "build:documentation:prod": "webpack --config webpack.prod.ts --env app=documentation", - "build:insights:prod": "webpack --config webpack.prod.ts --env app=insights", "build:installation-wizard:prod": "webpack --config webpack.prod.ts --env app=installationWizard", "build:main:prod": "webpack --config webpack.prod.ts --env app=main", "build:navigation:prod": "webpack --config webpack.prod.ts --env app=navigation", "build:notifications:prod": "webpack --config webpack.prod.ts --env app=notifications", "build:recentActivity:prod": "webpack --config webpack.prod.ts --env app=recentActivity", - "build:tests:prod": "webpack --config webpack.prod.ts --env app=tests", "build:troubleshooting:prod": "webpack --config webpack.prod.ts --env app=troubleshooting", "build:prod": "webpack --config webpack.prod.ts", "build:prod:web": "webpack --config webpack.prod.ts --env platform=Web", @@ -75,6 +69,7 @@ "@types/react-syntax-highlighter": "^15.5.7", "@types/react-transition-group": "^4.4.5", "@types/semver": "^7.5.6", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.49.0", "@typescript-eslint/parser": "^5.49.0", "babel-loader": "^9.1.3", @@ -122,6 +117,7 @@ "react-transition-group": "^4.4.5", "recharts": "^2.6.2", "semver": "^7.5.4", - "styled-components": "^6.1.0" + "styled-components": "^6.1.0", + "uuid": "^9.0.1" } } diff --git a/public/images/environmentId_dark.svg b/public/images/environmentId_dark.svg new file mode 100644 index 000000000..c8b899086 --- /dev/null +++ b/public/images/environmentId_dark.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/environmentId_light.svg b/public/images/environmentId_light.svg new file mode 100644 index 000000000..aca04a1a4 --- /dev/null +++ b/public/images/environmentId_light.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/howToSetupEnvironmentMenuItem_dark.svg b/public/images/howToSetupEnvironmentMenuItem_dark.svg new file mode 100644 index 000000000..8f3a3beb1 --- /dev/null +++ b/public/images/howToSetupEnvironmentMenuItem_dark.svg @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/howToSetupEnvironmentMenuItem_light.svg b/public/images/howToSetupEnvironmentMenuItem_light.svg new file mode 100644 index 000000000..0a2b7eb77 --- /dev/null +++ b/public/images/howToSetupEnvironmentMenuItem_light.svg @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/longArrow.svg b/public/images/longArrow.svg new file mode 100644 index 000000000..c9c01de66 --- /dev/null +++ b/public/images/longArrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/actions.ts b/src/actions.ts index 2c3f83dae..a94d93cef 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -25,7 +25,7 @@ export const actions = addPrefix(ACTION_PREFIX, { SET_OBSERVABILITY: "SET_OBSERVABILITY", GET_BACKEND_INFO: "GET_BACKEND_INFO", SET_BACKEND_INFO: "SET_BACKEND_INFO", - REGISTER: "REGISTER", + PERSONALIZE_REGISTER: "PERSONALIZE_REGISTER", SET_ENVIRONMENTS: "SET_ENVIRONMENTS", SET_IS_MICROMETER_PROJECT: "SET_IS_MICROMETER_PROJECT", SAVE_TO_PERSISTENCE: "SAVE_TO_PERSISTENCE", @@ -42,6 +42,12 @@ export const actions = addPrefix(ACTION_PREFIX, { GET_INSIGHT_STATS: "GET_INSIGHT_STATS", SET_INSIGHT_STATS: "SET_INSIGHT_STATS", CHANGE_ENVIRONMENT: "CHANGE_ENVIRONMENT", + SET_USER_INFO: "SET_USER_INFO", + SET_LOGIN_RESULT: "SET_LOGIN_RESULT", + LOGIN: "LOGIN", + LOGOUT: "LOGOUT", + REGISTER: "REGISTER", + SET_REGISTRATION_RESULT: "SET_REGISTRATION_RESULT", SET_DIGMATHON_MODE: "SET_DIGMATHON_MODE", SET_PRODUCT_KEY: "SET_PRODUCT_KEY", SET_USER_ID: "SET_USER_ID", diff --git a/src/components/Assets/AssetList/AssetEntry/index.tsx b/src/components/Assets/AssetList/AssetEntry/index.tsx index d78c748f3..45627ee45 100644 --- a/src/components/Assets/AssetList/AssetEntry/index.tsx +++ b/src/components/Assets/AssetList/AssetEntry/index.tsx @@ -182,22 +182,6 @@ export const AssetEntry = (props: AssetEntryProps) => { - {!props.isOverallImpactHidden && ( - - Overall impact - - - - - - - )} )} diff --git a/src/components/Assets/AssetList/AssetEntry/types.ts b/src/components/Assets/AssetList/AssetEntry/types.ts index 031bc1d26..8a5ada33a 100644 --- a/src/components/Assets/AssetList/AssetEntry/types.ts +++ b/src/components/Assets/AssetList/AssetEntry/types.ts @@ -5,7 +5,6 @@ export interface AssetEntryProps { onAssetLinkClick: (entry: AssetEntry) => void; sortingCriterion: SORTING_CRITERION; isImpactHidden: boolean; - isOverallImpactHidden: boolean; } export interface ImpactScoreIndicatorProps { diff --git a/src/components/Assets/AssetList/AssetList.stories.tsx b/src/components/Assets/AssetList/AssetList.stories.tsx index 8016ca1f3..08efc6d38 100644 --- a/src/components/Assets/AssetList/AssetList.stories.tsx +++ b/src/components/Assets/AssetList/AssetList.stories.tsx @@ -21,7 +21,6 @@ export const Default: Story = { args: { searchQuery: "", assetTypeId: "Endpoint", - services: [], data: { data: [ { diff --git a/src/components/Assets/AssetList/index.tsx b/src/components/Assets/AssetList/index.tsx index e3a83334f..bcbb60e7d 100644 --- a/src/components/Assets/AssetList/index.tsx +++ b/src/components/Assets/AssetList/index.tsx @@ -8,12 +8,10 @@ import { } from "react"; import { DefaultTheme, useTheme } from "styled-components"; import { dispatcher } from "../../../dispatcher"; -import { getFeatureFlagValue } from "../../../featureFlags"; import { usePrevious } from "../../../hooks/usePrevious"; import { isEnvironment } from "../../../typeGuards/isEnvironment"; import { isNumber } from "../../../typeGuards/isNumber"; import { isString } from "../../../typeGuards/isString"; -import { FeatureFlag } from "../../../types"; import { ConfigContext } from "../../common/App/ConfigContext"; import { DeploymentType } from "../../common/App/types"; import { EmptyState } from "../../common/EmptyState"; @@ -124,30 +122,15 @@ const getSortingCriterionInfo = ( [SORTING_CRITERION.PERFORMANCE_IMPACT]: { label: "Performance impact", defaultOrder: SORTING_ORDER.DESC - }, - [SORTING_CRITERION.OVERALL_IMPACT]: { - label: "Overall impact", - defaultOrder: SORTING_ORDER.DESC } }; return sortingCriterionInfoMap[sortingCriterion]; }; -const getSortingCriteria = ( - isImpactHidden: boolean, - isOverallImpactHidden: boolean -) => +const getSortingCriteria = (isImpactHidden: boolean) => Object.values(SORTING_CRITERION).filter( - (x) => - !( - (isImpactHidden && - [ - SORTING_CRITERION.PERFORMANCE_IMPACT, - SORTING_CRITERION.OVERALL_IMPACT - ].includes(x)) || - (isOverallImpactHidden && x === SORTING_CRITERION.OVERALL_IMPACT) - ) + (x) => !(isImpactHidden && x === SORTING_CRITERION.PERFORMANCE_IMPACT) ); const getData = ( @@ -156,8 +139,6 @@ const getData = ( sorting: Sorting, searchQuery: string, filters: AssetFilterQuery | undefined, - services: string[] | undefined, - isComplexFilterEnabled: boolean, isDirect?: boolean, scopedSpanCodeObjectId?: string ) => { @@ -175,13 +156,11 @@ const getData = ( ...(searchQuery && searchQuery.length > 0 ? { displayName: searchQuery } : {}), - ...(isComplexFilterEnabled - ? filters || { - services: [], - operations: [], - insights: [] - } - : { services: services || [] }) + ...(filters || { + services: [], + operations: [], + insights: [] + }) } } }); @@ -217,19 +196,8 @@ export const AssetList = (props: AssetListProps) => { const refreshTimerId = useRef(); const previousEnvironment = usePrevious(config.environment); const previousAssetTypeId = usePrevious(props.assetTypeId); - const previousServices = usePrevious(props.services); const previousFilters = usePrevious(props.filters); const previousViewScope = usePrevious(props.scopeViewOptions); - const isComplexFilterEnabled = useMemo( - () => - Boolean( - getFeatureFlagValue( - config, - FeatureFlag.IS_ASSETS_COMPLEX_FILTER_ENABLED - ) - ), - [config] - ); const refreshData = useCallback(() => { getData( @@ -238,20 +206,16 @@ export const AssetList = (props: AssetListProps) => { sorting, props.searchQuery, props.filters, - props.services, - isComplexFilterEnabled, props.scopeViewOptions?.isDirect, props.scopeViewOptions?.scopedSpanCodeObjectId ); }, [ - isComplexFilterEnabled, page, props.assetTypeId, props.filters, props.scopeViewOptions?.isDirect, props.scopeViewOptions?.scopedSpanCodeObjectId, props.searchQuery, - props.services, sorting ]); @@ -263,24 +227,15 @@ export const AssetList = (props: AssetListProps) => { () => !( config.backendInfo?.deploymentType === DeploymentType.HELM && - config.environment?.type === "shared" + config.environment?.type === "Public" ), [config.backendInfo?.deploymentType, config.environment?.type] ); - const isOverallImpactHidden = Boolean( - getFeatureFlagValue(config, FeatureFlag.IS_ASSETS_OVERALL_IMPACT_HIDDEN) - ); - - const sortingCriteria = getSortingCriteria( - isImpactHidden, - isOverallImpactHidden - ); + const sortingCriteria = getSortingCriteria(isImpactHidden); const areAnyFiltersApplied = checkIfAnyFiltersApplied( - isComplexFilterEnabled, props.filters, - props.services, props.searchQuery ); @@ -315,36 +270,31 @@ export const AssetList = (props: AssetListProps) => { if ( (isNumber(previousPage) && previousPage !== page) || (isEnvironment(previousEnvironment) && - previousEnvironment.originalName !== - config.environment?.originalName) || + previousEnvironment.id !== config.environment?.id) || (previousSorting && previousSorting !== sorting) || (isString(previousSearchQuery) && previousSearchQuery !== props.searchQuery) || (isString(previousAssetTypeId) && previousAssetTypeId !== props.assetTypeId) || - (Array.isArray(previousServices) && - previousServices !== props.services) || (previousFilters && previousFilters !== props.filters) || previousViewScope !== props.scopeViewOptions ) { refreshData(); } }, [ - config.environment?.originalName, + config.environment?.id, page, previousAssetTypeId, previousEnvironment, previousFilters, previousPage, previousSearchQuery, - previousServices, previousSorting, previousViewScope, props.assetTypeId, props.filters, props.scopeViewOptions, props.searchQuery, - props.services, refreshData, sorting ]); @@ -373,10 +323,7 @@ export const AssetList = (props: AssetListProps) => { useEffect(() => { if ( isImpactHidden && - [ - SORTING_CRITERION.PERFORMANCE_IMPACT, - SORTING_CRITERION.OVERALL_IMPACT - ].includes(sorting.criterion) + sorting.criterion === SORTING_CRITERION.PERFORMANCE_IMPACT ) { setSorting({ criterion: SORTING_CRITERION.CRITICAL_INSIGHTS, @@ -388,7 +335,7 @@ export const AssetList = (props: AssetListProps) => { useEffect(() => { setPage(0); }, [ - config.environment?.originalName, + config.environment?.id, props.searchQuery, sorting, props.assetTypeId, @@ -398,7 +345,7 @@ export const AssetList = (props: AssetListProps) => { useEffect(() => { listRef.current?.scrollTo(0, 0); }, [ - config.environment?.originalName, + config.environment?.id, props.searchQuery, sorting, page, @@ -464,7 +411,6 @@ export const AssetList = (props: AssetListProps) => { onAssetLinkClick={handleAssetLinkClick} sortingCriterion={sorting.criterion} isImpactHidden={isImpactHidden} - isOverallImpactHidden={isOverallImpactHidden} /> ); })} diff --git a/src/components/Assets/AssetList/types.ts b/src/components/Assets/AssetList/types.ts index d5a5ec4bc..708d78d0d 100644 --- a/src/components/Assets/AssetList/types.ts +++ b/src/components/Assets/AssetList/types.ts @@ -6,7 +6,6 @@ export interface AssetListProps { data?: AssetsData; onBackButtonClick: () => void; assetTypeId: string; - services?: string[]; filters?: AssetFilterQuery; searchQuery: string; scopeViewOptions: AssetScopeOption | null; @@ -20,8 +19,7 @@ export enum SORTING_CRITERION { SLOWEST_FIVE_PERCENT = "p95", LATEST = "latest", NAME = "displayname", - PERFORMANCE_IMPACT = "performanceimpact", - OVERALL_IMPACT = "overallimpact" + PERFORMANCE_IMPACT = "performanceimpact" } export enum SORTING_ORDER { diff --git a/src/components/Assets/AssetTypeList/AssetTypeList.stories.tsx b/src/components/Assets/AssetTypeList/AssetTypeList.stories.tsx index b1041fa6f..a3d68c14a 100644 --- a/src/components/Assets/AssetTypeList/AssetTypeList.stories.tsx +++ b/src/components/Assets/AssetTypeList/AssetTypeList.stories.tsx @@ -20,7 +20,6 @@ type Story = StoryObj; export const Default: Story = { args: { searchQuery: "", - services: [], data: { assetCategories: [ { @@ -55,7 +54,6 @@ export const Default: Story = { export const Empty: Story = { args: { searchQuery: "", - services: [], data: { assetCategories: [] } diff --git a/src/components/Assets/AssetTypeList/index.tsx b/src/components/Assets/AssetTypeList/index.tsx index 8bc3b2095..4e4d71ca2 100644 --- a/src/components/Assets/AssetTypeList/index.tsx +++ b/src/components/Assets/AssetTypeList/index.tsx @@ -1,19 +1,10 @@ -import { - useCallback, - useContext, - useEffect, - useMemo, - useRef, - useState -} from "react"; +import { useCallback, useContext, useEffect, useRef, useState } from "react"; import { dispatcher } from "../../../dispatcher"; -import { getFeatureFlagValue } from "../../../featureFlags"; import { usePrevious } from "../../../hooks/usePrevious"; import { isEnvironment } from "../../../typeGuards/isEnvironment"; import { isNull } from "../../../typeGuards/isNull"; import { isNumber } from "../../../typeGuards/isNumber"; import { isString } from "../../../typeGuards/isString"; -import { FeatureFlag } from "../../../types"; import { ConfigContext } from "../../common/App/ConfigContext"; import { AssetFilterQuery } from "../AssetsFilter/types"; import { NoDataMessage } from "../NoDataMessage"; @@ -42,9 +33,7 @@ const ASSET_TYPE_IDS = [ const getData = ( filters: AssetFilterQuery | undefined, - services: string[] | undefined, searchQuery: string, - isComplexFilterEnabled: boolean, isDirect?: boolean, scopedSpanCodeObjectId?: string ) => { @@ -54,9 +43,7 @@ const getData = ( query: { directOnly: isDirect, scopedSpanCodeObjectId, - ...(isComplexFilterEnabled - ? filters || { services: [], operations: [], insights: [] } - : { services: services || [] }), + ...(filters || { services: [], operations: [], insights: [] }), ...(searchQuery.length > 0 ? { displayName: searchQuery } : {}) } } @@ -75,38 +62,23 @@ export const AssetTypeList = (props: AssetTypeListProps) => { const config = useContext(ConfigContext); const previousEnvironment = usePrevious(config.environment); const refreshTimerId = useRef(); - const previousServices = usePrevious(props.services); const previousFilters = usePrevious(props.filters); const previousSearchQuery = usePrevious(props.searchQuery); const previousViewScope = usePrevious(props.scopeViewOptions); - const isComplexFilterEnabled = useMemo( - () => - Boolean( - getFeatureFlagValue( - config, - FeatureFlag.IS_ASSETS_COMPLEX_FILTER_ENABLED - ) - ), - [config] - ); const refreshData = useCallback( () => getData( props.filters, - props.services, props.searchQuery, - isComplexFilterEnabled, props.scopeViewOptions?.isDirect, props.scopeViewOptions?.scopedSpanCodeObjectId ), [ - isComplexFilterEnabled, props.filters, props.scopeViewOptions?.isDirect, props.scopeViewOptions?.scopedSpanCodeObjectId, - props.searchQuery, - props.services + props.searchQuery ] ); @@ -115,9 +87,7 @@ export const AssetTypeList = (props: AssetTypeListProps) => { }, [refreshData, props.setRefresher]); const areAnyFiltersApplied = checkIfAnyFiltersApplied( - isComplexFilterEnabled, props.filters, - props.services, props.searchQuery ); @@ -153,10 +123,7 @@ export const AssetTypeList = (props: AssetTypeListProps) => { useEffect(() => { if ( (isEnvironment(previousEnvironment) && - previousEnvironment.originalName !== - config.environment?.originalName) || - (Array.isArray(previousServices) && - previousServices !== props.services) || + previousEnvironment.id !== config.environment?.id) || (previousFilters && previousFilters !== props.filters) || (isString(previousSearchQuery) && previousSearchQuery !== props.searchQuery) || @@ -165,16 +132,14 @@ export const AssetTypeList = (props: AssetTypeListProps) => { refreshData(); } }, [ - config.environment?.originalName, + config.environment?.id, previousEnvironment, previousFilters, previousSearchQuery, - previousServices, previousViewScope, props.filters, props.scopeViewOptions, props.searchQuery, - props.services, refreshData ]); diff --git a/src/components/Assets/AssetTypeList/types.ts b/src/components/Assets/AssetTypeList/types.ts index 92c5a4110..cd336e36d 100644 --- a/src/components/Assets/AssetTypeList/types.ts +++ b/src/components/Assets/AssetTypeList/types.ts @@ -6,7 +6,6 @@ import { AssetScopeOption } from "../AssetsViewScopeConfiguration/types"; export interface AssetTypeListProps { data?: AssetCategoriesData; onAssetTypeSelect: (assetTypeId: string) => void; - services?: string[]; filters?: AssetFilterQuery; searchQuery: string; scopeViewOptions: AssetScopeOption | null; diff --git a/src/components/Assets/Assets.stories.tsx b/src/components/Assets/Assets.stories.tsx index 460964847..0fe51a129 100644 --- a/src/components/Assets/Assets.stories.tsx +++ b/src/components/Assets/Assets.stories.tsx @@ -17,6 +17,4 @@ export default meta; type Story = StoryObj; // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args -export const Default: Story = { - args: {} -}; +export const Default: Story = {}; diff --git a/src/components/Assets/AssetsFilter/index.tsx b/src/components/Assets/AssetsFilter/index.tsx index 5bff8e7d7..25dc3236d 100644 --- a/src/components/Assets/AssetsFilter/index.tsx +++ b/src/components/Assets/AssetsFilter/index.tsx @@ -137,8 +137,7 @@ export const AssetsFilter = (props: AssetsFilterProps) => { useEffect(() => { if ( (isEnvironment(previousEnvironment) && - previousEnvironment.originalName !== - config.environment?.originalName) || + previousEnvironment.id !== config.environment?.id) || (previousScope && previousScope !== config.scope) ) { const defaultFilters = { diff --git a/src/components/Assets/AssetsViewScopeConfiguration/index.tsx b/src/components/Assets/AssetsViewScopeConfiguration/index.tsx index c1853c0a5..9c03ef46b 100644 --- a/src/components/Assets/AssetsViewScopeConfiguration/index.tsx +++ b/src/components/Assets/AssetsViewScopeConfiguration/index.tsx @@ -20,7 +20,7 @@ export const AssetsViewScopeConfiguration = ({ useEffect(() => { const isEntryPoint = !currentScope || currentScope.span?.role === "Entry"; - setViewMode(isEntryPoint ? "children" : "descendants"); + setViewMode(isEntryPoint ? "descendants" : "children"); onAssetViewChange({ scopedSpanCodeObjectId: currentScope?.span?.spanCodeObjectId, diff --git a/src/components/Assets/ServicesFilter/FilterButton/index.tsx b/src/components/Assets/ServicesFilter/FilterButton/index.tsx deleted file mode 100644 index d1cabaaf6..000000000 --- a/src/components/Assets/ServicesFilter/FilterButton/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { isNumber } from "../../../../typeGuards/isNumber"; -import { ChevronIcon } from "../../../common/icons/ChevronIcon"; -import { FilterIcon } from "../../../common/icons/FilterIcon"; -import { Direction } from "../../../common/icons/types"; -import * as s from "./styles"; -import { FilterButtonProps } from "./types"; - -export const FilterButton = (props: FilterButtonProps) => ( - - - - {props.title} - {props.showCount ? ( - isNumber(props.selectedCount) && - props.selectedCount > 0 && - !props.isLoading ? ( - {props.selectedCount} - ) : ( - - All - - ) - ) : null} - - - - - -); diff --git a/src/components/Assets/ServicesFilter/FilterButton/styles.ts b/src/components/Assets/ServicesFilter/FilterButton/styles.ts deleted file mode 100644 index 9757d8356..000000000 --- a/src/components/Assets/ServicesFilter/FilterButton/styles.ts +++ /dev/null @@ -1,67 +0,0 @@ -import styled from "styled-components"; - -export const Button = styled.button` - border: 1px solid #4e5157; - background: transparent; - border-radius: 4px; - padding: 8px; - display: flex; - gap: 10px; - align-items: center; -`; - -export const Label = styled.span` - display: flex; - gap: 4px; - align-items: center; - font-size: 14px; - color: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#818594"; - case "dark": - case "dark-jetbrains": - return "#b4b8bf"; - } - }}; -`; - -export const SelectedItemsNumberPlaceholder = styled.span` - color: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#494b57"; - case "dark": - case "dark-jetbrains": - return "#dfe1e5"; - } - }}; - user-select: none; -`; - -export const Number = styled.span` - min-width: 18px; - height: 18px; - flex-shrink: 0; - font-size: 14px; - line-height: 100%; - font-weight: 500; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - color: #fff; - background: #5053d4; -`; - -export const ChevronIconContainer = styled.span` - color: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#494b57"; - case "dark": - case "dark-jetbrains": - return "#dfe1e5"; - } - }}; -`; diff --git a/src/components/Assets/ServicesFilter/FilterButton/types.ts b/src/components/Assets/ServicesFilter/FilterButton/types.ts deleted file mode 100644 index a15c293c5..000000000 --- a/src/components/Assets/ServicesFilter/FilterButton/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface FilterButtonProps { - title: string; - isLoading?: boolean; - isMenuOpen: boolean; - selectedCount?: number; - showCount?: boolean; -} diff --git a/src/components/Assets/ServicesFilter/index.tsx b/src/components/Assets/ServicesFilter/index.tsx deleted file mode 100644 index 707a09f0b..000000000 --- a/src/components/Assets/ServicesFilter/index.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import { useContext, useEffect, useState } from "react"; -import { dispatcher } from "../../../dispatcher"; -import { usePrevious } from "../../../hooks/usePrevious"; -import { isEnvironment } from "../../../typeGuards/isEnvironment"; -import { isNumber } from "../../../typeGuards/isNumber"; -import { isString } from "../../../typeGuards/isString"; -import { ConfigContext } from "../../common/App/ConfigContext"; -import { FilterMenu } from "../../common/FilterMenu"; -import { NewPopover } from "../../common/NewPopover"; -import { actions } from "../actions"; -import { ServiceData } from "../types"; -import { FilterButton } from "./FilterButton"; -import { ServicesFilterProps } from "./types"; - -const REFRESH_INTERVAL = isNumber(window.assetsRefreshInterval) - ? window.assetsRefreshInterval - : 10 * 1000; // in milliseconds - -const preselectedServices = - Array.isArray(window.assetsSelectedServices) && - window.assetsSelectedServices.every(isString) - ? window.assetsSelectedServices - : []; - -export const ServicesFilter = (props: ServicesFilterProps) => { - const [isServiceMenuOpen, setIsServiceMenuOpen] = useState(false); - const [areServicesLoading, setAreServicesLoading] = useState(false); - const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); - const [services, setServices] = useState(); - const previousSelectedServices = usePrevious(props.selectedServices); - const config = useContext(ConfigContext); - const previousEnvironment = usePrevious(config.environment); - - useEffect(() => { - window.sendMessageToDigma({ - action: actions.GET_SERVICES - }); - setAreServicesLoading(true); - }, []); - - useEffect(() => { - const handleServicesData = (data: unknown, timeStamp: number) => { - const serviceData = data as ServiceData; - setLastSetDataTimeStamp(timeStamp); - const oldSelectedServices = Array.isArray(props.selectedServices) - ? props.selectedServices - : preselectedServices; - - const newSelectedServices = serviceData.services.filter((x) => - oldSelectedServices.includes(x) - ); - - props.onChange(newSelectedServices); - setServices(serviceData.services); - setAreServicesLoading(false); - }; - - dispatcher.addActionListener(actions.SET_SERVICES, handleServicesData); - - return () => { - dispatcher.removeActionListener(actions.SET_SERVICES, handleServicesData); - }; - }, [props.selectedServices, props.onChange]); - - useEffect(() => { - if ( - isEnvironment(previousEnvironment) && - previousEnvironment.originalName !== config.environment?.originalName - ) { - setServices(undefined); - window.sendMessageToDigma({ - action: actions.GET_SERVICES - }); - setAreServicesLoading(true); - } - }, [previousEnvironment, config.environment, services]); - - useEffect(() => { - const timerId = window.setTimeout(() => { - window.sendMessageToDigma({ - action: actions.GET_SERVICES - }); - }, REFRESH_INTERVAL); - - return () => { - window.clearTimeout(timerId); - }; - }, [lastSetDataTimeStamp]); - - useEffect(() => { - if ( - previousSelectedServices && - previousSelectedServices !== props.selectedServices - ) { - window.sendMessageToDigma({ - action: actions.SET_SELECTED_SERVICES, - payload: { - services: props.selectedServices - } - }); - } - }, [previousSelectedServices, props.selectedServices]); - - const handleServiceMenuClose = () => { - setIsServiceMenuOpen(false); - }; - - const handleServiceMenuItemClick = (service: string) => { - const oldSelectedServices = props.selectedServices || []; - const serviceIndex = oldSelectedServices.findIndex((x) => x === service); - - if (serviceIndex < 0) { - props.onChange([...oldSelectedServices, service]); - } else { - props.onChange([ - ...oldSelectedServices.slice(0, serviceIndex), - ...oldSelectedServices.slice(serviceIndex + 1) - ]); - } - }; - - const filterMenuItems = (services || []).map((x) => ({ - label: x, - value: x, - selected: (props.selectedServices || []).includes(x) - })); - - return ( - - } - onOpenChange={setIsServiceMenuOpen} - isOpen={isServiceMenuOpen} - placement={"bottom-end"} - > -
- -
-
- ); -}; diff --git a/src/components/Assets/ServicesFilter/styles.ts b/src/components/Assets/ServicesFilter/styles.ts deleted file mode 100644 index 03db0e560..000000000 --- a/src/components/Assets/ServicesFilter/styles.ts +++ /dev/null @@ -1,67 +0,0 @@ -import styled from "styled-components"; - -export const ServiceMenuButton = styled.button` - border: 1px solid #4e5157; - background: transparent; - border-radius: 4px; - padding: 8px; - display: flex; - gap: 10px; - align-items: center; -`; - -export const ServiceMenuButtonLabel = styled.span` - display: flex; - gap: 4px; - align-items: center; - font-size: 14px; - color: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#818594"; - case "dark": - case "dark-jetbrains": - return "#b4b8bf"; - } - }}; -`; - -export const SelectedServiceNumberPlaceholder = styled.span` - color: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#494b57"; - case "dark": - case "dark-jetbrains": - return "#dfe1e5"; - } - }}; - user-select: none; -`; - -export const Number = styled.span` - min-width: 18px; - height: 18px; - flex-shrink: 0; - font-size: 14px; - line-height: 100%; - font-weight: 500; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - color: #fff; - background: #5053d4; -`; - -export const ServiceMenuChevronIconContainer = styled.span` - color: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#494b57"; - case "dark": - case "dark-jetbrains": - return "#dfe1e5"; - } - }}; -`; diff --git a/src/components/Assets/ServicesFilter/types.ts b/src/components/Assets/ServicesFilter/types.ts deleted file mode 100644 index 4e5641d78..000000000 --- a/src/components/Assets/ServicesFilter/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ServicesFilterProps { - selectedServices?: string[]; - onChange: (services: string[]) => void; -} diff --git a/src/components/Assets/actions.ts b/src/components/Assets/actions.ts index 89d8b1d12..75ad6e442 100644 --- a/src/components/Assets/actions.ts +++ b/src/components/Assets/actions.ts @@ -8,9 +8,6 @@ export const actions = addPrefix(ACTION_PREFIX, { GO_TO_ASSET: "GO_TO_ASSET", GET_CATEGORIES_DATA: "GET_CATEGORIES_DATA", SET_CATEGORIES_DATA: "SET_CATEGORIES_DATA", - GET_SERVICES: "GET_SERVICES", - SET_SERVICES: "SET_SERVICES", - SET_SELECTED_SERVICES: "SET_SELECTED_SERVICES", GET_ASSET_FILTERS_DATA: "GET_ASSET_FILTERS_DATA", SET_ASSET_FILTERS_DATA: "SET_ASSET_FILTERS_DATA" }); diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index b2929db6f..69196910d 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -1,12 +1,6 @@ -import { useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { lt, valid } from "semver"; -import { - featureFlagMinBackendVersions, - getFeatureFlagValue -} from "../../featureFlags"; +import { useCallback, useContext, useEffect, useState } from "react"; import { useDebounce } from "../../hooks/useDebounce"; import { usePrevious } from "../../hooks/usePrevious"; -import { FeatureFlag } from "../../types"; import { sendUserActionTrackingEvent } from "../../utils/actions/sendUserActionTrackingEvent"; import { ConfigContext } from "../common/App/ConfigContext"; import { EmptyState } from "../common/EmptyState"; @@ -20,7 +14,6 @@ import { AssetFilterQuery } from "./AssetsFilter/types"; import { AssetsViewScopeConfiguration } from "./AssetsViewScopeConfiguration"; import { AssetScopeOption } from "./AssetsViewScopeConfiguration/types"; import { NoDataMessage } from "./NoDataMessage"; -import { ServicesFilter } from "./ServicesFilter"; import * as s from "./styles"; import { trackingEvents } from "./tracking"; import { DataRefresher } from "./types"; @@ -32,7 +25,6 @@ export const Assets = () => { ); const [searchInputValue, setSearchInputValue] = useState(""); const debouncedSearchInputValue = useDebounce(searchInputValue, 1000); - const [selectedServices, setSelectedServices] = useState(); const [assetScopeOption, setAssetScopeOption] = useState(null); const [selectedFilters, setSelectedFilters] = useState(); @@ -43,30 +35,7 @@ export const Assets = () => { const [assetListDataRefresher, setAssetListRefresher] = useState(null); - const isServiceFilterVisible = getFeatureFlagValue( - config, - FeatureFlag.IS_ASSETS_SERVICE_FILTER_VISIBLE - ); - - const isComplexFilterEnabled = getFeatureFlagValue( - config, - FeatureFlag.IS_ASSETS_COMPLEX_FILTER_ENABLED - ); - - const isBackendUpgradeMessageVisible = useMemo(() => { - const backendVersion = config.backendInfo?.applicationVersion; - - return Boolean( - backendVersion && - valid(backendVersion) && - lt( - backendVersion, - featureFlagMinBackendVersions[ - FeatureFlag.IS_ASSETS_COMPLEX_FILTER_ENABLED - ] - ) - ); - }, [config]); + const isBackendUpgradeMessageVisible = false; useEffect(() => { if (!config.scope?.span) { @@ -78,7 +47,6 @@ export const Assets = () => { if (!previousScope || previousScope !== config.scope?.span) { setSelectedAssetTypeId(null); setSearchInputValue(""); - setSelectedServices(undefined); } }, [config.scope, previousScope]); @@ -94,10 +62,6 @@ export const Assets = () => { setSelectedAssetTypeId(assetTypeId); }; - const handleServicesChange = (services: string[]) => { - setSelectedServices(services); - }; - const handleApplyFilters = (filters: AssetFilterQuery) => { setSelectedFilters(filters); }; @@ -147,7 +111,7 @@ export const Assets = () => { return ; } - if (!selectedFilters && !selectedServices) { + if (!selectedFilters) { return ; } @@ -155,7 +119,6 @@ export const Assets = () => { return ( { { )} - {window.assetsSearch === true && ( - - )} - {isComplexFilterEnabled ? ( - - ) : ( - // TODO: Remove this clause when the feature flag is removed - isServiceFilterVisible && ( - - ) - )} + + - (isComplexFilterEnabled - ? filters && - [...filters.insights, ...filters.operations, ...filters.services].length > - 0 - : services && services.length > 0) || searchQuery.length > 0; + (filters && + [...filters.insights, ...filters.operations, ...filters.services].length > + 0) || + searchQuery.length > 0; diff --git a/src/components/Dashboard/index.tsx b/src/components/Dashboard/index.tsx index 87813d28a..ab69eee79 100644 --- a/src/components/Dashboard/index.tsx +++ b/src/components/Dashboard/index.tsx @@ -3,10 +3,8 @@ import { Helmet } from "react-helmet"; import { useTheme } from "styled-components"; import { actions as globalActions } from "../../actions"; import { dispatcher } from "../../dispatcher"; -import { getFeatureFlagValue } from "../../featureFlags"; import { platform } from "../../platform"; import { isString } from "../../typeGuards/isString"; -import { FeatureFlag } from "../../types"; import { openURLInDefaultBrowser } from "../../utils/actions/openURLInDefaultBrowser"; import { sendTrackingEvent } from "../../utils/actions/sendTrackingEvent"; import { formatEnvironmentName } from "../../utils/formatEnvironmentName"; @@ -38,11 +36,6 @@ export const Dashboard = () => { platform === "Web" ? "" : formatEnvironmentName(environment) ); - const isClientSpansOverallImpactEnabled = getFeatureFlagValue( - config, - FeatureFlag.IS_DASHBOARD_CLIENT_SPANS_OVERALL_IMPACT_ENABLED - ); - const handleOpenInBrowserLinkClick = () => { const hostname = new URL(config.digmaApiUrl).hostname; const digmaUiUrl = `http://${hostname}:${DIGMA_UI_DEFAULT_PORT}`; @@ -141,9 +134,7 @@ export const Dashboard = () => { ) : ( <> - {isClientSpansOverallImpactEnabled && ( - - )} + )} diff --git a/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/GetEnvironmentIdInstruction.stories.tsx b/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/GetEnvironmentIdInstruction.stories.tsx new file mode 100644 index 000000000..83f7e058a --- /dev/null +++ b/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/GetEnvironmentIdInstruction.stories.tsx @@ -0,0 +1,20 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { GetEnvironmentIdInstruction } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Documentation/GetEnvironmentIdInstruction", + component: GetEnvironmentIdInstruction, + 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; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Default: Story = {}; diff --git a/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/index.tsx b/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/index.tsx new file mode 100644 index 000000000..0d2f2695f --- /dev/null +++ b/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/index.tsx @@ -0,0 +1,48 @@ +import { useTheme } from "styled-components"; +import { getThemeKind } from "../../../../common/App/styles"; +import { SectionNumber } from "../Page/styles"; +import * as s from "./styles"; + +export const GetEnvironmentIdInstruction = () => { + const theme = useTheme(); + const themeKind = getThemeKind(theme); + + const steps = [ + { + id: "how-to-setup-menu-item", + description: ( + + Click on the environment options menu in the observability panel and + select How to setup + + ), + image: ( + + ) + }, + { + id: "copy-environment-id", + description: ( + Copy the Environment ID value from the instructions page + ), + image: + } + ]; + + return ( + + + Follow the steps to get your Environment ID + + {steps.map((x, i) => ( + + {i + 1} + + {x.description} + {x.image} + + + ))} + + ); +}; diff --git a/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/styles.ts b/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/styles.ts new file mode 100644 index 000000000..6ea99bd34 --- /dev/null +++ b/src/components/Documentation/pages/RunDigma/GetEnvironmentIdInstruction.tsx/styles.ts @@ -0,0 +1,38 @@ +import styled from "styled-components"; +import { + footnoteRegularTypography, + subheadingBoldTypography +} from "../../../../common/App/typographies"; + +export const Container = styled.div` + display: flex; + gap: 16px; + padding: 16px; + border-radius: 4px; + background: ${({ theme }) => theme.colors.v3.surface.primary}; + + & > * { + flex: 1 1 0; + } +`; + +export const Section = styled.div` + display: flex; + flex-direction: column; + gap: 8px; +`; + +export const TitleSection = styled(Section)` + ${subheadingBoldTypography} + + color: ${({ theme }) => theme.colors.v3.text.primary}; + padding: 16px 0 24px; +`; + +export const SectionContent = styled.div` + ${footnoteRegularTypography} + + display: flex; + flex-direction: column; + gap: 12px; +`; diff --git a/src/components/Documentation/pages/RunDigma/runDigmaWithCommandLine.tsx b/src/components/Documentation/pages/RunDigma/runDigmaWithCommandLine.tsx index 6bd1f2840..8c5a1d18f 100644 --- a/src/components/Documentation/pages/RunDigma/runDigmaWithCommandLine.tsx +++ b/src/components/Documentation/pages/RunDigma/runDigmaWithCommandLine.tsx @@ -1,4 +1,5 @@ import { CodeSnippet } from "../../../common/CodeSnippet"; +import { GetEnvironmentIdInstruction } from "./GetEnvironmentIdInstruction.tsx"; import { PageContent } from "./Page/types"; export const runDigmaWithCommandLine: PageContent = { @@ -40,7 +41,7 @@ export const runDigmaWithCommandLine: PageContent = { `} language={"xml"} - > + /> To collect data with Digma when you run your application from command line you should now run: @@ -114,13 +115,16 @@ curl --create-dirs -O -L --output-dir ./otel https://github.com/digma-ai/otel-ja export JAVA_TOOL_OPTIONS="-javaagent:/otel/opentelemetry-javaagent.jar -Dotel.exporter.otlp.endpoint=http://localhost:5050 -Dotel.javaagent.extensions=/otel/digma-otel-agent-extension.jar -Dotel.metrics.exporter=none -Dotel.logs.exporter=none -Dotel.exporter.otlp.protocol=grpc" export OTEL_SERVICE_NAME={--ENTER YOUR SERVICE NAME HERE--} -export OTEL_RESOURCE_ATTRIBUTES=digma.environment=LOCAL +export OTEL_RESOURCE_ATTRIBUTES=digma.environment.id={--ENTER YOUR ENVIRONMENT ID HERE--} java app.jar`} language={"bash"} /> ) + }, + { + content: } ] }; diff --git a/src/components/Documentation/pages/RunDigma/runDigmaWithDocker.tsx b/src/components/Documentation/pages/RunDigma/runDigmaWithDocker.tsx index 92ac1e3b4..adfbb376e 100644 --- a/src/components/Documentation/pages/RunDigma/runDigmaWithDocker.tsx +++ b/src/components/Documentation/pages/RunDigma/runDigmaWithDocker.tsx @@ -1,4 +1,5 @@ import { CodeSnippet } from "../../../common/CodeSnippet"; +import { GetEnvironmentIdInstruction } from "./GetEnvironmentIdInstruction.tsx"; import { PageContent } from "./Page/types"; export const runDigmaWithDocker: PageContent = { @@ -58,7 +59,7 @@ curl --create-dirs -O -L --output-dir ./otel https://github.com/digma-ai/otel-ja environment: - JAVA_TOOL_OPTIONS=-javaagent:/otel/opentelemetry-javaagent.jar -Dotel.exporter.otlp.endpoint=http://host.docker.internal:5050 -Dotel.javaagent.extensions=/otel/digma-otel-agent-extension.jar -Dotel.metrics.exporter=none -Dotel.logs.exporter=none -Dotel.exporter.otlp.protocol=grpc - OTEL_SERVICE_NAME=#[your-service] - - OTEL_RESOURCE_ATTRIBUTES=digma.environment=DOCKER_LOCAL + - OTEL_RESOURCE_ATTRIBUTES=digma.environment.id=[ENVIRONMENT_ID] - OTEL_METRICS_EXPORTER=none extra_hosts: - "host.docker.internal:host-gateway"`} @@ -79,6 +80,9 @@ curl --create-dirs -O -L --output-dir ./otel https://github.com/digma-ai/otel-ja language={"bash"} /> ) + }, + { + content: } ] }; diff --git a/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx b/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx index c5ed1bb32..f75755d15 100644 --- a/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx +++ b/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx @@ -20,12 +20,14 @@ type Story = StoryObj; export const WaitingForData: Story = { args: { - isLoading: true + type: "loading", + text: "Detected issues will appear here" } }; export const NoData: Story = { args: { - isLoading: false + type: "noData", + text: "No Issues available at the moment" } }; diff --git a/src/components/Highlights/EmptyStateCard/index.tsx b/src/components/Highlights/EmptyStateCard/index.tsx index 3fe679509..d635e6796 100644 --- a/src/components/Highlights/EmptyStateCard/index.tsx +++ b/src/components/Highlights/EmptyStateCard/index.tsx @@ -3,33 +3,34 @@ import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import * as s from "./styles"; import { EmptyStateCardProps } from "./types"; -export const EmptyStateCard = ({ isLoading }: EmptyStateCardProps) => { +export const EmptyStateCard = ({ type, text }: EmptyStateCardProps) => { const renderContent = () => { - if (isLoading) { - return ( - <> - - - - - Waiting for Data - Detected issues will appear here - - - ); + switch (type) { + case "loading": + return ( + <> + + + + + Waiting for Data + {text} + + + ); + case "noData": + return ( + <> + + + + + No data + {text} + + + ); } - - return ( - <> - - - - - No data - No Issues available at the moment - - - ); }; return ( diff --git a/src/components/Highlights/EmptyStateCard/types.ts b/src/components/Highlights/EmptyStateCard/types.ts index 7aca297c6..21e4d5f6c 100644 --- a/src/components/Highlights/EmptyStateCard/types.ts +++ b/src/components/Highlights/EmptyStateCard/types.ts @@ -1,3 +1,4 @@ export interface EmptyStateCardProps { - isLoading: boolean; + type: "loading" | "noData"; + text: string; } diff --git a/src/components/Highlights/Highlights.stories.tsx b/src/components/Highlights/Highlights.stories.tsx index b356e7aaf..9055c58af 100644 --- a/src/components/Highlights/Highlights.stories.tsx +++ b/src/components/Highlights/Highlights.stories.tsx @@ -2,6 +2,7 @@ import { Meta, StoryObj } from "@storybook/react"; import { Highlights } from "."; import { actions as mainActions } from "../Main/actions"; +import { mockedPerformanceData } from "./Performance/mockData"; import { mockedTopIssuesData } from "./TopIssues/mockData"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction @@ -28,8 +29,13 @@ export const Default: Story = { action: mainActions.SET_HIGHLIGHTS_TOP_ISSUES_DATA, payload: mockedTopIssuesData }); - }); - }, 1000); + window.postMessage({ + type: "digma", + action: mainActions.SET_HIGHLIGHTS_PERFORMANCE_DATA, + payload: mockedPerformanceData + }); + }, 1000); + }); } }; @@ -42,7 +48,12 @@ export const Empty: Story = { action: mainActions.SET_HIGHLIGHTS_TOP_ISSUES_DATA, payload: { topInsights: [] } }); - }); - }, 1000); + window.postMessage({ + type: "digma", + action: mainActions.SET_HIGHLIGHTS_PERFORMANCE_DATA, + payload: { performance: [] } + }); + }, 1000); + }); } }; diff --git a/src/components/Highlights/Performance/Performance.stories.tsx b/src/components/Highlights/Performance/Performance.stories.tsx new file mode 100644 index 000000000..43b1e4f0b --- /dev/null +++ b/src/components/Highlights/Performance/Performance.stories.tsx @@ -0,0 +1,47 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { Performance } from "."; +import { actions } from "../../Main/actions"; +import { mockedPerformanceData } from "./mockData"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Highlights/Performance", + component: Performance, + 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; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args + +export const Default: Story = { + play: () => { + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_HIGHLIGHTS_PERFORMANCE_DATA, + payload: mockedPerformanceData + }); + }); + } +}; + +export const Loading: Story = {}; + +export const Empty: Story = { + play: () => { + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_HIGHLIGHTS_PERFORMANCE_DATA, + payload: { performance: [] } + }); + }); + } +}; diff --git a/src/components/Highlights/Performance/index.tsx b/src/components/Highlights/Performance/index.tsx new file mode 100644 index 000000000..f1e11265e --- /dev/null +++ b/src/components/Highlights/Performance/index.tsx @@ -0,0 +1,153 @@ +import { Row, createColumnHelper } from "@tanstack/react-table"; +import { useContext, useEffect, useState } from "react"; +import { usePrevious } from "../../../hooks/usePrevious"; +import { isBoolean } from "../../../typeGuards/isBoolean"; +import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; +import { formatTimeDistance } from "../../../utils/formatTimeDistance"; +import { getDurationString } from "../../../utils/getDurationString"; +import { ConfigContext } from "../../common/App/ConfigContext"; +import { Card } from "../../common/v3/Card"; +import { Tag } from "../../common/v3/Tag"; +import { EmptyStateCard } from "../EmptyStateCard"; +import { EnvironmentName } from "../common/EnvironmentName"; +import { Section } from "../common/Section"; +import { Table } from "../common/Table"; +import { handleEnvironmentTableRowClick } from "../handleEnvironmentTableRowClick"; +import { trackingEvents } from "../tracking"; +import * as s from "./styles"; +import { EnvironmentPerformanceData } from "./types"; +import { usePerformanceData } from "./usePerformanceData"; + +export const Performance = () => { + const [isInitialLoading, setIsInitialLoading] = useState(true); + const { data, getData } = usePerformanceData(); + const previousData = usePrevious(data); + const config = useContext(ConfigContext); + + useEffect(() => { + getData(); + }, []); + + useEffect(() => { + if (!previousData && data) { + setIsInitialLoading(false); + } + }, [previousData, data]); + + const renderPerformanceCard = (data: EnvironmentPerformanceData[]) => { + const columnHelper = createColumnHelper(); + + const columns = [ + columnHelper.accessor("environment", { + header: "Env", + cell: (info) => { + const environment = info.getValue(); + return ; + } + }), + columnHelper.accessor((x) => x, { + header: "Median", + cell: (info) => { + const value = info.getValue(); + const percentileData = value.p50; + const durationString = getDurationString(percentileData.duration); + const tagType = isBoolean(percentileData.isCritical) + ? percentileData.isCritical + ? "highSeverity" + : "success" + : undefined; + + return ( + + ); + } + }), + columnHelper.accessor((x) => x, { + header: "Slowest 5%", + cell: (info) => { + const value = info.getValue(); + const percentileData = value.p95; + const durationString = getDurationString(percentileData.duration); + const tagType = isBoolean(percentileData.isCritical) + ? percentileData.isCritical + ? "highSeverity" + : "success" + : undefined; + + return ( + + ); + } + }), + columnHelper.accessor("lastCallTimeStamp", { + header: "Last", + cell: (info) => { + const lastCallDateTime = info.getValue(); + + if (!lastCallDateTime) { + return null; + } + + const value = formatTimeDistance(lastCallDateTime, { + format: "short", + withDescriptiveWords: false + }).replace(" ", ""); + const title = new Date(lastCallDateTime).toString(); + + return ( + {value} + ); + } + }) + ]; + + const handleTableRowClick = (row: Row) => { + sendUserActionTrackingEvent( + trackingEvents.PERFORMANCE_CARD_TABLE_ROW_CLICKED + ); + handleEnvironmentTableRowClick( + config.environments, + row.original.environment.id, + "analytics" + ); + }; + + return ( + Performance} + content={ + + columns={columns} + data={data} + onRowClick={handleTableRowClick} + /> + } + /> + ); + }; + + return ( +
+ {data && data.performance.length > 0 ? ( + renderPerformanceCard(data.performance) + ) : ( + + )} +
+ ); +}; diff --git a/src/components/Highlights/Performance/mockData.ts b/src/components/Highlights/Performance/mockData.ts new file mode 100644 index 000000000..eb0aa3a42 --- /dev/null +++ b/src/components/Highlights/Performance/mockData.ts @@ -0,0 +1,140 @@ +import { PerformanceData } from "./types"; + +export const mockedPerformanceData: PerformanceData = { + performance: [ + { + environment: { + name: "LOCAL-TESTS", + id: "#DIGMA#TESTS#CODELENSTESTS-SHOW_RUNTIMEDATA_WHENMETHODINSIGHTSWITHOUTDECORATORS-2024/03/04-14:52:41[LOCAL-TESTS]", + type: "Public" + }, + p50: { + duration: { + value: 20.0, + unit: "ms", + raw: 20000000.0 + }, + isCritical: true + }, + p95: { + duration: { + value: 20.0, + unit: "ms", + raw: 20000000.0 + }, + isCritical: false + }, + lastCallTimeStamp: null + }, + { + environment: { + name: "LOCAL-TESTS", + id: "#DIGMA#TESTS#SPANDURATIONINSIGHTTESTS-SANITY-2024/03/26-16:45:40[LOCAL-TESTS]", + type: "Public" + }, + p50: { + duration: { + value: 7.94, + unit: "ms", + raw: 7944704.0 + } + }, + p95: { + duration: { + value: 19.88, + unit: "ms", + raw: 19880704.0 + } + }, + lastCallTimeStamp: "2024-03-26T14:41:30.481486Z" + }, + { + environment: { + name: "LOCAL-TESTS", + id: "#DIGMA#TESTS#CODELENSTESTS-SHOW_RUNTIMEDATA_WHENMETHODINSIGHTSWITHOUTDECORATORS-2024/03/14-13:54:22[LOCAL-TESTS]", + type: "Public" + }, + p50: { + duration: { + value: 20.0, + unit: "ms", + raw: 20000000.0 + } + }, + p95: { + duration: { + value: 20.0, + unit: "ms", + raw: 20000000.0 + } + }, + lastCallTimeStamp: "2024-03-14T11:53:22.708519Z" + }, + { + environment: { + name: "LOCAL-TESTS", + id: "#DIGMA#TESTS#SPANDURATIONINSIGHTTESTS-SANITY-2024/03/14-13:44:43[LOCAL-TESTS]", + type: "Public" + }, + p50: { + duration: { + value: 7.94, + unit: "ms", + raw: 7935744.0 + } + }, + p95: { + duration: { + value: 8.71, + unit: "ms", + raw: 8711488.0 + } + }, + lastCallTimeStamp: "2024-03-14T11:40:33.160219Z" + }, + { + environment: { + name: "LOCAL-TESTS", + id: "#DIGMA#TESTS#DEACTIVATEINSIGHTSJOBTESTS-SANITY-2024/03/14-13:41:38[LOCAL-TESTS]", + type: "Public" + }, + p50: { + duration: { + value: 97.66, + unit: "ms", + raw: 97664512.0 + } + }, + p95: { + duration: { + value: 107.43, + unit: "ms", + raw: 107425280.0 + } + }, + lastCallTimeStamp: "2024-03-14T11:41:40.11119Z" + }, + { + environment: { + name: "LOCAL-TESTS", + id: "#DIGMA#TESTS#LIVEDATATESTS-CHECKLIVEDATA-2024/03/14-13:54:33[LOCAL-TESTS]", + type: "Public" + }, + p50: { + duration: { + value: 20.05, + unit: "ms", + raw: 20054272.0 + } + }, + p95: { + duration: { + value: 21.73, + unit: "ms", + raw: 21732864.0 + } + }, + lastCallTimeStamp: "2024-03-14T09:54:43.097589Z" + } + ] +}; diff --git a/src/components/Highlights/Performance/styles.ts b/src/components/Highlights/Performance/styles.ts new file mode 100644 index 000000000..24d4b2a1d --- /dev/null +++ b/src/components/Highlights/Performance/styles.ts @@ -0,0 +1,11 @@ +import styled from "styled-components"; +import { bodySemiboldTypography } from "../../common/App/typographies"; +import { TableText } from "../common/TableText"; + +export const CardTitle = styled.div` + ${bodySemiboldTypography} +`; + +export const LastCallTableText = styled(TableText)` + color: ${({ theme }) => theme.colors.v3.text.secondary}; +`; diff --git a/src/components/Highlights/Performance/types.ts b/src/components/Highlights/Performance/types.ts new file mode 100644 index 000000000..2e49ee50a --- /dev/null +++ b/src/components/Highlights/Performance/types.ts @@ -0,0 +1,27 @@ +import { Duration } from "../../../globals"; +import { EnvironmentType } from "../../common/App/types"; + +interface PerformancePercentileData { + duration: Duration; + isCritical?: boolean; +} + +export type EnvironmentPerformanceData = { + environment: { + name: string; + id: string; + type: EnvironmentType; + }; + p50: PerformancePercentileData; + p95: PerformancePercentileData; + lastCallTimeStamp: string | null; +}; + +export type PerformanceData = { performance: EnvironmentPerformanceData[] }; + +export interface GetHighlightsPerformanceDataPayload { + query: { + scopedSpanCodeObjectId: string | null; + environments: string[]; + }; +} diff --git a/src/components/Highlights/Performance/usePerformanceData.ts b/src/components/Highlights/Performance/usePerformanceData.ts new file mode 100644 index 000000000..eca694ab0 --- /dev/null +++ b/src/components/Highlights/Performance/usePerformanceData.ts @@ -0,0 +1,71 @@ +import { useCallback, useContext, useEffect, useRef, useState } from "react"; +import { dispatcher } from "../../../dispatcher"; +import { usePrevious } from "../../../hooks/usePrevious"; +import { actions as mainActions } from "../../Main/actions"; +import { ConfigContext } from "../../common/App/ConfigContext"; +import { GetHighlightsPerformanceDataPayload, PerformanceData } from "./types"; +const REFRESH_INTERVAL = 10 * 1000; // in milliseconds + +export const usePerformanceData = () => { + const [data, setData] = useState(); + const config = useContext(ConfigContext); + const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); + const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); + const refreshTimerId = useRef(); + + const getData = useCallback(() => { + window.sendMessageToDigma({ + action: mainActions.GET_HIGHLIGHTS_PERFORMANCE_DATA, + payload: { + query: { + scopedSpanCodeObjectId: config.scope?.span?.spanCodeObjectId || null, + environments: config.environments?.map((x) => x.id) || [] + } + } + }); + }, [config.scope?.span?.spanCodeObjectId, config.environments]); + const previousGetData = usePrevious(getData); + + useEffect(() => { + if (previousGetData && previousGetData !== getData) { + window.clearTimeout(refreshTimerId.current); + + getData(); + } + }, [previousGetData, getData]); + + useEffect(() => { + if ( + previousLastSetDataTimeStamp && + previousLastSetDataTimeStamp !== lastSetDataTimeStamp + ) { + refreshTimerId.current = window.setTimeout(() => { + getData(); + }, REFRESH_INTERVAL); + } + }, [previousLastSetDataTimeStamp, lastSetDataTimeStamp, getData]); + + useEffect(() => { + const handlePerformanceData = (data: any, timeStamp: number) => { + setData(data as PerformanceData); + setLastSetDataTimeStamp(timeStamp); + }; + + dispatcher.addActionListener( + mainActions.SET_HIGHLIGHTS_PERFORMANCE_DATA, + handlePerformanceData + ); + + return () => { + dispatcher.removeActionListener( + mainActions.SET_HIGHLIGHTS_PERFORMANCE_DATA, + handlePerformanceData + ); + }; + }, []); + + return { + data, + getData + }; +}; diff --git a/src/components/Highlights/TopIssues/common/HighlightCard/index.tsx b/src/components/Highlights/TopIssues/common/HighlightCard/index.tsx index 040b93209..f912e6289 100644 --- a/src/components/Highlights/TopIssues/common/HighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/common/HighlightCard/index.tsx @@ -1,7 +1,6 @@ import { getInsightTypeInfo } from "../../../../../utils/getInsightTypeInfo"; -import { InfoCircleIcon } from "../../../../common/icons/InfoCircleIcon"; import { Card } from "../../../../common/v3/Card"; -import { Tooltip } from "../../../../common/v3/Tooltip"; +import { Info } from "../../../../common/v3/Info"; import * as s from "./styles"; import { HighlightCardProps } from "./types"; @@ -14,11 +13,7 @@ export const HighlightCard = ({ highlight, content }: HighlightCardProps) => { {insightTypeInfo?.label} {insightTypeInfo?.description && ( - }> - - - - + } /> )} } diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx index f7d2d1618..04e9d9a5c 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx @@ -1,16 +1,18 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useContext } from "react"; import { Duration } from "../../../../../globals"; +import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { ConfigContext } from "../../../../common/App/ConfigContext"; +import { Tag } from "../../../../common/v3/Tag"; import { Table } from "../../../common/Table"; -import { TableTag } from "../../../common/TableTag"; import { TableText } from "../../../common/TableText"; +import { handleEnvironmentTableRowClick } from "../../../handleEnvironmentTableRowClick"; +import { trackingEvents } from "../../../tracking"; import { AssetLink } from "../../common/AssetLink"; import { HighlightCard } from "../../common/HighlightCard"; import { EndpointBottleneckMetrics, EnvironmentData } from "../../types"; import { addEnvironmentColumns } from "../addEnvironmentColumns"; -import { handleEnvironmentTableRowClick } from "../goToEnvironmentIssues"; import { DescriptionContainer } from "../styles"; import { EndpointBottleneckHighlightCardProps } from "./types"; @@ -54,7 +56,7 @@ export const EndpointBottleneckHighlightCard = ({ const value = metric ? getDurationString(metric.value as Duration) : ""; - return metric ? : null; + return metric ? : null; } } ) @@ -65,10 +67,16 @@ export const EndpointBottleneckHighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/mockData.ts index e10cbb442..a169a35c7 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/mockData.ts @@ -26,41 +26,46 @@ export const mockedEndpointBottleneckHighlightData: HighlightData> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/mockData.ts index b8f3f3af4..3f6bdfee9 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/mockData.ts @@ -17,41 +17,46 @@ export const mockedEndpointChattyApiV2HighlightData: HighlightData> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/mockData.ts index 5318dd0e9..1a89ff70e 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/mockData.ts @@ -22,41 +22,46 @@ export const mockedEndpointHighNumberOfQueriesHighlightData: HighlightData { const metric = info.getValue(); const value = metric ? getDurationString(metric.value) : ""; - return metric ? : null; + return metric ? : null; } }) ]; @@ -39,10 +41,16 @@ export const EndpointQueryOptimizationV2HighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/mockData.ts index 6adf78460..92fa6f2af 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/mockData.ts @@ -22,41 +22,46 @@ export const mockedEndpointQueryHighLightData: HighlightData> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/mockData.ts index 2bd2bf06e..4dc99c61b 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/mockData.ts @@ -13,41 +13,46 @@ export const mockedEndpointSessionInViewHighlightData: HighlightData { const metric = info.getValue(); const value = metric ? getDurationString(metric.value) : ""; - return metric ? : null; + return metric ? : null; } } ) @@ -39,10 +41,16 @@ export const EndpointSlowdownSourceHighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/mockData.ts index e2bca6ada..b64136587 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/mockData.ts @@ -22,41 +22,46 @@ export const mockedEndpointSlowdownSourceHighlightData: HighlightData { const metric = info.getValue(); const value = metric ? getDurationString(metric.value as Duration) : ""; - return metric ? : null; + return metric ? : null; } }) ]; @@ -57,10 +59,16 @@ export const EndpointSpanNPlusOneHighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/mockData.ts index ad36c2963..ad90cae1d 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/mockData.ts @@ -26,41 +26,46 @@ export const mockedEndpointSpanNPlusOneHighlightData: HighlightData { @@ -28,10 +30,16 @@ export const HotSpotHighlightCard = ({ data }: HotSpotHighlightCardProps) => { const columns = addEnvironmentColumns(columnHelper, metricsColumns); const handleTableRowClick = (row: Row>) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/mockData.ts index e770a51fb..9dae47319 100644 --- a/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/mockData.ts @@ -16,41 +16,46 @@ export const mockedHotSpotHighlightData: HighlightData = { instrumentationLibrary: "instrumentationLibrary", spanCodeObjectId: "spanCodeObjectId", methodCodeObjectId: "methodCodeObjectId", - kind: "kind", - codeObjectId: null + kind: "kind" }, environments: [ { + environmentId: "1", environmentName: "Dev", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedHotSpotMetrics }, { + environmentId: "2", environmentName: "Staging", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedHotSpotMetrics }, { + environmentId: "3", environmentName: "Production", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedHotSpotMetrics }, { + environmentId: "4", environmentName: "Env1", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedHotSpotMetrics }, { + environmentId: "5", environmentName: "Env2", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedHotSpotMetrics }, { + environmentId: "6", environmentName: "Env3", insightStatus: InsightStatus.Active, criticality: 0.8, diff --git a/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx index 29ce0fb4a..9d5c28488 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx @@ -1,15 +1,17 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useContext } from "react"; import { Duration } from "../../../../../globals"; +import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { ConfigContext } from "../../../../common/App/ConfigContext"; +import { Tag } from "../../../../common/v3/Tag"; import { Table } from "../../../common/Table"; -import { TableTag } from "../../../common/TableTag"; import { TableText } from "../../../common/TableText"; +import { handleEnvironmentTableRowClick } from "../../../handleEnvironmentTableRowClick"; +import { trackingEvents } from "../../../tracking"; import { HighlightCard } from "../../common/HighlightCard"; import { EnvironmentData, SpaNPlusOneMetrics } from "../../types"; import { addEnvironmentColumns } from "../addEnvironmentColumns"; -import { handleEnvironmentTableRowClick } from "../goToEnvironmentIssues"; import { SpaNPlusOneHighlightCardProps } from "./types"; export const SpaNPlusOneHighlightCard = ({ @@ -56,7 +58,7 @@ export const SpaNPlusOneHighlightCard = ({ cell: (info) => { const metric = info.getValue(); const value = metric ? getDurationString(metric.value as Duration) : ""; - return metric ? : null; + return metric ? : null; } }) ]; @@ -66,10 +68,16 @@ export const SpaNPlusOneHighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/mockData.ts index 3ee3b8992..8ffbac861 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/mockData.ts @@ -27,41 +27,46 @@ export const mockedSpaNPlusOneHighlightData: HighlightData = instrumentationLibrary: "instrumentationLibrary", spanCodeObjectId: "spanCodeObjectId", methodCodeObjectId: "methodCodeObjectId", - kind: "kind", - codeObjectId: null + kind: "kind" }, environments: [ { + environmentId: "1", environmentName: "Dev", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpaNPlusOneInsights }, { + environmentId: "2", environmentName: "Staging", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpaNPlusOneInsights }, { + environmentId: "3", environmentName: "Production", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpaNPlusOneInsights }, { + environmentId: "4", environmentName: "Env1", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpaNPlusOneInsights }, { + environmentId: "5", environmentName: "Env2", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpaNPlusOneInsights }, { + environmentId: "6", environmentName: "Env3", insightStatus: InsightStatus.Active, criticality: 0.8, diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx index 80685de4d..111f2ab26 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx @@ -1,15 +1,17 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useContext } from "react"; import { Duration } from "../../../../../globals"; +import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { ConfigContext } from "../../../../common/App/ConfigContext"; +import { Tag } from "../../../../common/v3/Tag"; import { Table } from "../../../common/Table"; -import { TableTag } from "../../../common/TableTag"; import { TableText } from "../../../common/TableText"; +import { handleEnvironmentTableRowClick } from "../../../handleEnvironmentTableRowClick"; +import { trackingEvents } from "../../../tracking"; import { HighlightCard } from "../../common/HighlightCard"; import { EnvironmentData, SpanEndpointBottleneckMetrics } from "../../types"; import { addEnvironmentColumns } from "../addEnvironmentColumns"; -import { handleEnvironmentTableRowClick } from "../goToEnvironmentIssues"; import { SpanEndpointBottleneckHighlightCardProps } from "./types"; export const SpanEndpointBottleneckHighlightCard = ({ @@ -52,7 +54,7 @@ export const SpanEndpointBottleneckHighlightCard = ({ const value = metric ? getDurationString(metric.value as Duration) : ""; - return metric ? : null; + return metric ? : null; } } ) @@ -63,10 +65,16 @@ export const SpanEndpointBottleneckHighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/mockData.ts index e3393c02c..bd78a9cb7 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/mockData.ts @@ -27,41 +27,46 @@ export const mockedSpanEndpointBottleneckHighlightData: HighlightData { const metric = info.getValue(); const value = metric ? getDurationString(metric.value as Duration) : ""; - return metric ? : null; + return metric ? : null; } }), columnHelper.accessor( @@ -51,7 +53,7 @@ export const SpanQueryOptimizationHighlightCard = ({ const value = metric ? getDurationString(metric.value as Duration) : ""; - return metric ? : null; + return metric ? : null; } } ), @@ -70,10 +72,16 @@ export const SpanQueryOptimizationHighlightCard = ({ const handleTableRowClick = ( row: Row> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/mockData.ts index f3b0a0fc8..e93c359d0 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/mockData.ts @@ -35,41 +35,46 @@ export const mockedSpanQueryOptimizationHighlightData: HighlightData> ) => { + sendUserActionTrackingEvent( + trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, + { + insightType: data.insightType + } + ); handleEnvironmentTableRowClick( config.environments, - row.original.environmentName, - data.insightType + row.original.environmentId, + "insights" ); }; diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/mockData.ts b/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/mockData.ts index 64dac789e..f76d36df2 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/mockData.ts +++ b/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/mockData.ts @@ -17,41 +17,46 @@ export const mockedSpanScalingHighlightData: HighlightData = instrumentationLibrary: "instrumentationLibrary", spanCodeObjectId: "spanCodeObjectId", methodCodeObjectId: "methodCodeObjectId", - kind: "kind", - codeObjectId: null + kind: "kind" }, environments: [ { + environmentId: "1", environmentName: "Dev", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpanScalingMetrics }, { + environmentId: "2", environmentName: "Staging", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpanScalingMetrics }, { + environmentId: "3", environmentName: "Production", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpanScalingMetrics }, { + environmentId: "4", environmentName: "Env1", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpanScalingMetrics }, { + environmentId: "5", environmentName: "Env2", insightStatus: InsightStatus.Active, criticality: 0.8, metrics: mockedSpanScalingMetrics }, { + environmentId: "6", environmentName: "Env3", insightStatus: InsightStatus.Active, criticality: 0.8, diff --git a/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx b/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx index 63750f011..5aa07edf9 100644 --- a/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx @@ -14,7 +14,12 @@ export const addEnvironmentColumns = < header: "Env", cell: (info) => { const environmentData = info.getValue(); - return ; + return ( + + ); } }), ...columns, diff --git a/src/components/Highlights/TopIssues/highlightCards/goToEnvironmentIssues.ts b/src/components/Highlights/TopIssues/highlightCards/goToEnvironmentIssues.ts deleted file mode 100644 index 1b231e6c9..000000000 --- a/src/components/Highlights/TopIssues/highlightCards/goToEnvironmentIssues.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { actions as globalActions } from "../../../../actions"; -import { - ChangeEnvironmentPayload, - ChangeViewPayload, - InsightType -} from "../../../../types"; -import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; -import { Environment } from "../../../common/App/types"; -import { trackingEvents } from "../../tracking"; - -export const handleEnvironmentTableRowClick = ( - environments: Environment[] | undefined, - environmentNameToSelect: string, - insightType: InsightType -) => { - sendUserActionTrackingEvent( - trackingEvents.TOP_ISSUES_CARD_TABLE_ROW_CLICKED, - { - insightType - } - ); - - const environmentChangeTo = environments?.find( - (x) => x.originalName === environmentNameToSelect - ); - - if (environmentChangeTo) { - window.sendMessageToDigma({ - action: globalActions.CHANGE_ENVIRONMENT, - payload: { - environment: environmentChangeTo - } - }); - - window.sendMessageToDigma({ - action: globalActions.CHANGE_VIEW, - payload: { - view: "insights" - } - }); - } -}; diff --git a/src/components/Highlights/TopIssues/index.tsx b/src/components/Highlights/TopIssues/index.tsx index d4af69baf..7ed744490 100644 --- a/src/components/Highlights/TopIssues/index.tsx +++ b/src/components/Highlights/TopIssues/index.tsx @@ -5,7 +5,7 @@ import { ChangeViewPayload } from "../../../types"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { Link } from "../../common/v3/Link"; import { EmptyStateCard } from "../EmptyStateCard"; -import { SectionHeader } from "../styles"; +import { Section } from "../common/Section"; import { trackingEvents } from "../tracking"; import { EndpointBottleneckHighlightCard } from "./highlightCards/EndpointBottleneckHighlightCard"; import { EndpointChattyApiV2HighlightCard } from "./highlightCards/EndpointChattyApiV2HighlightCard"; @@ -19,7 +19,6 @@ import { SpaNPlusOneHighlightCard } from "./highlightCards/SpaNPlusOneHighlightC import { SpanEndpointBottleneckHighlightCard } from "./highlightCards/SpanEndpointBottleneckHighlightCard"; import { SpanQueryOptimizationHighlightCard } from "./highlightCards/SpanQueryOptimizationHighlightCard"; import { SpanScalingHighlightCard } from "./highlightCards/SpanScalingHighlightCard"; -import * as s from "./styles"; import { isEndpointBottleneckHighlight, isEndpointChattyApiV2Highlight, @@ -116,20 +115,28 @@ export const TopIssues = () => { const isViewAllLinkDisabled = (data?.topInsights || []).length === 0; return ( - - - Top Issues +
View all - + } + > {data && data.topInsights.length > 0 ? ( data.topInsights.map((x) => ( {renderHighlightCard(x)} )) ) : ( - + )} - +
); }; diff --git a/src/components/Highlights/TopIssues/mockData.ts b/src/components/Highlights/TopIssues/mockData.ts index 199aea52f..31650aa8c 100644 --- a/src/components/Highlights/TopIssues/mockData.ts +++ b/src/components/Highlights/TopIssues/mockData.ts @@ -1,6 +1,12 @@ +import { mockedEndpointChattyApiV2HighlightData } from "./highlightCards/EndpointChattyApiV2HighlightCard/mockData"; +import { mockedEndpointHighNumberOfQueriesHighlightData } from "./highlightCards/EndpointHighNumberOfQueriesHighlightCard/mockData"; import { mockedSpanScalingHighlightData } from "./highlightCards/SpanScalingHighlightCard/mockData"; import { TopIssuesData } from "./types"; export const mockedTopIssuesData: TopIssuesData = { - topInsights: [mockedSpanScalingHighlightData] + topInsights: [ + mockedSpanScalingHighlightData, + mockedEndpointHighNumberOfQueriesHighlightData, + mockedEndpointChattyApiV2HighlightData + ] }; diff --git a/src/components/Highlights/TopIssues/typeGuards.ts b/src/components/Highlights/TopIssues/typeGuards.ts index 169410a4c..1fb797dc5 100644 --- a/src/components/Highlights/TopIssues/typeGuards.ts +++ b/src/components/Highlights/TopIssues/typeGuards.ts @@ -10,8 +10,8 @@ import { GenericMetrics, HighlightData, HotSpotMetrics, - SpanEndpointBottleneckMetrics, SpaNPlusOneMetrics, + SpanEndpointBottleneckMetrics, SpanQueryOptimizationMetrics, SpanScalingMetrics } from "./types"; diff --git a/src/components/Highlights/TopIssues/types.ts b/src/components/Highlights/TopIssues/types.ts index 7a2f6675a..17751d2b8 100644 --- a/src/components/Highlights/TopIssues/types.ts +++ b/src/components/Highlights/TopIssues/types.ts @@ -3,6 +3,7 @@ import { SpanInfo } from "../../../types"; import { InsightStatus, InsightType } from "../../Insights/types"; export interface EnvironmentData { + environmentId: string; environmentName: string; insightStatus: InsightStatus; criticality: number; diff --git a/src/components/Highlights/TopIssues/useTopIssuesData.ts b/src/components/Highlights/TopIssues/useTopIssuesData.ts index 44588936a..0250f9804 100644 --- a/src/components/Highlights/TopIssues/useTopIssuesData.ts +++ b/src/components/Highlights/TopIssues/useTopIssuesData.ts @@ -20,8 +20,7 @@ export const useTopIssuesData = () => { payload: { query: { scopedCodeObjectId: config.scope?.span?.spanCodeObjectId || null, - environments: - config.environments?.map((env) => env.originalName) || [] + environments: config.environments?.map((env) => env.id) || [] } } }); diff --git a/src/components/Highlights/common/EnvironmentName/index.tsx b/src/components/Highlights/common/EnvironmentName/index.tsx index 22087730f..a2fc91dc1 100644 --- a/src/components/Highlights/common/EnvironmentName/index.tsx +++ b/src/components/Highlights/common/EnvironmentName/index.tsx @@ -1,21 +1,24 @@ import { useTheme } from "styled-components"; -import { formatEnvironmentName } from "../../../../utils/formatEnvironmentName"; import { getInsightCriticalityColor } from "../../../../utils/getInsightCriticalityColor"; import { GlobeIcon } from "../../../common/icons/16px/GlobeIcon"; import { Tooltip } from "../../../common/v3/Tooltip"; import * as s from "./styles"; import { EnvironmentNameProps } from "./types"; -export const EnvironmentName = ({ data }: EnvironmentNameProps) => { +export const EnvironmentName = ({ + name, + criticality +}: EnvironmentNameProps) => { const theme = useTheme(); - const iconColor = getInsightCriticalityColor(data.criticality, theme); - const name = formatEnvironmentName(data.environmentName); + const iconColor = criticality + ? getInsightCriticalityColor(criticality, theme) + : undefined; return ( - + {name} diff --git a/src/components/Highlights/common/EnvironmentName/styles.ts b/src/components/Highlights/common/EnvironmentName/styles.ts index b80e6abef..b26e55f45 100644 --- a/src/components/Highlights/common/EnvironmentName/styles.ts +++ b/src/components/Highlights/common/EnvironmentName/styles.ts @@ -10,6 +10,7 @@ export const Container = styled.div` export const IconContainer = styled.div` display: flex; + color: ${({ theme }) => theme.colors.v3.icon.disabled}; `; export const Name = styled.span` diff --git a/src/components/Highlights/common/EnvironmentName/types.ts b/src/components/Highlights/common/EnvironmentName/types.ts index 3f84d4be7..7bf57bfd4 100644 --- a/src/components/Highlights/common/EnvironmentName/types.ts +++ b/src/components/Highlights/common/EnvironmentName/types.ts @@ -1,5 +1,4 @@ -import { EnvironmentData } from "../../TopIssues/types"; - export interface EnvironmentNameProps { - data: EnvironmentData; + name: string; + criticality?: number; } diff --git a/src/components/Highlights/common/Section/index.tsx b/src/components/Highlights/common/Section/index.tsx new file mode 100644 index 000000000..62310a8ed --- /dev/null +++ b/src/components/Highlights/common/Section/index.tsx @@ -0,0 +1,12 @@ +import * as s from "./styles"; +import { SectionProps } from "./types"; + +export const Section = ({ title, toolbarContent, children }: SectionProps) => ( + + + {title} +
{toolbarContent}
+
+ {children} +
+); diff --git a/src/components/Highlights/common/Section/styles.ts b/src/components/Highlights/common/Section/styles.ts new file mode 100644 index 000000000..69f717abe --- /dev/null +++ b/src/components/Highlights/common/Section/styles.ts @@ -0,0 +1,18 @@ +import styled from "styled-components"; +import { subscriptRegularTypography } from "../../../common/App/typographies"; + +export const Container = styled.div` + display: flex; + flex-direction: column; + gap: 8px; +`; + +export const Header = styled.div` + ${subscriptRegularTypography} + + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 4px; + color: ${({ theme }) => theme.colors.v3.text.secondary}; +`; diff --git a/src/components/Highlights/common/Section/types.ts b/src/components/Highlights/common/Section/types.ts new file mode 100644 index 000000000..82e882810 --- /dev/null +++ b/src/components/Highlights/common/Section/types.ts @@ -0,0 +1,7 @@ +import { ReactNode } from "react"; + +export interface SectionProps { + title: string; + toolbarContent?: ReactNode; + children: ReactNode; +} diff --git a/src/components/Highlights/common/TableTag/index.tsx b/src/components/Highlights/common/TableTag/index.tsx deleted file mode 100644 index 06f57357f..000000000 --- a/src/components/Highlights/common/TableTag/index.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Tag } from "../../../common/v3/Tag"; -import { Tooltip } from "../../../common/v3/Tooltip"; -import { TableTagProps } from "./types"; - -export const TableTag = ({ content, title }: TableTagProps) => ( - - - -); diff --git a/src/components/Highlights/common/TableTag/types.ts b/src/components/Highlights/common/TableTag/types.ts deleted file mode 100644 index 81c18e944..000000000 --- a/src/components/Highlights/common/TableTag/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ReactNode } from "react"; - -export interface TableTagProps { - content: ReactNode; - title: string; -} diff --git a/src/components/Highlights/common/TableText/index.tsx b/src/components/Highlights/common/TableText/index.tsx index 4e61fcaa9..19464d51d 100644 --- a/src/components/Highlights/common/TableText/index.tsx +++ b/src/components/Highlights/common/TableText/index.tsx @@ -1,8 +1,8 @@ import { Tooltip } from "../../../common/v3/Tooltip"; import { TableTextProps } from "./types"; -export const TableText = ({ title, children }: TableTextProps) => ( +export const TableText = ({ title, children, className }: TableTextProps) => ( - {children} + {children} ); diff --git a/src/components/Highlights/common/TableText/types.ts b/src/components/Highlights/common/TableText/types.ts index 9516c9bd2..e0ed24cba 100644 --- a/src/components/Highlights/common/TableText/types.ts +++ b/src/components/Highlights/common/TableText/types.ts @@ -3,4 +3,5 @@ import { ReactNode } from "react"; export interface TableTextProps { children: ReactNode; title: string; + className?: string; } diff --git a/src/components/Highlights/handleEnvironmentTableRowClick.ts b/src/components/Highlights/handleEnvironmentTableRowClick.ts new file mode 100644 index 000000000..47adc6c5a --- /dev/null +++ b/src/components/Highlights/handleEnvironmentTableRowClick.ts @@ -0,0 +1,30 @@ +import { actions as globalActions } from "../../actions"; +import { ChangeEnvironmentPayload, ChangeViewPayload } from "../../types"; +import { View } from "../Main/types"; +import { Environment } from "../common/App/types"; + +export const handleEnvironmentTableRowClick = ( + environments: Environment[] | undefined, + environmentIdToSelect: string, + viewToSelect: View +) => { + const environmentChangeTo = environments?.find( + (x) => x.id === environmentIdToSelect + ); + + if (environmentChangeTo) { + window.sendMessageToDigma({ + action: globalActions.CHANGE_ENVIRONMENT, + payload: { + environment: environmentChangeTo.id + } + }); + + window.sendMessageToDigma({ + action: globalActions.CHANGE_VIEW, + payload: { + view: viewToSelect + } + }); + } +}; diff --git a/src/components/Highlights/index.tsx b/src/components/Highlights/index.tsx index 45cabc20c..06e5afc37 100644 --- a/src/components/Highlights/index.tsx +++ b/src/components/Highlights/index.tsx @@ -1,3 +1,4 @@ +import { Performance } from "./Performance"; import { TopIssues } from "./TopIssues"; import * as s from "./styles"; @@ -5,6 +6,7 @@ export const Highlights = () => { return ( + ); }; diff --git a/src/components/Highlights/styles.ts b/src/components/Highlights/styles.ts index 64431b37f..b8fdcdd3a 100644 --- a/src/components/Highlights/styles.ts +++ b/src/components/Highlights/styles.ts @@ -1,29 +1,11 @@ import styled from "styled-components"; -import { subscriptRegularTypography } from "../common/App/typographies"; export const Container = styled.div` display: flex; flex-direction: column; gap: 16px; padding: 16px 8px; - height: 100%; + min-height: 100%; box-sizing: border-box; background: ${({ theme }) => theme.colors.v3.surface.primary}; `; - -export const SectionHeader = styled.div` - ${subscriptRegularTypography} - - display: flex; - justify-content: space-between; - align-items: center; - padding: 0 4px; - color: ${({ theme }) => theme.colors.v3.text.secondary}; -`; - -export const SpinnerContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - height: 100px; -`; diff --git a/src/components/Highlights/tracking.ts b/src/components/Highlights/tracking.ts index 89a574169..b5e6d1965 100644 --- a/src/components/Highlights/tracking.ts +++ b/src/components/Highlights/tracking.ts @@ -7,7 +7,8 @@ export const trackingEvents = addPrefix( { VIEW_ALL_LINK_CLICKED: "view all link clicked", TOP_ISSUES_CARD_ASSET_LINK_CLICKED: "top issues card asset link clicked", - TOP_ISSUES_CARD_TABLE_ROW_CLICKED: "top issues card table row clicked" + TOP_ISSUES_CARD_TABLE_ROW_CLICKED: "top issues card table row clicked", + PERFORMANCE_CARD_TABLE_ROW_CLICKED: "performance card table row clicked" }, " " ); diff --git a/src/components/Insights/InsightsCatalog/InsightsCatalog.stories.tsx b/src/components/Insights/InsightsCatalog/InsightsCatalog.stories.tsx index 86ca4c0c5..9a458e928 100644 --- a/src/components/Insights/InsightsCatalog/InsightsCatalog.stories.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsCatalog.stories.tsx @@ -2,6 +2,7 @@ import { Meta, StoryObj } from "@storybook/react"; import { InsightsCatalog } from "."; import { SORTING_ORDER } from "../../common/SortingSelector/types"; import { mockedEndpointBottleneckInsight } from "./InsightsPage/insightCards/EndpointBottleneckInsightCard/mockData"; +import { mockedSpanDurationsInsight } from "./InsightsPage/insightCards/SpanDurationsInsightCard/mockData"; import { SORTING_CRITERION } from "./types"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction @@ -20,7 +21,22 @@ type Story = StoryObj; export const Default: Story = { args: { - insights: [{ ...mockedEndpointBottleneckInsight, isRead: false }], + insights: [ + { ...mockedEndpointBottleneckInsight, isRead: false }, + { + ...mockedSpanDurationsInsight, + average: { + value: 110.74, + unit: "ms", + raw: 110735000 + }, + standardDeviation: { + value: 12.55, + unit: "ms", + raw: 12548500 + } + } + ], totalCount: 1, dismissedCount: 1, defaultQuery: { diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx index 3dd1039b4..66e372943 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx @@ -17,7 +17,6 @@ import { CardsIcon } from "../../../common/icons/CardsIcon"; import { actions } from "../../actions"; import { trackingEvents } from "../../tracking"; import { - isChattyApiEndpointInsight, isEndpointBottleneckInsight, isEndpointBreakdownInsight, isEndpointChattyApiV2Insight, @@ -25,7 +24,6 @@ import { isEndpointHighUsageInsight, isEndpointLowUsageInsight, isEndpointNormalUsageInsight, - isEndpointQueryOptimizationInsight, isEndpointQueryOptimizationV2Insight, isEndpointSlowdownSourceInsight, isEndpointSpanNPlusOneInsight, @@ -48,10 +46,8 @@ import { import { ViewMode } from "../types"; import { EndpointBottleneckInsightCard } from "./insightCards/EndpointBottleneckInsightCard"; import { EndpointBreakdownInsightCard } from "./insightCards/EndpointBreakdownInsightCard"; -import { EndpointChattyApiInsightCard } from "./insightCards/EndpointChattyApiInsightCard"; import { EndpointChattyApiV2InsightCard } from "./insightCards/EndpointChattyApiV2InsightCard"; import { EndpointHighNumberOfQueriesInsightCard } from "./insightCards/EndpointHighNumberOfQueriesInsightCard"; -import { EndpointQueryOptimizationInsightCard } from "./insightCards/EndpointQueryOptimizationInsightCard"; import { EndpointQueryOptimizationV2InsightCard } from "./insightCards/EndpointQueryOptimizationV2InsightCard"; import { EndpointSessionInViewInsightCard } from "./insightCards/EndpointSessionInViewInsightCard"; import { EndpointSlowdownSourceInsightCard } from "./insightCards/EndpointSlowdownSourceInsightCard"; @@ -70,6 +66,8 @@ import * as s from "./styles"; import { InsightsPageProps, MarkInsightTypesAsViewedPayload, + OpenHistogramPayload, + OpenLiveViewPayload, RecalculatePayload, isInsightJiraTicketHintShownPayload } from "./types"; @@ -119,27 +117,25 @@ const renderInsightCard = ( // }; const handleHistogramButtonClick = ( - instrumentationLibrary: string, - name: string, + spanCodeObjectId: string, insightType: InsightType, displayName: string ) => { - window.sendMessageToDigma({ + window.sendMessageToDigma({ action: actions.OPEN_HISTOGRAM, payload: { - instrumentationLibrary, - name, + spanCodeObjectId, insightType, displayName } }); }; - const handleLiveButtonClick = (prefixedCodeObjectId: string) => { - window.sendMessageToDigma({ + const handleLiveButtonClick = (codeObjectId: string) => { + window.sendMessageToDigma({ action: actions.OPEN_LIVE_VIEW, payload: { - prefixedCodeObjectId + codeObjectId } }); }; @@ -414,22 +410,6 @@ const renderInsightCard = ( ); } - // deprecated - if (isChattyApiEndpointInsight(insight)) { - return ( - - ); - } - if (isEndpointChattyApiV2Insight(insight)) { return ( - ); - } - if (isEndpointQueryOptimizationV2Insight(insight)) { return ( { (isNumber(previousPage) && previousPage !== props.page) || (previousConfig && (previousConfig?.scope?.span !== config?.scope?.span || - previousConfig?.environment?.originalName !== - config.environment?.originalName)) + previousConfig?.environment?.id !== config.environment?.id)) ) { listRef.current?.scrollTo(0, 0); } diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/index.tsx index 75d494b6c..6244ee0ec 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/index.tsx @@ -1,5 +1,4 @@ import { getDurationString } from "../../../../../../utils/getDurationString"; -import { Info } from "../common/Info"; import { InsightCard } from "../common/InsightCard"; import { ColumnsContainer } from "../common/InsightCard/ColumnsContainer"; import { KeyValue } from "../common/InsightCard/KeyValue"; @@ -62,25 +61,17 @@ export const EndpointBottleneckInsightCard = ({ + label={"% of Duration"} + info={ + "The percentage of the overall request time taken up by this bottleneck asset" } > {span.avgFractionWhenBeingBottleneck}% + label={"% of Requests"} + info={ + "The percentage of requests for the selected endpoint experiencing this bottleneck" } > {span.requestPercentage}% diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/mockData.ts b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/mockData.ts index b1a89393b..5586f9d5c 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/mockData.ts +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBottleneckInsightCard/mockData.ts @@ -32,8 +32,7 @@ export const mockedEndpointBottleneckInsight: EndpointBottleneckInsight = { instrumentationLibrary: "SampleInsightsController", spanCodeObjectId: "span:SampleInsightsController$_$DelayAsync", methodCodeObjectId: null, - kind: "Internal", - codeObjectId: null + kind: "Internal" }, probabilityOfBeingBottleneck: 0.6923076923076923, avgFractionWhenBeingBottleneck: 50, @@ -44,36 +43,9 @@ export const mockedEndpointBottleneckInsight: EndpointBottleneckInsight = { }, criticality: 0, ticketLink: "https://digma.ai/1", - requestPercentage: 90, - p50: { - fraction: 0, - maxDuration: { - value: 0, - unit: "ns", - raw: 0 - } - }, - p95: { - fraction: 0, - maxDuration: { - value: 0, - unit: "ns", - raw: 0 - } - }, - p99: { - fraction: 0, - maxDuration: { - value: 0, - unit: "ns", - raw: 0 - } - } + requestPercentage: 90 }, 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: { @@ -84,9 +56,7 @@ export const mockedEndpointBottleneckInsight: EndpointBottleneckInsight = { "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)" + kind: "Server" }, shortDisplayInfo: { title: "", @@ -100,8 +70,6 @@ export const mockedEndpointBottleneckInsight: EndpointBottleneckInsight = { environment: "BOB-LAPTOP[LOCAL]", severity: 0, isRecalculateEnabled: true, - prefixedCodeObjectId: - "method:Sample.MoneyTransfer.API.Controllers.SampleInsightsController$_$Lock(Double)", customStartTime: null, actualStartTime: "2023-06-16T11:10:30.349Z" }; diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/EndpointBreakdownInsightCard.stories.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/EndpointBreakdownInsightCard.stories.tsx index 6b1416a6f..509b34fa2 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/EndpointBreakdownInsightCard.stories.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/EndpointBreakdownInsightCard.stories.tsx @@ -28,26 +28,6 @@ export const Async: Story = { args: { insight: { ...mockedEndpointBreakdownInsight, - components: [ - { - type: ComponentType.Internal, - fraction: 0.996539483729232, - duration: { - value: 2.06, - unit: "ms", - raw: 2063332.9999999993 - } - }, - { - type: ComponentType.Rendering, - fraction: 0.0034605162707679665, - duration: { - value: 1.03, - unit: "ms", - raw: 1031666.4999999995 - } - } - ], p50Components: [ { type: ComponentType.Internal, diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/index.tsx index ebc97afac..6de16a2ad 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/index.tsx @@ -11,7 +11,6 @@ import { DefaultTheme } from "styled-components/dist/types"; import { getDurationString } from "../../../../../../utils/getDurationString"; import { roundTo } from "../../../../../../utils/roundTo"; import { Tag } from "../../../../../common/v3/Tag"; -import { Tooltip } from "../../../../../common/v3/Tooltip"; import { Component, ComponentType, @@ -49,14 +48,14 @@ const DEFAULT_PERCENTILE = 0.5; const getComponents = ( insight: EndpointBreakdownInsight, percentile: number -): Component[] | undefined => { +): Component[] => { switch (percentile) { case 0.5: - return insight.p50Components || undefined; + return insight.p50Components; case 0.95: - return insight.p95Components || undefined; + return insight.p95Components; default: - return undefined; + return []; } }; @@ -75,9 +74,7 @@ export const EndpointBreakdownInsightCard = ( useState(DEFAULT_PERCENTILE); const data = useMemo(() => { - const components = - getComponents(props.insight, percentileViewMode) || - props.insight.components; + const components = getComponents(props.insight, percentileViewMode); const sortedComponents = props.insight.hasAsyncSpans ? [...components].sort((a, b) => @@ -170,9 +167,11 @@ export const EndpointBreakdownInsightCard = ( {duration && ( - - - + )} ); @@ -223,12 +222,10 @@ export const EndpointBreakdownInsightCard = ( insight={props.insight} content={ - {props.insight.p50Components && props.insight.p95Components && ( - - )} + {props.insight.hasAsyncSpans ? renderTable() : renderPieChart()} } diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/mockData.ts b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/mockData.ts index a1082cabc..5bfac8554 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/mockData.ts +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointBreakdownInsightCard/mockData.ts @@ -27,28 +27,6 @@ export const mockedEndpointBreakdownInsight: EndpointBreakdownInsight = { hasAsyncSpans: false, isDismissed: false, isDismissible: true, - components: [ - { - type: ComponentType.Internal, - fraction: 0.396539483729232, - duration: null - }, - { - type: ComponentType.Rendering, - fraction: 0.396539483729232, - duration: null - }, - { - type: ComponentType.HttpClients, - fraction: 0.103460516270768, - duration: null - }, - { - type: ComponentType.DbQueries, - fraction: 0.103460516270768, - duration: null - } - ], p50Components: [ { type: ComponentType.Internal, @@ -94,8 +72,6 @@ export const mockedEndpointBreakdownInsight: EndpointBreakdownInsight = { } ], scope: InsightScope.EntrySpan, - endpointSpan: "HTTP GET /owners/new", - spanCodeObjectId: "span:io.opentelemetry.tomcat-10.0$_$HTTP GET /owners/new", route: "epHTTP:HTTP GET /owners/new", serviceName: "PetClinic", spanInfo: { @@ -106,9 +82,7 @@ export const mockedEndpointBreakdownInsight: EndpointBreakdownInsight = { "span:io.opentelemetry.tomcat-10.0$_$HTTP GET /owners/new", methodCodeObjectId: "method:org.springframework.samples.petclinic.owner.OwnerController$_$initCreationForm", - kind: "Server", - codeObjectId: - "org.springframework.samples.petclinic.owner.OwnerController$_$initCreationForm" + kind: "Server" }, shortDisplayInfo: { title: "Request Breakdown", @@ -121,8 +95,6 @@ export const mockedEndpointBreakdownInsight: EndpointBreakdownInsight = { decorators: null, environment: "SAMPLE_ENV", severity: 0, - prefixedCodeObjectId: - "method:org.springframework.samples.petclinic.owner.OwnerController$_$initCreationForm", customStartTime: null, actualStartTime: "2023-06-30T00:00:00.000Z" }; diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard/EndpointChattyApiInsightCard.stories.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard/EndpointChattyApiInsightCard.stories.tsx deleted file mode 100644 index 3fab49008..000000000 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard/EndpointChattyApiInsightCard.stories.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Meta, StoryObj } from "@storybook/react"; -import { EndpointChattyApiInsightCard } from "."; -import { mockedEndpointChattyApiInsight } from "./mockData"; - -// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction -const meta: Meta = { - title: - "Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard", - component: EndpointChattyApiInsightCard, - 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: mockedEndpointChattyApiInsight - } -}; - -export const WithMultipleSpans: Story = { - args: { - insight: { - ...mockedEndpointChattyApiInsight, - spans: new Array(4).fill(undefined).map((x, i) => ({ - ...mockedEndpointChattyApiInsight.spans[0], - clientSpan: { - ...mockedEndpointChattyApiInsight.spans[0].clientSpan, - spanCodeObjectId: `${mockedEndpointChattyApiInsight.spans[0].clientSpan.spanCodeObjectId} ${i}` - } - })) - } - } -}; diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard/index.tsx deleted file mode 100644 index ee6bd9aa0..000000000 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointChattyApiInsightCard/index.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { useContext } from "react"; -import { usePagination } from "../../../../../../hooks/usePagination"; -import { ConfigContext } from "../../../../../common/App/ConfigContext"; -import { TargetIcon } from "../../../../../common/icons/12px/TargetIcon"; -import { Button } from "../../../../../common/v3/Button"; -import { Pagination } from "../../../../../common/v3/Pagination"; -import { Tooltip } from "../../../../../common/v3/Tooltip"; -import { InsightType, Trace } from "../../../../types"; -import { InsightCard } from "../common/InsightCard"; -import { ContentContainer, Description, ListContainer } from "../styles"; -import * as s from "./styles"; -import { EndpointChattyApiInsightCardProps } from "./types"; - -const PAGE_SIZE = 3; - -/** - * @deprecated - */ -export const EndpointChattyApiInsightCard = ({ - insight, - onAssetLinkClick, - onTraceButtonClick, - onRecalculate, - onRefresh, - onGoToSpan, - isMarkAsReadButtonEnabled -}: EndpointChattyApiInsightCardProps) => { - const config = useContext(ConfigContext); - - const [pageItems, page, setPage] = usePagination( - insight.spans, - PAGE_SIZE, - insight.id - ); - - const handleLinkClick = (spanCodeObjectId: string) => { - onAssetLinkClick(spanCodeObjectId, insight.type); - }; - - const handleTraceButtonClick = ( - trace: Trace, - insightType: InsightType, - spanCodeObjectId: string - ) => { - onTraceButtonClick(trace, insightType, spanCodeObjectId); - }; - - return ( - - - Excessive API calls to specific endpoint found - - - {pageItems.map((span) => { - const spanName = span.clientSpan.displayName; - const traceId = span.traceId; - const spanCodeObjectId = span.clientSpan.spanCodeObjectId; - - return ( - handleLinkClick(spanCodeObjectId)} - buttons={[ - config.isJaegerEnabled && traceId && ( - -