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

如何通过编程方式获取Gatling性能测试指标?

在Gatling Scala代码中直接获取性能指标的方案

你的测试代码

package computerdatabase

import io.gatling.app.Gatling
import io.gatling.commons.shared.unstable.model.stats.GeneralStats
import io.gatling.core.Predef._
import io.gatling.core.config.GatlingPropertiesBuilder
import io.gatling.http.Predef._

import java.util.concurrent.ThreadLocalRandom

/**
 * This sample is based on our official tutorials:
 *
 *   - [[https://gatling.io/docs/gatling/tutorials/quickstart Gatling quickstart tutorial]]
 *   - [[https://gatling.io/docs/gatling/tutorials/advanced Gatling advanced tutorial]]
 */
class ComputerDatabaseSimulation extends Simulation {
  var simulationId: Option[String] = None

  val feeder = csv("search.csv").random

  val search =
    exec(
      http("Home")
        .get("/")
    )
      .pause(1)
      .feed(feeder)
      .exec(
        http("Search")
          .get("/computers?f=#{searchCriterion}")
          .check(
            css("a:contains('#{searchComputerName}')", "href").saveAs("computerUrl")
          )
      )
      .pause(1)
      .exec(
        http("Select")
          .get("#{computerUrl}")
          .check(status.is(200))
      )
      .pause(1)

  // repeat is a loop resolved at RUNTIME
  val browse =
    // Note how we force the counter name, so we can reuse it
    repeat(4, "i") {
      exec(
        http("Page #{i}").get("/computers?p=#{i}")
      ).pause(1)
    }

  // Note we should be using a feeder here
  // let's demonstrate how we can retry: let's make the request fail randomly and retry a given
  // number of times

  val edit =
    // let's try at max 2 times
    tryMax(2) {
      exec(
        http("Form")
          .get("/computers/new")
      )
        .pause(1)
        .exec(
          http("Post")
            .post("/computers")
            .formParam("name", "Beautiful Computer")
            .formParam("introduced", "2012-05-30")
            .formParam("discontinued", "")
            .formParam("company", "37")
            .check(
              status.is { session =>
                  // we do a check on a condition that's been customized with
                  // a lambda. It will be evaluated every time a user executes
                  // the request
                  200 + ThreadLocalRandom.current().nextInt(2)
              }
            )
        )
    }
    // if the chain didn't finally succeed, have the user exit the whole scenario
    .exitHereIfFailed

  val httpProtocol =
    http.baseUrl("https://computer-database.gatling.io")
      .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
      .acceptLanguageHeader("en-US,en;q=0.5")
      .acceptEncodingHeader("gzip, deflate")
      .userAgentHeader(
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/119.0"
      )

  val users = scenario("Users").exec(search, browse)
  val admins = scenario("Admins").exec(search, browse, edit)

  setUp(
    users.inject(rampUsers(10).during(10)),
    admins.inject(rampUsers(2).during(10))
  ).protocols(httpProtocol)
}

你的问题

各位技术同仁:我正在使用Gatling的Scala实现开展应用程序性能测试工作。查阅Gatling官方文档后,未找到可通过编程方式获取性能指标的相关方案。我曾尝试读取Gatling生成的性能报告作为替代,但该方式效率低下。请问是否存在可在代码中直接获取性能指标的方法?


解决方案

1. 自定义StatsEngine实时捕获指标

这是社区版最可靠的方式,通过扩展Gatling的StatsEngine类,重写日志方法来实时收集每个请求的响应时间、状态等数据,完全跳过报告生成环节。

先编写自定义StatsEngine:

import io.gatling.core.stats._
import io.gatling.core.stats.message._

class CustomStatsEngine(delegate: StatsEngine) extends StatsEngine {
  // 保留Gatling默认统计逻辑,避免影响原有功能
  override def start(): Unit = delegate.start()
  override def stop(): Unit = delegate.stop()
  override def logUserStart(session: Session): Unit = delegate.logUserStart(session)
  override def logUserEnd(session: Session): Unit = delegate.logUserEnd(session)
  
  // 重写logResponse方法,捕获每个请求的关键指标
  override def logResponse(
    session: Session,
    requestName: String,
    startTimestamp: Long,
    endTimestamp: Long,
    status: Status,
    responseCode: Option[String],
    message: Option[String]
  ): Unit = {
    // 计算响应时间(单位:毫秒)
    val responseTime = endTimestamp - startTimestamp
    // 这里可按需处理指标:打印、存入内存队列、写入数据库等
    println(s"[实时指标] 请求名: $requestName, 响应时间: $responseTime ms, 状态: $status, 响应码: ${responseCode.getOrElse("无")}")
    
    // 必须调用委托方法,保证Gatling默认统计流程正常执行
    delegate.logResponse(session, requestName, startTimestamp, endTimestamp, status, responseCode, message)
  }
}

然后在你的Simulation类中配置这个自定义引擎:

override def setUp(scn: ScenarioBuilder*): Simulation = {
  // 创建自定义StatsEngine,包装默认引擎
  val customStatsEngine = new CustomStatsEngine(super.statsEngine)
  // 应用自定义引擎到测试配置
  super.setUp(scn:_*).protocols(httpProtocol).statsEngine(customStatsEngine)
}

2. 测试结束后获取汇总指标

如果需要测试完成后的整体统计数据,可以利用Simulation的afterSimulation生命周期钩子,通过Gatling内部统计对象获取汇总指标。注意:部分内部API可能随版本变动,使用时要核对Gatling版本。

示例代码:

import io.gatling.core.stats.writer.ConsoleStatsWriter
import io.gatling.commons.shared.unstable.model.stats.GeneralStats

override def afterSimulation(): Unit = {
  super.afterSimulation()
  
  // 尝试从默认ConsoleStatsWriter中获取汇总统计
  statsEngine match {
    case writer: ConsoleStatsWriter =>
      val generalStats: GeneralStats = writer.generalStats
      println("\n[汇总指标]")
      println(s"总请求数: ${generalStats.total}")
      println(s"成功请求数: ${generalStats.successful}")
      println(s"失败请求数: ${generalStats.failed}")
      println(s"最小响应时间: ${generalStats.minResponseTime} ms")
      println(s"最大响应时间: ${generalStats.maxResponseTime} ms")
      println(s"平均响应时间: ${generalStats.meanResponseTime} ms")
      println(s"95分位响应时间: ${generalStats.percentile1} ms")
      println(s"99分位响应时间: ${generalStats.percentile2} ms")
    case _ => println("无法获取汇总指标,请检查StatsEngine类型")
  }
}

3. 企业版专属Metrics API

如果使用Gatling企业版,官方提供了现成的Metrics API,可直接获取实时和历史性能指标,无需自定义开发。但社区版不支持此功能。


内容的提问来源于stack exchange,提问作者Asad Mahmood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:04:58