You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Azure Kusto查询对比两组JMeter测试结果?

对比两组JMeter测试结果的Azure Kusto查询优化方案

需求说明

已有单组JMeter测试结果的Kusto查询,需修改为支持两组测试数据的对比展示。

方案一:纵向合并对比(每组数据独立行展示)

该方案将两组数据通过union合并,新增TestGroup字段区分组别,适合查看每组的完整指标:

let testName = "jmeter";
// 定义两组测试的起始时间
let TestStartTime1 = "{StartTime_Group1}";
let TestStartTime2 = "{StartTime_Group2}";

// 处理第一组测试数据
let Group1Data = requests
| where name == testName
    and customDimensions.TestStartTime == TestStartTime1
| summarize
    Samples = count(),
    Average = tolong(avg(duration)),
    (L50, L90, L95, L99) = percentiles(duration, 50, 90, 95, 99),
    Min = min(duration),
    Maximum = max(duration),
    ErrorCount = countif(success == false),
    StartTime = min(tolong(customDimensions.SampleStartTime)),
    EndTime = max(tolong(customDimensions.SampleEndTime))
by Label = tostring(customDimensions.SampleLabel)
| extend TestGroup = "测试组A", s = 0
| union (
    requests
    | where name == testName
        and customDimensions.TestStartTime == TestStartTime1
    | summarize
        Samples = count(),
        Average = tolong(avg(duration)),
        (L50, L90, L95, L99) = percentiles(duration, 50, 90, 95, 99),
        Min = min(duration),
        Maximum = max(duration),
        ErrorCount = countif(success == false),
        StartTime = min(tolong(customDimensions.SampleStartTime)),
        EndTime = max(tolong(customDimensions.SampleEndTime))
    | extend Label = 'TOTAL', TestGroup = "测试组A", s = 9
)
| extend
    tp = Samples / ((EndTime - StartTime) / 1000.0)
| project
    Label, TestGroup, Samples, Average,
    Median = round(L50),
    ['90% Line'] = round(L90),
    ['95% Line'] = round(L95),
    ['99% Line'] = round(L99),
    Min, Maximum,
    ['Error %'] = strcat(round(ErrorCount * 100.0 / Samples, 2), '%'),
    ['Throughput'] = iif(tp < 1.0,
                        strcat(round(tp * 60, 1), '/min'),
                        strcat(round(tp, 1), '/sec')
                     );

// 处理第二组测试数据
let Group2Data = requests
| where name == testName
    and customDimensions.TestStartTime == TestStartTime2
| summarize
    Samples = count(),
    Average = tolong(avg(duration)),
    (L50, L90, L95, L99) = percentiles(duration, 50, 90, 95, 99),
    Min = min(duration),
    Maximum = max(duration),
    ErrorCount = countif(success == false),
    StartTime = min(tolong(customDimensions.SampleStartTime)),
    EndTime = max(tolong(customDimensions.SampleEndTime))
by Label = tostring(customDimensions.SampleLabel)
| extend TestGroup = "测试组B", s = 0
| union (
    requests
    | where name == testName
        and customDimensions.TestStartTime == TestStartTime2
    | summarize
        Samples = count(),
        Average = tolong(avg(duration)),
        (L50, L90, L95, L99) = percentiles(duration, 50, 90, 95, 99),
        Min = min(duration),
        Maximum = max(duration),
        ErrorCount = countif(success == false),
        StartTime = min(tolong(customDimensions.SampleStartTime)),
        EndTime = max(tolong(customDimensions.SampleEndTime))
    | extend Label = 'TOTAL', TestGroup = "测试组B", s = 9
)
| extend
    tp = Samples / ((EndTime - StartTime) / 1000.0)
| project
    Label, TestGroup, Samples, Average,
    Median = round(L50),
    ['90% Line'] = round(L90),
    ['95% Line'] = round(L95),
    ['99% Line'] = round(L99),
    Min, Maximum,
    ['Error %'] = strcat(round(ErrorCount * 100.0 / Samples, 2), '%'),
    ['Throughput'] = iif(tp < 1.0,
                        strcat(round(tp * 60, 1), '/min'),
                        strcat(round(tp, 1), '/sec')
                     );

