Adding custom metric from csv file

Hello,
Is it possible to add custom metric for trend from a csv file? I am able to assign a variable and print the value from the csv file correctly but when I try to use the same variable to generate unique response time per request, I get an error.

ERRO[0005] TypeError: Object has no member ‘add’

Basically, I have set vus = data.lenth and each vu picks up a unique row from the csv file for post request. I want to capture the corresponding response time for each request using Trend in the report.
Is there an easier approach for this?
Thanks

Hi @alex977,

Can you please post the code you are running as I am not certain I understand what you tried :), thanks.

Hi @mstoykov,
Thanks for responding. Sorry for not making it clear the first time. Below is my script and csv file content.

my csv file content

AIds,BId,tagNewTrend
0122-1254-5579,112,Most RecentTag
0122-5932-5552,372,Most UpdatedTag
0122-1254-5987,239,Most LatestTag

my main.js script

import http from 'k6/http';
import { SharedArray } from "k6/data";
import papaparse from "https://jslib.k6.io/papaparse/5.1.1/index.js";
import { group, sleep, check } from 'k6';
import { Trend } from 'k6/metrics';
import { vu } from 'k6/execution';
import exec from "k6/execution";
import {RecentTag, UpdatedTag, LatestTag } from "./my_tags.js";;



const data = new SharedArray("credentials", function() {
   return papaparse.parse(open('./data.csv'), {header: true}).data; 
});


export const options = {
	scenarios: {
		login: {
		  executor: 'per-vu-iterations',
		  vus: data.length,
		  iterations: 1,
		  maxDuration: '10s',
		},
	  },
	
};





let payload = JSON.parse(open('./testdata_v1.json'));



export default function(token) {
    let headers = { 'Content-Type': 'application/json' };
	
	let $token = "a8X3yRXkCPTs"

	let data_Ids = data[vu.idInTest - 1].AIds;
	let hub_Ids = data[vu.idInTest - 1].BId;
	let tmpTrend = data[vu.idInTest - 1].tagNewTrend;
	

	let tmpTrend = Newtrend; 

	
    payload.parameter[0].valueString = data_Ids;
    payload.parameter[1].part[0].valueString = hub_Ids;

	
	const BASE_URL = 'https://example.test.com/resolve/';


    let f = JSON.stringify(payload);

    sleep(1);


        
		let res = http.request('POST', BASE_URL, JSON.stringify(({"resourceType":"Parameters","parameter":[{"name":"Ids","valueString": data_Ids},{"name":"context","part":[{"name":"randId","valueString": hub_Ids},{"name":"fhirtoken","valueString": $token},{"name":"sampleId","valueString":"23344"}]}]})), {

headers: headers,

});
		check(res, {

            'is status 200': (r) => r.status === 200});
	


	# able to get the tagID from the csv file 
		console.log("Individual API Response Time (ms): " + Newtrend + "  " + res.timings.duration);

	  Newtrend.add(res.timings.duration);		
};

So when I try to use the “Newtrend” I get the error message saying object has no “add” member.

Also, is there a way to have the VUs run in sequence rather than all at once. My response time for the VUs executing at the end is very high since all the VUs are getting executed in parallel.
How do I run the VUs in order so that all of the response times are similar? Thanks in advance.

I don’t see anywhere where you define newTrend as it’s explained in custom metrics.

From the csv it seems like you expect newTrend to somehow be defined from the csv file, but I don’t understand why you would expect that. Please try to explain your reasoning so we can possibly fix the documentation to make this less confusing for the next person :wink:

Sorry, looks like I forgot to put that in the description. I have imported the newTrend from the page.
import {RecentTag, UpdatedTag, LatestTag } from “./my_tags.js”;

the content of the my_tags.js file is below
let MostRecentTagTrend = new Trend(‘Most RecentTag’);
let MostUpdatedTagTrend = new Trend(‘Most UpdatedTag’);
let MostLatestTagTrend = new Trend(‘Most LatestTag’);

Please let me know if I have put this together in a better way :slight_smile:

Yes, but none of those are assigned to a variable newTrend they are assigned to mostRecentTagTrend and so on so you need to do mostRecentTagTrend.add(res.timings.duration) Where I guess you will choose the *TagTrend based on something :man_shrugging:

1 Like

Yes, if I directly put the mostRecentTagTrend.add then it works. But I would like to put a variable so that with each POST request I can capture the individual API response time.
I assume below code would pick one Trend defined in the csv and assign it to the VU?

let tmpTrend = data[vu.idInTest - 1].tagNewTrend;

Below, I am creating a new variable to be used dynamically with trend.

let Newtrend = tmpTrend;

then I was hoping that each time the POST request ran with a payload combo of AIds and BId, it would get me the individual response time.
Am I doing something wrong? I am kind of new to K6 so sorry for this mess of a process :wink:

data[...].tagNewTrend is a string not a metrics.Trend which is why that you are trying to do.

I guess you can make a map of string to Trends as in

let trends = {
   "trendName": new Trend("trendName"),
   "trendName2": new Trend("trendName2"),
}

