Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const ctx: (cfg: Partial<ISlowQueryConfig>) => ISlowQueryContext = (
showResourceGroupFilter: true,
showDownloadSlowQueryDBFile: true,
showInternalFilter: true,
showRuV2: true,
...cfg
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export const ctx: (cfg: Partial<IStatementConfig>) => IStatementContext = (
ds: new DataSource(),
cfg: {
apiPathBase: client.getBasePath(),
showRuV2: true,
...cfg
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export interface ISlowQueryConfig extends IContextConfig {

// show internal slow queries
showInternalFilter?: boolean

// show RU V2 fields (clinic-only: ru_v2, ru_v2_detail columns,
// Basic-tab rows, and the dedicated RU V2 Metrics tab)
showRuV2?: boolean
}

export interface ISlowQueryContext {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { SlowqueryModel } from '@lib/client'
import { DateTime } from '@lib/components'
import { getValueFormat } from '@baurine/grafana-value-formats'

export const tabBasicItems = (data: SlowqueryModel) => [
export const tabBasicItems = (
data: SlowqueryModel,
options?: { showRuV2?: boolean }
) => [
{
key: 'timestamp',
value: <DateTime.Calendar unixTimestampMs={(data.timestamp ?? 0) * 1000} />
Expand Down Expand Up @@ -35,5 +38,6 @@ export const tabBasicItems = (data: SlowqueryModel) => [
{ key: 'user', value: data.user },
{ key: 'host', value: data.host },
{ key: 'ru', value: data.ru },
...(options?.showRuV2 ? [{ key: 'ru_v2', value: data.ru_v2 }] : []),
{ key: 'resource_group', value: data.resource_group }
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import React, { ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
import { getValueFormat } from '@baurine/grafana-value-formats'

import { RequestUnitV2Metrics, SlowqueryModel } from '@lib/client'
import { CardTable, Pre } from '@lib/components'
import { valueColumns } from '@lib/utils/tableColumns'

const num = (v: number | undefined, unit: 'short' | 'bytes' = 'short') =>
v == null ? '' : getValueFormat(unit)(v, 2)

const mapToCompactJson = (map: Record<string, number> | undefined): string => {
if (!map || Object.keys(map).length === 0) return ''
return JSON.stringify(map)
}

/**
* Metrics struct rows for the metrics table inside the RU V2 tab.
*/
function buildMetricsItems(data: SlowqueryModel) {
const m: RequestUnitV2Metrics = data.ru_v2_metrics ?? {}
return [
{ key: 'ru_v2_metrics.total_ru', value: num(m.total_ru) },
{ key: 'ru_v2_metrics.tidb_ru', value: num(m.tidb_ru) },
{ key: 'ru_v2_metrics.tikv_ru', value: num(m.tikv_ru) },
{ key: 'ru_v2_metrics.tiflash_ru', value: num(m.tiflash_ru) },
{ key: 'ru_v2_metrics.txn_cnt', value: num(m.txn_cnt) },
{ key: 'ru_v2_metrics.plan_cnt', value: num(m.plan_cnt) },
{
key: 'ru_v2_metrics.plan_derive_stats_paths',
value: num(m.plan_derive_stats_paths)
},
{
key: 'ru_v2_metrics.session_parser_total',
value: num(m.session_parser_total)
},
{ key: 'ru_v2_metrics.executor_l1', value: num(m.executor_l1) },
{ key: 'ru_v2_metrics.executor_l2', value: num(m.executor_l2) },
{ key: 'ru_v2_metrics.executor_l3', value: num(m.executor_l3) },
{
key: 'ru_v2_metrics.executor_l5_insert_rows',
value: num(m.executor_l5_insert_rows)
},
{
key: 'ru_v2_metrics.result_chunk_cells',
value: num(m.result_chunk_cells)
},
{
key: 'ru_v2_metrics.resource_manager_read_cnt',
value: num(m.resource_manager_read_cnt)
},
{
key: 'ru_v2_metrics.resource_manager_write_cnt',
value: num(m.resource_manager_write_cnt)
},
{
key: 'ru_v2_metrics.tikv_coprocessor_executor_iterations',
value: num(m.tikv_coprocessor_executor_iterations)
},
{
key: 'ru_v2_metrics.tikv_coprocessor_response_bytes',
value: num(m.tikv_coprocessor_response_bytes, 'bytes')
},
{
key: 'ru_v2_metrics.tikv_coprocessor_executor_work_total',
value: mapToCompactJson(m.tikv_coprocessor_executor_work_total)
},
{
key: 'ru_v2_metrics.tikv_storage_processed_keys_get',
value: num(m.tikv_storage_processed_keys_get)
},
{
key: 'ru_v2_metrics.tikv_storage_processed_keys_batch_get',
value: num(m.tikv_storage_processed_keys_batch_get)
},
{
key: 'ru_v2_metrics.tikv_kv_engine_cache_miss',
value: num(m.tikv_kv_engine_cache_miss)
},
{
key: 'ru_v2_metrics.tikv_raftstore_store_write_trigger_wb_bytes',
value: num(m.tikv_raftstore_store_write_trigger_wb_bytes, 'bytes')
}
]
}

function Section({ title, children }: { title: string; children: ReactNode }) {
return (
<div style={{ marginBottom: 20 }}>
<div
style={{
fontSize: 14,
fontWeight: 600,
color: '#262626',
marginBottom: 8
}}
>
{title}
</div>
{children}
</div>
)
}

export function RuV2TabContent({
data,
schemaColumns
}: {
data: SlowqueryModel
schemaColumns: string[]
}) {
const { t } = useTranslation()
const schemaSet = new Set(schemaColumns)
const v2 = data.ru_v2
const v2Detail = data.ru_v2_detail

// Schema (available_fields) tells us which RU V2 fields the backend can
// populate for this cluster tier. Premium only declares `ru_v2`; Starter /
// Essential declare `ru_v2`, `ru_v2_detail`, `ru_v2_metrics`. Hide each
// section if its field is not in the schema, regardless of the data value.
const showV2 = schemaSet.has('ru_v2')
const showDetail = schemaSet.has('ru_v2_detail')
const showMetrics = schemaSet.has('ru_v2_metrics')
const metricsItems = showMetrics ? buildMetricsItems(data) : []

// Columns: Name + Value only (drop the Description column).
const nameValueColumns = valueColumns('slow_query.fields.').slice(0, 2)

return (
<div style={{ padding: '8px 16px' }}>
{showV2 && (
<Section title={t('slow_query.fields.ru_v2')}>
<span style={{ fontSize: 13 }}>{num(v2)}</span>
</Section>
)}

{showDetail && (
<Section title={t('slow_query.fields.ru_v2_detail')}>
<Pre style={{ margin: 0, fontSize: 12, lineHeight: 1.5 }}>
{v2Detail ?? ''}
</Pre>
</Section>
)}

{showMetrics && (
<Section title={t('slow_query.fields.ru_v2_metrics_label')}>
<CardTable
cardNoMargin
columns={nameValueColumns}
items={metricsItems}
extendLastColumn
/>
</Section>
)}
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,36 @@ import { tabBasicItems } from './DetailTabBasic'
import { tabTimeItems } from './DetailTabTime'
import { tabCoprItems } from './DetailTabCopr'
import { tabTxnItems } from './DetailTabTxn'
import { RuV2TabContent } from './DetailTabRuV2'
import { useSchemaColumns } from '../../utils/useSchemaColumns'
import { SlowQueryContext } from '../../context'

export default function DetailTabs({ data }: { data: SlowqueryModel }) {
const ctx = useContext(SlowQueryContext)
const showRuV2 = !!ctx?.cfg.showRuV2

const { t } = useTranslation()
const { schemaColumns } = useSchemaColumns(
ctx!.ds.slowQueryAvailableFieldsGet
)

const tabs = useMemo(() => {
const schemaSet = new Set(schemaColumns)
// Premium tier only declares `ru_v2` in the schema; Starter / Essential
// also declare `ru_v2_detail` and `ru_v2_metrics`. Use the presence of the
// metrics struct as the tier signal: when absent it's Premium, so the
// ru_v2 row stays inside the Basic tab; when present, RU V2 / Detail /
// Metrics get their own dedicated tab.
const isEssentialLike = schemaSet.has('ru_v2_metrics')
const showRuV2InBasic =
showRuV2 && schemaSet.has('ru_v2') && !isEssentialLike
const showRuV2Tab = showRuV2 && isEssentialLike
const tbs = [
{
key: 'basic',
title: t('slow_query.detail.tabs.basic'),
content: () => {
const items = tabBasicItems(data)
const items = tabBasicItems(data, { showRuV2: showRuV2InBasic })
const columns = valueColumns('slow_query.fields.')
return (
<CardTable
Expand Down Expand Up @@ -92,6 +104,15 @@ export default function DetailTabs({ data }: { data: SlowqueryModel }) {
}
}
]
if (showRuV2Tab) {
tbs.push({
key: 'ru_v2',
title: t('slow_query.detail.tabs.ru_v2'),
content: () => (
<RuV2TabContent data={data} schemaColumns={schemaColumns} />
)
})
}
if (data.warnings) {
tbs.push({
key: 'warnings',
Expand All @@ -112,6 +133,6 @@ export default function DetailTabs({ data }: { data: SlowqueryModel }) {
})
}
return tbs
}, [schemaColumns, data, t])
}, [schemaColumns, data, t, showRuV2])
return <CardTabs animated={false} tabs={tabs} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,34 @@ slow_query:

ru: RU
ru_tooltip: request units
ru_v2: RU V2
ru_v2_tooltip: Total RU V2 consumed by this query
ru_v2_detail: RU V2 Detail
ru_v2_detail_tooltip: Per-component RU V2 breakdown (raw)
ru_v2_metrics_label: RU V2 Metrics
ru_v2_metrics:
total_ru: Total RU
tidb_ru: TiDB RU
tikv_ru: TiKV RU
tiflash_ru: TiFlash RU
txn_cnt: Transaction Count
plan_cnt: Plan Count
plan_derive_stats_paths: Plan Derive Stats Paths
session_parser_total: Session Parser Total
executor_l1: Executor L1
executor_l2: Executor L2
executor_l3: Executor L3
executor_l5_insert_rows: Executor L5 Insert Rows
result_chunk_cells: Result Chunk Cells
resource_manager_read_cnt: Resource Manager Read Count
resource_manager_write_cnt: Resource Manager Write Count
tikv_coprocessor_executor_iterations: TiKV Coprocessor Executor Iterations
tikv_coprocessor_response_bytes: TiKV Coprocessor Response Bytes
tikv_coprocessor_executor_work_total: TiKV Coprocessor Executor Work Total
tikv_storage_processed_keys_get: TiKV Storage Processed Keys (Get)
tikv_storage_processed_keys_batch_get: TiKV Storage Processed Keys (Batch Get)
tikv_kv_engine_cache_miss: TiKV KV Engine Cache Miss
tikv_raftstore_store_write_trigger_wb_bytes: TiKV Raftstore Write Trigger WB Bytes
resource_group: Resource Group
resource_group_tooltip: The resource group that the query belongs to
time_queued_by_rc: The total time queued by RC
Expand Down Expand Up @@ -174,6 +202,7 @@ slow_query:
time: Time
copr: Coprocessor
txn: Transaction
ru_v2: RU V2
warnings: Warnings
toolbar:
schemas:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,34 @@ slow_query:

ru: RU
ru_tooltip: 资源单位(RU)
ru_v2: RU V2
ru_v2_tooltip: 本次查询消耗的 RU V2 总量
ru_v2_detail: RU V2 明细
ru_v2_detail_tooltip: 各组件 RU V2 拆分(原始数据)
ru_v2_metrics_label: RU V2 Metrics
ru_v2_metrics:
total_ru: Total RU
tidb_ru: TiDB RU
tikv_ru: TiKV RU
tiflash_ru: TiFlash RU
txn_cnt: 事务数
plan_cnt: Plan 数
plan_derive_stats_paths: Plan Derive Stats Paths
session_parser_total: Session Parser Total
executor_l1: Executor L1
executor_l2: Executor L2
executor_l3: Executor L3
executor_l5_insert_rows: Executor L5 插入行数
result_chunk_cells: Result Chunk Cells
resource_manager_read_cnt: Resource Manager 读次数
resource_manager_write_cnt: Resource Manager 写次数
tikv_coprocessor_executor_iterations: TiKV Coprocessor Executor 迭代数
tikv_coprocessor_response_bytes: TiKV Coprocessor 响应字节
tikv_coprocessor_executor_work_total: TiKV Coprocessor Executor 工作总量
tikv_storage_processed_keys_get: TiKV Storage Processed Keys (Get)
tikv_storage_processed_keys_batch_get: TiKV Storage Processed Keys (Batch Get)
tikv_kv_engine_cache_miss: TiKV KV Engine Cache Miss
tikv_raftstore_store_write_trigger_wb_bytes: TiKV Raftstore Write Trigger WB Bytes
resource_group: 资源组
resource_group_tooltip: SQL 语句所属的资源组
time_queued_by_rc: RC 等待累积耗时
Expand Down Expand Up @@ -178,6 +206,7 @@ slow_query:
time: 执行时间
copr: Coprocessor 读取
txn: 事务
ru_v2: RU V2
warnings: 警告
toolbar:
schemas:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ export function slowQueryColumns(
}),
// resource control
tcf.bar.single('ru', 'none', rows),
tcf.bar.single('ru_v2', 'none', rows),
tcf.textWithTooltip('ru_v2_detail', rows),
tcf.textWithTooltip('resource_group', rows),
tcf.bar.single('time_queued_by_rc', 's', rows),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ export interface IStatementConfig extends IContextConfig {
customAbsoluteRangePicker: boolean
timeRangeLimit?: number
}

// show RU V2 fields (clinic-only: avg_ru_v2 / sum_ru_v2 columns and the
// matching Basic-tab rows)
showRuV2?: boolean
}

export interface IStatementContext {
Expand Down
Loading
Loading