How to combine --tag cli flag and tags in script options?

When I try to combine the --tag command line flag and set tags in my script options I only see the tag specified in the command line flag. How can I have my metrics tagged with both tags?

import { sleep } from 'k6';

export const options = {
    stages: [{
        target: 1,
        duration: '5s'
    }],
    tags: {
        mytag: '123',
    }
};

export default function () {
    sleep(1);
    console.log('all green')
}

running the script with the following command properly tags the output with “mytag:123”

k6 run --out json=my_test_result.json test.js
{"type":"Point","data":{"time":"2022-03-22T18:28:26.851519-04:00","value":1,"tags":{"mytag":"123"}},"metric":"vus"}

running the script with the following command only results in the output being tagged with “foo:bar”

k6 run --tag foo=bar --out json=my_test_result.json test.js
{"type":"Point","data":{"time":"2022-03-22T18:15:36.610929-04:00","value":1,"tags":{"foo":"bar"}},"metric":"vus"}

I would like to be able to use both types of tags and have them merged. How can I accomplish that?

As is explained here, options specified from the CLI flags would generally overwrite the same option that was specified in the exported script options.

However, you can use k6’s environment variables to get around that: Options reference

Have something like this in your script:

export const options = {
    stages: [{
        target: 1,
        duration: '5s'
    }],
    tags: {
        mytag: '123',
        foo: __ENV.foo,
    }
};

And start k6 with k6 run --env foo=bar --out json=my_test_result.json test.js

Ah my apologies, I missed that section in the docs. Would it be possible to add a feature request to merge the options where possible? I get that when specifying an option like duration twice it makes sense to override, but it would be great to be able to merge the tags and only overwrite duplicate tags.

Unfortunately, it’s very, very unlikely we’ll ever implement something like this… :disappointed:

I understand how this might make some things like your use case slightly simpler, but in aggregate, it will probably add complexity to an already overly complex system. And we try to avoid breaking changes whenever possible, so existing k6 users are not afraid to update their k6 versions.

To give you some context about the config complexity, k6 has at least 5 different levels of configuration (defaults, JSON file, JS script options, environment variables, CLI flags), and some options (e.g. cloud) have even more ways of being configured. Some options are also complex, with their own sub-options… So we really want to reduce that complexity internally, since we use different libraries for these layers. If you look at this issue that collects some of the issues with out current config, you’d understand why we want to avoid introducing even more corner cases :sweat_smile:

Out of curiosity, what is the issue with the --env workaround I suggested above? Maybe we can improve that more easily than revamping the whole config?

I see, thanks @ned. I will give your suggestion above a try. We run k6 in a way that individual teams write their own scripts but then we run them in a centralized manner, so at run time I’d like to be able to provide a set of tags but also allow teams to set their own tags within their scripts. So the --env option will work, but it will require us to make sure that each individual script is also including the global tags passed in via the environment. Not terrible, just requires more coordination and configuration in many places instead of in one place.

You could maybe encapsulate some of that logic in a shared JS function that all of the teams import? :thinking: That function can traverse __ENV for anything that looks like a tag and include it in options.tags. Something like this:


import { getScriptTags } from "https://something/company-common-k6-libs.js";

export let options = {
    tags: getScriptTags(__ENV);
};

Then start the script with something like k6 run --env tag.foo=bar --env tag.key=value script.js. It’s not ideal, since it would require all of the teams to adopt this convention, but it seems like a fairly serviceable workaround?