diff --git a/ui/package.json b/ui/package.json index 199e72347d..15a41717ea 100644 --- a/ui/package.json +++ b/ui/package.json @@ -33,7 +33,7 @@ "eslint --fix", "prettier --write" ], - "*.+(json|css|md)": "prettier --write" + "*.+(json|css|md|html)": "prettier --write" }, "husky": { "hooks": { diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html b/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html index 03fd64bba1..321e73b55b 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html @@ -189,8 +189,17 @@ customAbsoluteRangePicker: true }, autoRefresh: false + }, + conProf: { + checkNgm: false, + showSetting: false, + enableDownloadGroup: false, + enableDotGraph: false, + enablePreviewGoroutine: false, + listDuration: 1 } - } + }, + appsEnabled: ['topsql', 'slow_query', 'conprof', 'sql_advisor'] }) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/context.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/context.ts index 849c3738bd..c5ddac5905 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/context.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/context.ts @@ -1,7 +1,8 @@ import { IConProfilingDataSource, IConProfilingContext, - ReqConfig + ReqConfig, + IConProfilingConfig } from '@pingcap/tidb-dashboard-lib' import client, { ConprofNgMonitoringConfig } from '~/client' @@ -84,7 +85,13 @@ class DataSource implements IConProfilingDataSource { const ds = new DataSource() -export const ctx: IConProfilingContext = { +export const ctx: ( + cfg: Partial +) => IConProfilingContext = (cfg) => ({ ds, - cfg: { apiPathBase: client.getBasePath(), publicPathBase } -} + cfg: { + apiPathBase: client.getBasePath(), + publicPathBase, + ...cfg + } +}) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/index.tsx b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/index.tsx index 90a036f304..15240cf990 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/index.tsx +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/ContinuousProfiling/index.tsx @@ -4,10 +4,13 @@ import { ConProfilingProvider } from '@pingcap/tidb-dashboard-lib' import { ctx } from './context' +import { getGlobalConfig } from '~/utils/globalConfig' export default function () { return ( - + ) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/utils/globalConfig.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/utils/globalConfig.ts index c7fafbf8c4..bd74acc2fb 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/utils/globalConfig.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/utils/globalConfig.ts @@ -1,4 +1,5 @@ import { + IConProfilingConfig, IOverviewConfig, ISlowQueryConfig, IStatementConfig, @@ -45,6 +46,7 @@ export type AppsConfig = { slowQuery?: Partial statement?: Partial topSQL?: Partial + conProf?: Partial } export type GlobalConfig = { diff --git a/ui/packages/tidb-dashboard-for-op/src/apps/ContinuousProfiling/context.ts b/ui/packages/tidb-dashboard-for-op/src/apps/ContinuousProfiling/context.ts index 849c3738bd..a8eacaee64 100644 --- a/ui/packages/tidb-dashboard-for-op/src/apps/ContinuousProfiling/context.ts +++ b/ui/packages/tidb-dashboard-for-op/src/apps/ContinuousProfiling/context.ts @@ -86,5 +86,8 @@ const ds = new DataSource() export const ctx: IConProfilingContext = { ds, - cfg: { apiPathBase: client.getBasePath(), publicPathBase } + cfg: { + apiPathBase: client.getBasePath(), + publicPathBase + } } diff --git a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/context/index.ts b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/context/index.ts index 95e678c1ea..f116dec0eb 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/context/index.ts +++ b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/context/index.ts @@ -58,9 +58,20 @@ export interface IConProfilingDataSource { getPDTopology(options?: ReqConfig): AxiosPromise> } +export interface IConProfilingConfig extends IContextConfig { + publicPathBase: string + + checkNgm?: boolean // default value is true + showSetting?: boolean // default value is true + enableDownloadGroup?: boolean // default value is true + enableDotGraph?: boolean // default value is true + enablePreviewGoroutine?: boolean // default value is true + listDuration?: number // unit hour, 1 means 1 hour, 2 means 2 hours, default value is 2 hours +} + export interface IConProfilingContext { ds: IConProfilingDataSource - cfg: IContextConfig & { publicPathBase: string } + cfg: IConProfilingConfig } export const ConProfilingContext = createContext( diff --git a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/index.tsx b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/index.tsx index 90998d4093..05b8204520 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/index.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/index.tsx @@ -13,25 +13,37 @@ addTranslations(translations) function AppRoutes() { useLocationChange() + const ctx = useContext(ConProfilingContext) + const checkNgm = ctx?.cfg.checkNgm ?? true return ( + checkNgm ? ( + + + + ) : ( - + ) } /> + checkNgm ? ( + + + + + + ) : ( - + ) } /> diff --git a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/Detail.tsx b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/Detail.tsx index 91e73678c6..20a70800f6 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/Detail.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/Detail.tsx @@ -16,8 +16,12 @@ import { telemetry } from '../utils/telemetry' import { ScrollablePane } from 'office-ui-fabric-react/lib/ScrollablePane' import { ConProfilingContext } from '../context' -const COMMON_ACTIONS: string[] = ['view_flamegraph', 'view_graph', 'download'] -const TEXT_ACTIONS: string[] = ['view_text'] +enum Action { + VIEW_FLAMEGRAPH = 'view_flamegraph', + VIEW_GRAPH = 'view_graph', + VIEW_TEXT = 'view_text', + DOWNLOAD = 'download' +} const profileTypeSortOrder: { [key: string]: number } = { profile: 1, @@ -29,6 +33,10 @@ const profileTypeSortOrder: { [key: string]: number } = { export default function Page() { const ctx = useContext(ConProfilingContext) + const enableDownloadGroup = ctx?.cfg.enableDownloadGroup ?? true + const enableDotGraph = ctx?.cfg.enableDotGraph ?? true + const enablePreviewGoroutine = ctx?.cfg.enablePreviewGoroutine ?? true + const { t } = useTranslation() const { ts } = useQueryParams() @@ -86,28 +94,28 @@ export default function Page() { let dataFormat = '' if (component === 'tikv' && profile_type === 'heap') { switch (action) { - case 'view_flamegraph': + case Action.VIEW_FLAMEGRAPH: // tikv heap flamegraph uses Brendan Gregg's collapsed stack format which is text based dataFormat = 'text' break - case 'view_graph': + case Action.VIEW_GRAPH: dataFormat = 'svg' break - case 'download': + case Action.DOWNLOAD: dataFormat = 'jeprof' break default: } } else { switch (action) { - case 'view_graph': + case Action.VIEW_GRAPH: dataFormat = 'svg' break - case 'view_text': + case Action.VIEW_TEXT: dataFormat = 'text' break - case 'view_flamegraph': - case 'download': + case Action.VIEW_FLAMEGRAPH: + case Action.DOWNLOAD: dataFormat = 'protobuf' break default: @@ -127,7 +135,7 @@ export default function Page() { component: component! }) - if (action === 'view_graph' || action === 'view_text') { + if (action === Action.VIEW_GRAPH || action === Action.VIEW_TEXT) { const profileURL = `${ ctx!.cfg.apiPathBase }/continuous_profiling/single_profile/view?token=${token}` @@ -135,7 +143,7 @@ export default function Page() { return } - if (action === 'view_flamegraph') { + if (action === Action.VIEW_FLAMEGRAPH) { // view flamegraph by speedscope const speedscopeTitle = `${rec.target?.component}_${rec.target?.address}_${rec.profile_type}` const profileURL = `${ @@ -150,7 +158,7 @@ export default function Page() { return } - if (action === 'download') { + if (action === Action.DOWNLOAD) { window.location.href = `${ ctx!.cfg.apiPathBase }/continuous_profiling/download?token=${token}` @@ -189,7 +197,8 @@ export default function Page() { maxWidth: 100, onRender: (record) => { const profileType = record.profile_type - if (profileType === 'profile') { + // in the cloud ngm, the `profile` is `cpu` + if (profileType === 'profile' || profileType === 'cpu') { return `CPU - ${profileDuration}s` } return upperFirst(profileType) @@ -246,9 +255,23 @@ export default function Page() { } const rec = record as ConprofProfileDetail - let actionsKey = TEXT_ACTIONS - if (rec.profile_type !== 'goroutine') { - actionsKey = COMMON_ACTIONS + let actionsKey: string[] = [] + if (rec.profile_type === 'goroutine') { + if (enablePreviewGoroutine) { + actionsKey = [Action.VIEW_TEXT] + } else { + actionsKey = [Action.DOWNLOAD] + } + } else { + if (enableDotGraph) { + actionsKey = [ + Action.VIEW_FLAMEGRAPH, + Action.VIEW_GRAPH, + Action.DOWNLOAD + ] + } else { + actionsKey = [Action.VIEW_FLAMEGRAPH, Action.DOWNLOAD] + } } return ( @@ -278,9 +301,11 @@ export default function Page() { } titleExtra={ - + enableDownloadGroup && ( + + ) } />
diff --git a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/List.tsx b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/List.tsx index fe089b3f8c..f0ea8f554a 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/List.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/ContinuousProfiling/pages/List.tsx @@ -37,17 +37,19 @@ import { useURLTimeRange } from '@lib/hooks/useURLTimeRange' export default function Page() { const ctx = useContext(ConProfilingContext) + const showSetting = ctx?.cfg.showSetting ?? true + const durationHour = ctx?.cfg.listDuration ?? 2 const { timeRange, setTimeRange } = useURLTimeRange() const endTime = timeRange.type === 'recent' ? '' : `${timeRange.value[1]}` const setEndTime = (v) => { if (!v) { - setTimeRange({ type: 'recent', value: 2 * 60 * 60 }) + setTimeRange({ type: 'recent', value: durationHour * 60 * 60 }) } else { const endUnix = v.unix() setTimeRange({ type: 'absolute', - value: [endUnix - 2 * 60 * 60, endUnix] + value: [endUnix - durationHour * 60 * 60, endUnix] }) } } @@ -78,7 +80,7 @@ export default function Page() { } else { _rangeEndTime = rangeEndTime } - const _rangeStartTime = _rangeEndTime.subtract(2, 'h') + const _rangeStartTime = _rangeEndTime.subtract(durationHour, 'h') return ctx!.ds.continuousProfilingGroupProfilesGet( _rangeStartTime.unix(), @@ -234,7 +236,7 @@ export default function Page() { /> - -2h + -{durationHour}h