// 合并两组数据并排序
Group1Data
| union Group2Data
| sort by Label asc, TestGroup asc
| project-reorder
    Label, TestGroup, Samples, Average,
    ['Median'], ['90% Line'], ['95% Line'], ['99% Line'],
    Min, Maximum, ['Error %'], ['Throughput']

方案二:横向关联对比(同Label数据同行展示)

该方案用自定义函数封装重复统计逻辑,通过join将两组数据按Label关联,同一指标的两组结果在同一行,对比更直观:

let testName = "jmeter";
let TestStartTime1 = "{StartTime_Group1}";
let TestStartTime2 = "{StartTime_Group2}";

// 封装通用统计逻辑,减少代码冗余
let getTestStats = (testStartTime:string) {
    requests
    | where name == testName
        and customDimensions.TestStartTime == testStartTime
    | summarize
        Samples = count(),
        Average = tolong(avg(duration)),
        Median = round(percentile(duration, 50)),
        ['90% Line'] = round(percentile(duration, 90)),
        ['95% Line'] = round(percentile(duration, 95)),
        ['99% Line'] = round(percentile(duration, 99)),
        Min = min(duration),
        Maximum = max(duration),
        ['Error %'] = strcat(round(countif(success == false) * 100.0 / count(), 2), '%'),
        tp = count() / ((max(tolong(customDimensions.SampleEndTime)) - min(tolong(customDimensions.SampleStartTime))) / 1000.0)
    by Label = tostring(customDimensions.SampleLabel)
    | extend
        ['Throughput'] = iif(tp < 1.0, strcat(round(tp * 60, 1), '/min'), strcat(round(tp, 1), '/sec'))
    | union (
        requests
        | where name == testName
            and customDimensions.TestStartTime == testStartTime
        | summarize
            Samples = count(),
            Average = tolong(avg(duration)),
            Median = round(percentile(duration, 50)),
            ['90% Line'] = round(percentile(duration, 90)),
            ['95% Line'] = round(percentile(duration, 95)),
            ['99% Line'] = round(percentile(duration, 99)),
            Min = min(duration),
            Maximum = max(duration),
            ['Error %'] = strcat(round(countif(success == false) * 100.0 / count(), 2), '%'),
            tp = count() / ((max(tolong(customDimensions.SampleEndTime)) - min(tolong(customDimensions.SampleStartTime))) / 1000.0)
        | extend Label = 'TOTAL',
            ['Throughput'] = iif(tp < 1.0, strcat(round(tp * 60, 1), '/min'), strcat(round(tp, 1), '/sec'))
    )
};

// 获取两组数据并横向关联
getTestStats(TestStartTime1)
| join kind=fullouter getTestStats(TestStartTime2) on Label
| project-reorder
    Label,
    // 测试组A指标
    Samples_A = Samples, Average_A = Average, Median_A = Median,
    ['90% Line_A'] = ['90% Line'], ['95% Line_A'] = ['95% Line'], ['99% Line_A'] = ['99% Line'],
    Min_A = Min, Maximum_A = Maximum, ['Error %_A'] = ['Error %'], ['Throughput_A'] = ['Throughput'],
    // 测试组B指标
    Samples_B = Samples1, Average_B = Average1, Median_B = Median1,
    ['90% Line_B'] = ['90% Line1'], ['95% Line_B'] = ['95% Line1'], ['99% Line_B'] = ['99% Line1'],
    Min_B = Min1, Maximum_B = Maximum1, ['Error %_B'] = ['Error %1'], ['Throughput_B'] = ['Throughput1']
| sort by Label asc

使用说明

  • 将{StartTime_Group1}和{StartTime_Group2}替换为对应测试的实际起始时间
  • 方案一适合查看每组的完整数据分布,方案二适合直接对比同一指标的两组差异

内容的提问来源于stack exchange,提问作者Jorge Beltran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 10:15:41