k6 Custom Tags Not Appearing in Output Fix
In this tutorial, you'll learn about k6 custom tags not appearing in output fix. We cover key concepts, practical examples, and best practices.
Your k6 test tags do not appear in the output — http_req_duration values are aggregated globally without per-endpoint or per-method breakdown. Tags must be set in the request parameters or in the tags option to enable filtering.
The Problem
import http from 'k6/http';
export default function () {
const res1 = http.get('https://api.example.com/users');
const res2 = http.get('https://api.example.com/orders');
const res3 = http.post('https://api.example.com/users', '{}');
}
http_req_duration........: avg=234ms p(95)=890ms
All requests are aggregated into a single metric — cannot distinguish between GET /users and POST /orders.
Step-by-Step Fix
1. Tag individual requests
import http from 'k6/http';
export default function () {
http.get('https://api.example.com/users', {
tags: { endpoint: 'users', method: 'GET' },
});
http.get('https://api.example.com/orders', {
tags: { endpoint: 'orders', method: 'GET' },
});
http.post('https://api.example.com/users', '{}', {
tags: { endpoint: 'users', method: 'POST' },
});
}
2. Set global tags in options
import http from 'k6/http';
export const options = {
tags: {
environment: 'staging',
team: 'backend',
service: 'api-gateway',
},
};
export default function () {
http.get('https://api.example.com/health');
}
3. Set per-endpoint thresholds with tags
export const options = {
thresholds: {
'http_req_duration{endpoint:users}': ['p(95)<500'],
'http_req_duration{endpoint:orders}': ['p(95)<2000'],
'http_req_duration{method:POST}': ['p(95)<3000'],
},
};
4. Tag checks and custom metrics
import http from 'k6/http';
import { check } from 'k6';
import { Trend } from 'k6/metrics';
const endpointLatency = new Trend('endpoint_latency');
export default function () {
const res = http.get('https://api.example.com/users', {
tags: { endpoint: 'users' },
});
endpointLatency.add(res.timings.duration, { endpoint: 'users' });
check(res, {
'users status is 200': (r) => r.status === 200,
});
}
5. Use dynamic tags from response data
import http from 'k6/http';
export default function () {
const res = http.get('https://api.example.com/users/1');
if (res.status === 200) {
const user = res.json();
http.put(`https://api.example.com/users/${user.id}`, JSON.stringify({
name: user.name,
}), {
tags: {
userRole: user.role,
userId: String(user.id),
},
});
}
}
Expected output:
http_req_duration{endpoint:users}....: avg=45ms p(95)=120ms
http_req_duration{endpoint:orders}...: avg=320ms p(95)=890ms
http_req_duration{method:POST}.......: avg=150ms p(95)=300ms
Prevention Tips
- Tag every request with endpoint and method for granular metrics
- Use global tags in
options.tagsfor environment/service identification - Set per-endpoint thresholds using tag selectors
- Tag custom metrics with context data for richer analysis
- Use short tag values — avoid long strings that bloat output
Common Mistakes with options tags
- Mixing let bindings with <- bindings in do notation, producing type errors
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
These mistakes appear frequently in real-world K6 code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro