Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(conprof): support conprof on new o11y #1607

Merged
merged 3 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"eslint --fix",
"prettier --write"
],
"*.+(json|css|md)": "prettier --write"
"*.+(json|css|md|html)": "prettier --write"
},
"husky": {
"hooks": {
Expand Down
11 changes: 10 additions & 1 deletion ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html
Original file line number Diff line number Diff line change
Expand Up @@ -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']
})
</script>
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
IConProfilingDataSource,
IConProfilingContext,
ReqConfig
ReqConfig,
IConProfilingConfig
} from '@pingcap/tidb-dashboard-lib'

import client, { ConprofNgMonitoringConfig } from '~/client'
Expand Down Expand Up @@ -84,7 +85,13 @@ class DataSource implements IConProfilingDataSource {

const ds = new DataSource()

export const ctx: IConProfilingContext = {
export const ctx: (
cfg: Partial<IConProfilingConfig>
) => IConProfilingContext = (cfg) => ({
ds,
cfg: { apiPathBase: client.getBasePath(), publicPathBase }
}
cfg: {
apiPathBase: client.getBasePath(),
publicPathBase,
...cfg
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import {
ConProfilingProvider
} from '@pingcap/tidb-dashboard-lib'
import { ctx } from './context'
import { getGlobalConfig } from '~/utils/globalConfig'

export default function () {
return (
<ConProfilingProvider value={ctx}>
<ConProfilingProvider
value={ctx(getGlobalConfig().appsConfig?.conProf || {})}
>
<ConProfilingApp />
</ConProfilingProvider>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
IConProfilingConfig,
IOverviewConfig,
ISlowQueryConfig,
IStatementConfig,
Expand Down Expand Up @@ -45,6 +46,7 @@ export type AppsConfig = {
slowQuery?: Partial<ISlowQueryConfig>
statement?: Partial<IStatementConfig>
topSQL?: Partial<ITopSQLConfig>
conProf?: Partial<IConProfilingConfig>
}

export type GlobalConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,8 @@ const ds = new DataSource()

export const ctx: IConProfilingContext = {
ds,
cfg: { apiPathBase: client.getBasePath(), publicPathBase }
cfg: {
apiPathBase: client.getBasePath(),
publicPathBase
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,20 @@ export interface IConProfilingDataSource {
getPDTopology(options?: ReqConfig): AxiosPromise<Array<TopologyPDInfo>>
}

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<IConProfilingContext | null>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,37 @@ addTranslations(translations)

function AppRoutes() {
useLocationChange()
const ctx = useContext(ConProfilingContext)
const checkNgm = ctx?.cfg.checkNgm ?? true

return (
<Routes>
<Route
path="/continuous_profiling"
element={
<NgmNotStartedGuard>
checkNgm ? (
<NgmNotStartedGuard>
<List />
</NgmNotStartedGuard>
) : (
<List />
</NgmNotStartedGuard>
)
}
/>
<Route
path="/continuous_profiling/detail"
element={
<NgmNotStartedGuard>
checkNgm ? (
<NgmNotStartedGuard>
<ParamsPageWrapper>
<Detail />
</ParamsPageWrapper>
</NgmNotStartedGuard>
) : (
<ParamsPageWrapper>
<Detail />
</ParamsPageWrapper>
</NgmNotStartedGuard>
)
}
/>
</Routes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()

Expand Down Expand Up @@ -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:
Expand All @@ -127,15 +135,15 @@ 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}`
window.open(profileURL, '_blank')
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 = `${
Expand All @@ -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}`
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -278,9 +301,11 @@ export default function Page() {
</Link>
}
titleExtra={
<Button type="primary" onClick={handleDownloadGroup}>
{t('conprof.detail.download')}
</Button>
enableDownloadGroup && (
<Button type="primary" onClick={handleDownloadGroup}>
{t('conprof.detail.download')}
</Button>
)
}
/>
<div style={{ height: '100%', position: 'relative' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
})
}
}
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -234,7 +236,7 @@ export default function Page() {
/>
</Form.Item>
<Form.Item label={t('conprof.list.toolbar.range_duration')}>
<span>-2h</span>
<span>-{durationHour}h</span>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={listLoading}>
Expand All @@ -256,19 +258,21 @@ export default function Page() {
<ReloadOutlined onClick={refresh} />
)}
</Tooltip>
<Tooltip
mouseEnterDelay={0}
mouseLeaveDelay={0}
title={t('conprof.list.toolbar.settings')}
placement="bottom"
>
<SettingOutlined
onClick={() => {
setShowSettings(true)
telemetry.clickSettings('settingIcon')
}}
/>
</Tooltip>
{showSetting && (
<Tooltip
mouseEnterDelay={0}
mouseLeaveDelay={0}
title={t('conprof.list.toolbar.settings')}
placement="bottom"
>
<SettingOutlined
onClick={() => {
setShowSettings(true)
telemetry.clickSettings('settingIcon')
}}
/>
</Tooltip>
)}
{!isDistro() && (
<Tooltip
mouseEnterDelay={0}
Expand Down
6 changes: 4 additions & 2 deletions ui/packages/tidb-dashboard-lib/src/utils/distro.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import i18next from 'i18next'

interface IDistro {
pd: string
tidb: string
tikv: string
tiflash: string
pd: string
ticdc: string
is_distro: boolean
}

const DEF_DISTRO: IDistro = {
pd: 'PD',
tidb: 'TiDB',
tikv: 'TiKV',
pd: 'PD',
tiflash: 'TiFlash',
ticdc: 'TiCDC',
is_distro: false
}

Expand Down