and then have trends[data[vu....].tagNewTrend].add(res.timings.duration.

That seems like what you want to do.

1 Like

I have mapped the string to Trends as suggested and tried to generate the response time but got the below error. Any idea what is missing?
trends[data[vu.idInTest - 1].tagNewTrend].add(res.timings.duration);
ERRO[0002] TypeError: Cannot read property ‘add’ of undefined or null

Also one more thing that I may have not done it right.
When I use the VUs option as below
vus: data.length,
iterations: data.length,
I get the individual response time as desired but since the iterations repeat, I get duplicate response times.
INFO[0002] Individual API Response Time (ms): HTN MostRecentWeight 111.5304 source=console
INFO[0003] Individual API Response Time (ms): HTN OnThiazideOrThiazideTypeDiuretic 1259.0893 source=console
INFO[0003] Individual API Response Time (ms): HTN MostRecentWeight 66.1254 source=console
INFO[0003] Individual API Response Time (ms): HTN HasEssentialTremor 1616.3457 source=console
INFO[0003] Individual API Response Time (ms): HTN PriorBlood 1702.0189 source=console
INFO[0004] Individual API Response Time (ms): HTN HasOsteo 2019.2183 source=console
INFO[0004] Individual API Response Time (ms): HTN MostRecent61.5539 source=console
INFO[0004] Individual API Response Time (ms): HTN OnThiazide 229.8114 source=console
INFO[0005] Individual API Response Time (ms): HTN HasEssential 462.7554 source=console
INFO[0005] Individual API Response Time (ms): HTN HasOsteo 280.4483 source=console
INFO[0005] Individual API Response Time (ms): HTN PriorBlood 713.5124 source=console
INFO[0005] Individual API Response Time (ms): HTN MostRecent 67.969 source=console
INFO[0006] Individual API Response Time (ms): HTN OnThiazide 193.0096 source=console
INFO[0006] Individual API Response Time (ms): HTN HasEssential 449.4907 source=console
INFO[0007] Individual API Response Time (ms): HTN HasOsteo 480.4304 source=console
INFO[0007] Individual API Response Time (ms): HTN PriorBlood 479.7807 source=console
but if I go with one single iteration as below
vus: data.length,
iterations: 1,
the response time that are sent later increase from the server because of the wait time increase.
INFO[0002] Individual API Response Time (ms): HTN MostRecent 99.7327 source=console
INFO[0003] Individual API Response Time (ms): HTN OnThiazide 1501.4011 source=console
INFO[0003] Individual API Response Time (ms): HTN PriorBlood 1618.4642 source=console
INFO[0004] Individual API Response Time (ms): HTN HasEssential 1875.9909 source=console
INFO[0004] Individual API Response Time (ms): HTN HasOsteo 1934.0077 source=console
In second scenario, is the VUs getting executed in parallel or in sequence?
Thanks for all the help.

Given this error you either did not create a k6 Trend in the map for each tag entry in data or you have some other small mistake.

You can console.log(JSON.stringify(something)) to see a json representation of something.

This will likely help you figure what is wrong, if you log parts of the line that gives you the error.

1 Like

Hi @mstoykov,
Thank you so much, this worked like a charm finally.

Would you also please point me how I can modify the VUs and Iteration property to get my response time report right?
When I use the VUs option as below

vus: data.length,
iterations: data.length,

I get the individual response time as desired but since the iterations repeat, I get duplicate response times.

INFO[0002] Individual API Response Time (ms): HTN MostRecentWeight 111.5304 source=console
INFO[0003] Individual API Response Time (ms): HTN OnThiazideOrThiazideTypeDiuretic 1259.0893 source=console
INFO[0003] Individual API Response Time (ms): HTN MostRecentWeight 66.1254 source=console
INFO[0003] Individual API Response Time (ms): HTN HasEssentialTremor 1616.3457 source=console
INFO[0003] Individual API Response Time (ms): HTN PriorBlood 1702.0189 source=console
INFO[0004] Individual API Response Time (ms): HTN HasOsteo 2019.2183 source=console
INFO[0004] Individual API Response Time (ms): HTN MostRecent61.5539 source=console
INFO[0004] Individual API Response Time (ms): HTN OnThiazide 229.8114 source=console
INFO[0005] Individual API Response Time (ms): HTN HasEssential 462.7554 source=console
INFO[0005] Individual API Response Time (ms): HTN HasOsteo 280.4483 source=console
INFO[0005] Individual API Response Time (ms): HTN PriorBlood 713.5124 source=console
INFO[0005] Individual API Response Time (ms): HTN MostRecent 67.969 source=console
INFO[0006] Individual API Response Time (ms): HTN OnThiazide 193.0096 source=console
INFO[0006] Individual API Response Time (ms): HTN HasEssential 449.4907 source=console
INFO[0007] Individual API Response Time (ms): HTN HasOsteo 480.4304 source=console
INFO[0007] Individual API Response Time (ms): HTN PriorBlood 479.7807 source=console

but if I go with one single iteration as below

vus: data.length,
iterations: 1,

the response time that are sent later increase from the server because of the wait time increase.

INFO[0002] Individual API Response Time (ms): HTN MostRecent 99.7327 source=console
INFO[0003] Individual API Response Time (ms): HTN OnThiazide 1501.4011 source=console
INFO[0003] Individual API Response Time (ms): HTN PriorBlood 1618.4642 source=console
INFO[0004] Individual API Response Time (ms): HTN HasEssential 1875.9909 source=console
INFO[0004] Individual API Response Time (ms): HTN HasOsteo 1934.0077 source=console

In second scenario, is the VUs getting executed in parallel or in sequence? The later post request response times seem to be spiking.
Really appreciate your help and inputs.

@alex977 I didn’t quite understand what the question was asking about.

In second scenario, is the VUs getting executed in parallel or in sequence?

Given that you haven’t provided the full option or at least the full scenarios I would expect that this errors out if it’s just

export let options = {
  vus: data.length,
  iterations:1, 
}

as the iterations in that case are shared between VUs - meaning all the VUs will together do 1 iteration and if the VUs are more than 1 it means some will not make an iteration which is consired a configuration error.

Other than that … VUs are run concurrently and scenarios are also run concurrently, wheter or not that means truly in parallel depends on your configuration and whether you have mulitple CPU cores (which I expect you do :wink: ).

But please if you have separate questions - open a new thread.

1 Like