从我的博客搬运:
http://keithmo.me/post/2017/12/2017-12-16-jmeter-grafana-dashboard/【警告】这篇东西是配置笔记,你会看到满屏鸡肠,不打算自己做一个可以不看。成品我已经传到官网了,能直接导入 Grafana 里,地址如下:
https://grafana.com/dashboards/4026接下来还会配 Gatling、服务器性能指标、数据库、MQ 的等等,都是把官网上一些比较好的拿来改造成方便自己看的样子
在服务器上跑 JMeter 做压测的话,给工具本身也配上实时监控是必须的,命令行输出能提供的信息太少。
JMeter 的 Backend Listener 支持 Graphite 和 InfluxDB,这里选择 InfluxDB 做时序数据库,支持类似 SQL 的查询语法是最大的优点。另外在 JMeter 3.2+ 里配置起来也比 Graphite 方便太多。(缺点是直到写这篇文章时官网文档都没更新,要自己查存储的字段,猜它有什么用)
Grafana 能配出非常漂亮的监控仪表板,就是配的过程非常痛苦,不做非常详细的笔记的话过几天又忘光了,于是有了这篇东西。
【前提】
InfluxdbBackendListenerClient
【注意】
吞吐率和响应时间图表只计算成功的请求(失败的通常没意义,超时失败的能在表格里看到数量),结果可能会跟 JMeter 里看到的有出入。
【效果】
已经上传到 Grafana 官网,可以从以下地址下载 JSON 文件,或通过 ID 4026
直接导入:
https://grafana.com/dashboards/4026
JMeter Backend Listener 参考配置:
JMeter Dashboard
Monitor your JMeter load test in real time with InfluxDB and Grafana.
load_test
Summary
, Errors
, Individual Transaction - $transaction
$data_source
data_source
$application
application
$data_source
SHOW TAG VALUES FROM "$measurement_name" WITH KEY = "application"
$transaction
transaction
$data_source
SHOW TAG VALUES FROM "$measurement_name" WITH KEY = "transaction" WHERE "application" =~ /^$application$/ AND "transaction" != 'internal' AND "transaction" != 'all'
可惜 templating 里不支持 $timeFilter
(由于 InfluxDB show tag values
语法的限制),时间久了之后各种接口名看着会比较乱。
$measurement_name
measurement_name
Measurement name
jmeter
(JMeter Backend Listener 默认)$send_interval
send_interval
Backend send interval
5
(JMeter InfluxdbBackendListenerClient 默认)编辑 Annotations & Alerts(Built-in)
Start/stop marker
$data_source
select text from events where $timeFilter
Singlestat - Total Requests
, Span 4
$data_source
[[send_interval]]s
SELECT sum("count") FROM "$measurement_name" WHERE ("application" =~ /^$application$/ AND "transaction" = 'all') AND $timeFilter GROUP BY time($__interval) fill(null)
Requests
0
0
Singlestat - Failed Requests
, Span 4
$data_source
[[send_interval]]s
SELECT sum("countError") FROM "$measurement_name" WHERE ("transaction" = 'all' AND "application" =~ /^$application$/) AND $timeFilter GROUP BY time($__interval) fill(null)
Failed
0
0
Singlestat - Error Rate %
, Span 4
$data_source
[[send_interval]]s
SELECT sum("error") / sum("all") FROM (SELECT sum("count") AS "all" FROM "$measurement_name" WHERE "transaction" = 'all' AND "application" =~ /^$application$/ AND $timeFilter GROUP BY time($__interval) fill(null)), (SELECT sum("countError") AS "error" FROM "$measurement_name" WHERE "transaction" = 'all' AND "application" =~ /^$application$/ AND $timeFilter GROUP BY time($__interval) fill(null))
2
0,0.01
1
0
Graph - Total Throughput
, Span: 4
$data_source
[[send_interval]]s
SELECT mean("count") / $send_interval FROM "$measurement_name" WHERE ("transaction" = 'all' AND "application" =~ /^$application$/) AND $timeFilter GROUP BY time($__interval) fill(null)
Req / sec
2
7
, Null value: null
Graph - Total Errors
, Span: 4
$data_source
[[send_interval]]s
SELECT sum("countError") FROM "$measurement_name" WHERE ("transaction" = 'all' AND "application" =~ /^$application$/) AND $timeFilter GROUP BY time($__interval) fill(null)
Num of Errors
0
0
7
, Null value: null
Graph - Active Threads
, Span: 4
$data_source
[[send_interval]]s
SELECT last("maxAT") FROM "$measurement_name" WHERE ("transaction" = 'internal' AND "application" =~ /^$application$/) AND $timeFilter GROUP BY time($__interval) fill(null)
Threads
0
0
7
, Null value: null
Graph - Transactions Response Times (95th pct)
, Span: 4
$data_source
[[send_interval]]s
SELECT mean("pct95.0") FROM "$measurement_name" WHERE ("statut" = 'ok' AND "application" =~ /^$application$/) AND $timeFilter GROUP BY "transaction", time($__interval) fill(null)
$tag_transaction
milliseconds(ms)
2
null
500
, ok, Fill, Line1500
, warning, Line5000
, critical, Fill, LineTable - Errors per Transaction
, Span: 4
$data_source
[[send_interval]]s
SELECT sum("count") FROM "$measurement_name" WHERE ("application" =~ /^$application$/ AND "statut" = 'ko') AND $timeFilter GROUP BY "transaction"
0
Table - Error Info
, Span: 8
$data_source
[[send_interval]]s
SELECT sum("count") FROM "$measurement_name" WHERE ("application" =~ /^$application$/ AND "responseCode" !~ /^$/) AND $timeFilter GROUP BY "responseCode","responseMessage"
0
复制第 1 行的图表(除了线程图),改一下 SQL 和一些细节就行。
Singlestat - Total Requests - $transaction
, Span 4
$data_source
[[send_interval]]s
SELECT sum("count") FROM "$measurement_name" WHERE ("application" =~ /^$application$/ AND "transaction" =~ /^$transaction$/ AND "statut" = 'all') AND $timeFilter GROUP BY time($__interval) fill(null)
Requests
0
0
Singlestat - Failed Requests - $transaction
, Span 4
$data_source
[[send_interval]]s
SELECT sum("count") FROM "$measurement_name" WHERE ("application" =~ /^$application$/ AND "transaction" =~ /^$transaction$/ AND "statut" = 'ko') AND $timeFilter GROUP BY time($__interval) fill(null)
Failed
0
0
Singlestat - Error Rate % - $transaction
, Span 4
$data_source
[[send_interval]]s
SELECT sum("error") / sum("all") FROM (SELECT sum("count") AS "all" FROM "$measurement_name" WHERE "transaction" =~ /^$transaction$/ AND "statut" = 'all' AND "application" =~ /^$application$/ AND $timeFilter GROUP BY time($__interval) fill(null)), (SELECT sum("count") AS "error" FROM "$measurement_name" WHERE "transaction" =~ /^$transaction$/ AND "statut" = 'ko' AND "application" =~ /^$application$/ AND $timeFilter GROUP BY time($__interval) fill(null))
2
0,0.01
1
0
Graph - Throughput - $transaction
, Span: 4
$data_source
[[send_interval]]s
SELECT last("count") / $send_interval FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval)
Req / sec
2
7
, Null value: null
Graph - Errors - $transaction
, Span: 4
$data_source
[[send_interval]]s
SELECT sum("count") FROM "$measurement_name" WHERE "application" =~ /^$application$/ AND "transaction" =~ /^$transaction$/ AND "statut" = 'ko' AND $timeFilter GROUP BY time($__interval) fill(null)
Num of Errors
0
0
7
1
null
Graph - Response Times - $transaction
, Span: 4
$data_source
[[send_interval]]s
SELECT last("avg") FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval)
Average
SELECT last("pct50.0") FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval)
Median
SELECT last("pct90.0") FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval) fill(null)
90th Percentile
SELECT last("pct95.0") FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval) fill(null)
95th Percentile
SELECT last("pct99.0") FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval) fill(null)
99th Percentile
SELECT last("max") FROM "$measurement_name" WHERE ("transaction" =~ /^$transaction$/ AND "statut" = 'ok') AND $timeFilter GROUP BY time($__interval) fill(null)
Max
milliseconds(ms)
2
null
500
, ok, Fill, Line1500
, warning, Line5000
, critical, Fill, Line导出的 JSON 文件没有 data source,无法直接导入,需要手动编辑文件,在 "__inputs": []
里加入以下:
{
"name": "JMETER_DASHBOARD",
"label": "DB name",
"description": "",
"type": "datasource",
"pluginId": "influxdb",
"pluginName": "InfluxDB"
},
如果想上传到官网,为了能正确分类,"__requires": []
里还要加入以下:
{
"type": "datasource",
"id": "influxdb",
"name": "InfluxDB",
"version": "1.4.0"
},
参考: