Skip to content

Instantly share code, notes, and snippets.

@polarnik
Created September 18, 2023 08:20
Show Gist options
  • Save polarnik/891f7b3fbe3969d8ad6954e24bb20112 to your computer and use it in GitHub Desktop.
Save polarnik/891f7b3fbe3969d8ad6954e24bb20112 to your computer and use it in GitHub Desktop.
k6.io custom metrics example
import {requestCounter,
requestBodySizeTotal, requestBodySizeTrend,
requestContentLengthTotal, requestContentLengthTrend,
responseCounter,
responseSuccessCounter, responseSuccessRate,
responseSuccessStatusTrend, responseSuccessErrorCodeTrend, responseSuccessDurationTrend,
responseSuccessBodySizeTotal, responseSuccessBodySizeTrend,
responseSuccessContentLengthTotal, responseSuccessContentLengthTrend,
apdexTotal, apdexSatisfied, apdexTolerating, apdexFlustrated,
apdexDuration,
responseErrorStatusTrend, responseErrorCodeTrend,
responseErrorRate, responseErrorCounter,
responseErrorDurationTrend, responseErrorBodySizeTotal,
responseErrorBodySizeTrend, responseErrorContentLengthTotal,
responseErrorContentLengthTrend
} from "./metrics.js";
export function do_handleResponse(response, tags, expectedStatus, targetDuration) {
requestCounter.add(1, tags);
if(response.request != null && response.request.body != null) {
const bodySize = response.request.body.length;
requestBodySizeTotal.add(bodySize, tags);
requestBodySizeTrend.add(bodySize, tags);
}
if(response.request != null && response.request.headers["content-length"]) {
const bodySize = parseInt(response.request.headers["content-length"]);
requestContentLengthTotal.add(bodySize, tags);
requestContentLengthTrend.add(bodySize, tags);
}
responseCounter.add(1, tags);
apdexDuration.add(targetDuration, tags);
if(response.status === expectedStatus) {
responseSuccessCounter.add(1, tags);
responseSuccessRate.add(1, tags);
responseSuccessStatusTrend.add(response.status, tags);
responseSuccessErrorCodeTrend.add(response.error_code, tags);
const duration = response.timings.duration;
responseSuccessDurationTrend.add(duration, tags);
if(response.body != null) {
const bodySize = response.body.length;
responseSuccessBodySizeTotal.add(bodySize, tags);
responseSuccessBodySizeTrend.add(bodySize, tags);
}
if(response.headers["content-length"]) {
const bodySize = parseInt(response.headers["content-length"]);
responseSuccessContentLengthTotal.add(bodySize, tags);
responseSuccessContentLengthTrend.add(bodySize, tags);
}
apdexTotal.add(1, tags);
if(duration < targetDuration) {
apdexSatisfied.add(1, tags);
apdexTolerating.add(0, tags);
apdexFlustrated.add(0, tags);
} else if (duration < 4.0 * targetDuration) {
apdexSatisfied.add(0, tags);
apdexTolerating.add(1, tags);
apdexFlustrated.add(0, tags);
} else {
apdexSatisfied.add(0, tags);
apdexTolerating.add(0, tags);
apdexFlustrated.add(1, tags);
}
} else {
responseErrorStatusTrend.add(response.status, tags);
responseErrorCodeTrend.add(response.error_code, tags);
responseErrorRate.add(1, tags);
responseErrorCounter.add(1, tags);
const duration = response.timings.duration;
responseErrorDurationTrend.add(duration, tags);
if(response.body != null) {
const bodySize = response.body.length;
responseErrorBodySizeTotal.add(bodySize, tags);
responseErrorBodySizeTrend.add(bodySize, tags);
}
if(response.headers["content-length"]) {
const bodySize = parseInt(response.headers["content-length"]);
responseErrorContentLengthTotal.add(bodySize, tags);
responseErrorContentLengthTrend.add(bodySize, tags);
}
}
}
import {
totalResultsCounter,
totalResultsTrend,
totalResourcesCounter,
totalResourcesTrend,
totalMembersCounter,
totalMembersTrend
} from "./metrics.js";
import {do_handleResponse} from '../../common/util.js';
import {do_getTargetDuration} from '../../common/util.js';
export function do_handleResponse_plus(response, tagValues, expectedStatus) {
if(response.body != null && response.status === expectedStatus) {
const totalResults = response.json().totalResults;
totalResultsCounter.add(totalResults, tagValues);
totalResultsTrend.add(totalResults, tagValues);
if(response.json().hasOwnProperty('Resources')) {
totalResourcesCounter.add(response.json().Resources.length, tagValues);
totalResourcesTrend.add(response.json().Resources.length, tagValues);
for (const resource in response.json().Resources) {
if (resource.hasOwnProperty('members')) {
totalMembersCounter.add(resource.members.length, tagValues);
totalMembersTrend.add(resource.members.length, tagValues);
} else {
totalMembersCounter.add(0, tagValues);
totalMembersTrend.add(0, tagValues);
}
}
} else {
totalResourcesCounter.add(0, tagValues);
totalResourcesTrend.add(0, tagValues);
totalMembersCounter.add(0, tagValues);
totalMembersTrend.add(0, tagValues);
}
}
const DURATION = do_getTargetDuration(tagValues);
do_handleResponse(response, tagValues, expectedStatus, DURATION);
}
const arrTrend = [
'http_req_blocked',
'http_req_connecting',
'http_req_duration',
'http_req_receiving',
'http_req_sending',
'http_req_tls_handshaking',
'http_req_waiting',
'Request Body Size Trend',
'Request Content-Length Trend',
'Response Success Status Trend',
'Response Success Error Code Trend',
'Response Success Duration Trend',
'Response Success Body Size Trend',
'Response Success Content-Length Trend',
'APDEX Duration',
'Response Error Status Trend',
'Response Error Code Trend',
'Response Error Duration Trend',
'Response Error Body Size Trend',
'Response Error Content-Length Trend'
];
const arrCounter = [
'http_reqs',
'Request Counter',
'Request Body Size Total',
'Request Content-Length Total',
'Response Counter',
'Response Success Counter',
'Response Success Body Size Total',
'Response Success Content-Length Total',
'APDEX Total',
'APDEX Satisfied',
'APDEX Tolerating',
'APDEX Flustrated',
'Response Error Counter',
'Response Error Body Size Total',
'Response Error Content-Length Total'
];
const arrRate = [
'http_req_failed',
'Response Success Rate',
'Response Error Rate'
];
export function do_loadThresholds(opt, tagValues, name) {
tagValues['name'] = name;
Object.keys(tagValues).forEach(
(key)=>{
arrTrend.forEach(function (nameMetric, index, array) {
opt.thresholds[`${nameMetric}{${key}:${tagValues[key]}}`]=['max>=0'];
});
arrCounter.forEach(function (nameMetric, index, array) {
opt.thresholds[`${nameMetric}{${key}:${tagValues[key]}}`]=['count>=0'];
});
arrRate.forEach(function (nameMetric, index, array) {
opt.thresholds[`${nameMetric}{${key}:${tagValues[key]}}`]=['rate>=0'];
});
}
);
return opt;
}
export function do_loadThresholds_for_scenario(opt, tagValues, scenarioName) {
tagValues['scenario'] = scenarioName;
Object.keys(tagValues).forEach(
(key)=>{
arrTrend.forEach(function (nameMetric, index, array) {
opt.thresholds[`${nameMetric}{${key}:${tagValues[key]}}`]=['max>=0'];
});
arrCounter.forEach(function (nameMetric, index, array) {
opt.thresholds[`${nameMetric}{${key}:${tagValues[key]}}`]=['count>=0'];
});
arrRate.forEach(function (nameMetric, index, array) {
opt.thresholds[`${nameMetric}{${key}:${tagValues[key]}}`]=['rate>=0'];
});
}
);
return opt;
}
import {Rate, Trend, Counter} from 'k6/metrics';
export const requestCounter = new Counter('Request Counter');
export const requestBodySizeTotal = new Counter('Request Body Size Total');
export const requestBodySizeTrend = new Trend('Request Body Size Trend');
export const requestContentLengthTotal = new Counter('Request Content-Length Total');
export const requestContentLengthTrend = new Trend('Request Content-Length Trend');
export const responseCounter = new Counter('Response Counter');
export const responseSuccessCounter = new Counter('Response Success Counter');
export const responseSuccessRate = new Rate('Response Success Rate');
export const responseSuccessStatusTrend = new Trend('Response Success Status Trend');
export const responseSuccessErrorCodeTrend = new Trend('Response Success Error Code Trend');
export const responseSuccessDurationTrend = new Trend('Response Success Duration Trend'); //
export const responseSuccessBodySizeTotal = new Counter('Response Success Body Size Total'); //
export const responseSuccessBodySizeTrend = new Trend('Response Success Body Size Trend'); //
export const responseSuccessContentLengthTotal = new Counter('Response Success Content-Length Total'); //
export const responseSuccessContentLengthTrend = new Trend('Response Success Content-Length Trend');
export const apdexTotal = new Counter('APDEX Total');
export const apdexSatisfied = new Counter('APDEX Satisfied');
export const apdexTolerating = new Counter('APDEX Tolerating');
export const apdexFlustrated = new Counter('APDEX Flustrated'); //
export const apdexDuration = new Trend('APDEX Duration'); //
export const responseErrorStatusTrend = new Trend('Response Error Status Trend'); //
export const responseErrorCodeTrend = new Trend('Response Error Code Trend'); //
export const responseErrorRate = new Rate('Response Error Rate'); //
export const responseErrorCounter = new Counter('Response Error Counter');
export const responseErrorDurationTrend = new Trend('Response Error Duration Trend'); //
export const responseErrorBodySizeTotal = new Counter('Response Error Body Size Total');
export const responseErrorBodySizeTrend = new Trend('Response Error Body Size Trend'); //
export const responseErrorContentLengthTotal = new Counter('Response Error Content-Length Total');
export const responseErrorContentLengthTrend = new Trend('Response Error Content-Length Trend');
import {commonOptions, do_loadTreshholds, do_handleResponse, URL} from '../../common/util.js';
import http from 'k6/http';
import {GROUP} from "./common.GROUP.js";
const NAME = `${GROUP}?startIndex=value&count=1X&top3`;
do_loadTreshholds(commonOptions, NAME, GROUP);
export function do_GET_api_v1_top3_startIndex_count(url, auth, scenario) {
const startIndex = 1;
const count = 10;
const urlRequest = new URL(url);
urlRequest.searchParams.append('startIndex', startIndex.toString());
urlRequest.searchParams.append('count', count.toString());
const tagValues = { name: NAME, group: GROUP, scenario: scenario };
const response = http.get(urlRequest.toString(),
{ tags: tagValues, headers: { Authorization: auth }, timeout: "600s", responseType: "none"});
do_handleResponse(response, tagValues, 200);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment