输出扩展
k6 提供了许多指标和输出格式,但无法直接支持所有可能性。要存储或修改在活动 k6 测试期间捕获的指标,您可以创建自定义输出扩展。
输出扩展二进制文件可以使用 --out
标志将指标发送到自定义位置。创建自定义扩展的一些潜在原因可能包括:
- 支持尚未支持的时序数据库
- 添加派生指标数据用于存储
- 过滤指标,仅保留您关心的数据
与JavaScript 扩展一样,输出扩展依赖于扩展作者实现特定的 API。
开始之前
要运行本教程,您需要安装以下应用程序:
- Go
- Git
您还需要安装 xk6:
go install go.k6.io/xk6/cmd/xk6@latest
编写一个简单的扩展
- 设置一个工作目录。
mkdir xk6-output-logger; cd xk6-output-logger; go mod init xk6-output-logger
- 输出扩展的核心是一个实现了
output.Output
接口的结构体。
创建一个简单示例,该示例将 output 接口的 AddMetricSamples(samples []metrics.SampleContainer)
方法接收到的每组指标输出到控制台。
package log
import (
"fmt"
"strings"
"time"
"go.k6.io/k6/metrics"
"go.k6.io/k6/output"
)
// AddMetricSamples receives metric samples from the k6 Engine as they're emitted.
func (l *Logger) AddMetricSamples(samples []metrics.SampleContainer) {
for _, sample := range samples {
all := sample.GetSamples()
fmt.Fprintf(l.out, "%s [%s]\n", all[0].GetTime().Format(time.RFC3339Nano), metricKeyValues(all))
}
}
// metricKeyValues returns a string of key-value pairs for all metrics in the sample.
func metricKeyValues(samples []metrics.Sample) string {
names := make([]string, 0, len(samples))
for _, sample := range samples {
names = append(names, fmt.Sprintf("%s=%v", sample.Metric.Name, sample.Value))
}
return strings.Join(names, ", ")
}
- 注册模块以便在 k6 测试脚本中使用它们。
import "go.k6.io/k6/output"
// init is called by the Go runtime at application startup.
func init() {
output.RegisterExtension("logger", New)
}
注意
运行 k6 时,您必须使用
-o
或--out
标志注册的名称!
最终的扩展代码如下所示:
package log
import (
"fmt"
"io"
"strings"
"time"
"go.k6.io/k6/metrics"
"go.k6.io/k6/output"
)
// init is called by the Go runtime at application startup.
func init() {
output.RegisterExtension("logger", New)
}
// Logger writes k6 metric samples to stdout.
type Logger struct {
out io.Writer
}
// New returns a new instance of Logger.
func New(params output.Params) (output.Output, error) {
return &Logger{params.StdOut}, nil
}
// Description returns a short human-readable description of the output.
func (*Logger) Description() string {
return "logger"
}
// Start initializes any state needed for the output, establishes network
// connections, etc.
func (*Logger) Start() error {
return nil
}
// AddMetricSamples receives metric samples from the k6 Engine as they're emitted.
func (l *Logger) AddMetricSamples(samples []metrics.SampleContainer) {
for _, sample := range samples {
all := sample.GetSamples()
fmt.Fprintf(l.out, "%s [%s]\n", all[0].GetTime().Format(time.RFC3339Nano), metricKeyValues(all))
}
}
// metricKeyValues returns a string of key-value pairs for all metrics in the sample.
func metricKeyValues(samples []metrics.Sample) string {
names := make([]string, 0, len(samples))
for _, sample := range samples {
names = append(names, fmt.Sprintf("%s=%v", sample.Metric.Name, sample.Value))
}
return strings.Join(names, ", ")
}
// Stop finalizes any tasks in progress, closes network connections, etc.
func (*Logger) Stop() error {
return nil
}
请注意以下几点:
模块初始化函数
New()
接收output.Params
实例。通过此对象,扩展可以访问特定于输出的配置、文件系统接口、同步的标准输出和标准错误输出等。本例中的
AddMetricSamples
写入标准输出。在实际场景中,为了避免内存泄漏,可能需要定期缓冲和刷新此输出。下面我们将讨论一些可用于此目的的辅助函数。参考statsd
输出 获取示例。
编译您的扩展 k6
要构建包含此扩展的 k6 二进制文件,请运行:
xk6 build --with xk6-output-logger=.
注意
xk6-output-logger
是传递给go mod init
的 Go 模块名称。通常,这将是一个类似于
github.com/grafana/xk6-output-logger
的 URL。
使用您的扩展
现在我们可以将扩展与测试脚本一起使用了。
- 在一个新的 JavaScript 文件中,编写一些简单的测试逻辑。
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('https://quickpizza.grafana.com');
sleep(0.5);
}
- 现在,运行测试。
./k6 run test.js --out logger --quiet --no-summary --iterations 2
注意
--out logger
参数告诉 k6 使用您的自定义输出。标志--quiet --no-summary
配置 k6 只显示自定义输出。
您的输出应该类似于这样:
2022-07-01T08:55:09.59272-05:00 [http_reqs=1, http_req_duration=117.003, http_req_blocked=558.983, http_req_connecting=54.135, http_req_tls_handshaking=477.198, http_req_sending=0.102, http_req_waiting=116.544, http_req_receiving=0.357, http_req_failed=0]
2022-07-01T08:55:09.917036-05:00 [vus=1, vus_max=1]
2022-07-01T08:55:10.094196-05:00 [data_sent=446, data_received=21364, iteration_duration=1177.505083, iterations=1]
2022-07-01T08:55:10.213926-05:00 [http_reqs=1, http_req_duration=119.122, http_req_blocked=0.015, http_req_connecting=0, http_req_tls_handshaking=0, http_req_sending=0.103, http_req_waiting=118.726, http_req_receiving=0.293, http_req_failed=0]
2022-07-01T08:55:10.715323-05:00 [data_sent=102, data_received=15904, iteration_duration=620.862459, iterations=1]
注意事项
- 输出结构体可以选择实现其他接口,以便接收阈值或运行状态更新,甚至中断测试。
- 考虑到 k6 产生大量数据,请考虑使用
output.SampleBuffer
和output.PeriodicFlusher
来提高性能。参考statsd
输出 获取示例。 - 使用项目模板作为您的输出扩展的起点。
有问题?欢迎加入k6 社区论坛 的扩展讨论。