Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions docs/command_line_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -905,9 +905,9 @@ Rally usually installs and launches an Elasticsearch cluster internally and wipe
``user-tags``
~~~~~~~~~~~~~

This is only relevant when you want to run :doc:`tournaments </tournament>`. You can use this flag to attach an arbitrary text to the meta-data of each metric record and also the corresponding race. This will help you to recognize a race when you run ``esrally list races`` as you don't need to remember the concrete timestamp on which a race has been run but can instead use your own descriptive names.
You can use this flag to attach arbitrary text to the meta-data of each metric record and also the corresponding race. This will help you to recognize a race when you run ``esrally list races`` as you don't need to remember the concrete timestamp on which a race has been run but can instead use your own descriptive names.

The required format is ``key`` ":" ``value``. You can choose ``key`` and ``value`` freely. You can also specify multiple tags. They need to be separated by a comma.
The required format is in ``key`` ":" ``value`` pairs which can be defined as string (separated by comma), inline json or referenced from a json file.

**Example**

Expand All @@ -919,16 +919,31 @@ The required format is ``key`` ":" ``value``. You can choose ``key`` and ``valu

::

esrally race --track=pmc --user-tags="disk:SSD,data_node_count:4"
esrally race --track=pmc --user-tags='{"disk":"SSD","data_node_count":4}'



**Example**

::

cat user_tags.json
{
"issue": "rally-issue-1000",
"iteration": 9
}

esrally race --track=pmc --user-tags=./user_tags.json



When you run ``esrally list races``, this will show up again::

Race Timestamp Track Track Parameters Challenge Car User Tags
---------------- ------- ------------------ ------------------- -------- ------------------------------------
20160518T122341Z pmc append-no-conflicts defaults intention:github-issue-1234-baseline
20160518T112341Z pmc append-no-conflicts defaults disk:SSD,data_node_count:4
Race ID Race Timestamp Track Challenge Car ES Version Revision Rally Version Track Revision Team Revision User Tags
------------------------------------ ---------------- -------- ------------------- -------- -------------- ---------------------------------------- ---------------------------------- ---------------- --------------- -----------------------------
5479b7ca-85bf-4e22-bce9-d32ab6093190 20221103T140347Z pmc append-no-conflicts defaults 8.6.0-SNAPSHOT 14b2d2d37e25071f820af7e9af8edca7c5ad0ac3 2.7.1.dev0 (git revision: 16e534b) fee27e9 c9ca37f gc=cms, intention=github-issue-1234-baseline
2689abb1-2274-4919-8b21-1cbe66243040 20221103T140206Z pmc append-no-conflicts defaults 8.6.0-SNAPSHOT 14b2d2d37e25071f820af7e9af8edca7c5ad0ac3 2.7.1.dev0 (git revision: 16e534b) fee27e9 c9ca37f disk=SSD, data_node_count=4
41c5be35-55e8-45a8-8bf4-1ed91cb778e8 20221103T135132Z pmc append-no-conflicts defaults 8.6.0-SNAPSHOT 14b2d2d37e25071f820af7e9af8edca7c5ad0ac3 2.6.1.dev0 (git revision: c47c204) fee27e9 c9ca37f issue=rally-issue-1000, iteration=9

This will help you recognize a specific race when running ``esrally compare``.

Expand Down
35 changes: 2 additions & 33 deletions esrally/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,37 +304,6 @@ def metrics_store_class(cfg):
return InMemoryMetricsStore


def extract_user_tags_from_config(cfg):
"""
Extracts user tags into a structured dict

:param cfg: The current configuration object.
:return: A dict containing user tags. If no user tags are given, an empty dict is returned.
"""
user_tags = cfg.opts("race", "user.tags", mandatory=False)
return extract_user_tags_from_string(user_tags)


def extract_user_tags_from_string(user_tags):
"""
Extracts user tags into a structured dict

:param user_tags: A string containing user tags (tags separated by comma, key and value separated by colon).
:return: A dict containing user tags. If no user tags are given, an empty dict is returned.
"""
user_tags_dict = {}
if user_tags and user_tags.strip() != "":
try:
for user_tag in user_tags.split(","):
user_tag_key, user_tag_value = user_tag.split(":")
user_tags_dict[user_tag_key] = user_tag_value
except ValueError:
msg = "User tag keys and values have to separated by a ':'. Invalid value [%s]" % user_tags
logging.getLogger(__name__).exception(msg)
raise exceptions.SystemSetupError(msg)
return user_tags_dict


class SampleType(IntEnum):
Warmup = 0
Normal = 1
Expand Down Expand Up @@ -414,7 +383,7 @@ def open(self, race_id=None, race_timestamp=None, track_name=None, challenge_nam
self._car,
)

user_tags = extract_user_tags_from_config(self._config)
user_tags = self._config.opts("race", "user.tags", default_value={}, mandatory=False)
for k, v in user_tags.items():
# prefix user tag with "tag_" in order to avoid clashes with our internal meta data
self.add_meta_info(MetaInfoScope.cluster, None, "tag_%s" % k, v)
Expand Down Expand Up @@ -1312,7 +1281,7 @@ def create_race(cfg, track, challenge, track_revision=None):
environment = cfg.opts("system", "env.name")
race_id = cfg.opts("system", "race.id")
race_timestamp = cfg.opts("system", "time.start")
user_tags = extract_user_tags_from_config(cfg)
user_tags = cfg.opts("race", "user.tags", default_value={}, mandatory=False)
pipeline = cfg.opts("race", "pipeline")
track_params = cfg.opts("track", "params")
car_params = cfg.opts("mechanic", "car.params")
Expand Down
2 changes: 1 addition & 1 deletion esrally/rally.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ def dispatch_sub_command(arg_parser, args, cfg):
# use the race id implicitly also as the install id.
cfg.add(config.Scope.applicationOverride, "system", "install.id", args.race_id)
cfg.add(config.Scope.applicationOverride, "race", "pipeline", args.pipeline)
cfg.add(config.Scope.applicationOverride, "race", "user.tags", args.user_tag)
cfg.add(config.Scope.applicationOverride, "race", "user.tags", opts.to_dict(args.user_tag))
cfg.add(config.Scope.applicationOverride, "driver", "profiling", args.enable_driver_profiling)
cfg.add(config.Scope.applicationOverride, "driver", "assertions", args.enable_assertions)
cfg.add(config.Scope.applicationOverride, "driver", "on.error", args.on_error)
Expand Down
34 changes: 5 additions & 29 deletions tests/metrics_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from esrally import config, exceptions, metrics, paths, track
from esrally.metrics import GlobalStatsCalculator
from esrally.track import Challenge, Operation, Task, Track
from esrally.utils import opts


class MockClientFactory:
Expand Down Expand Up @@ -109,31 +110,6 @@ def side_effects(self):
return side_effect_list


class TestExtractUserTags:
def test_no_tags_returns_empty_dict(self):
cfg = config.Config()
assert len(metrics.extract_user_tags_from_config(cfg)) == 0

def test_missing_comma_raises_error(self):
cfg = config.Config()
cfg.add(config.Scope.application, "race", "user.tags", "invalid")
with pytest.raises(exceptions.SystemSetupError) as ctx:
metrics.extract_user_tags_from_config(cfg)
assert ctx.value.args[0] == "User tag keys and values have to separated by a ':'. Invalid value [invalid]"

def test_missing_value_raises_error(self):
cfg = config.Config()
cfg.add(config.Scope.application, "race", "user.tags", "invalid1,invalid2")
with pytest.raises(exceptions.SystemSetupError) as ctx:
metrics.extract_user_tags_from_config(cfg)
assert ctx.value.args[0] == "User tag keys and values have to separated by a ':'. Invalid value [invalid1,invalid2]"

def test_extracts_proper_user_tags(self):
cfg = config.Config()
cfg.add(config.Scope.application, "race", "user.tags", "os:Linux,cpu:ARM")
assert metrics.extract_user_tags_from_config(cfg) == {"os": "Linux", "cpu": "ARM"}


class TestEsClient:
class TransportMock:
def __init__(self, hosts):
Expand Down Expand Up @@ -364,7 +340,7 @@ def test_put_value_with_explicit_timestamps(self):
def test_put_value_with_meta_info(self):
throughput = 5000
# add a user-defined tag
self.cfg.add(config.Scope.application, "race", "user.tags", "intention:testing,disk_type:hdd")
self.cfg.add(config.Scope.application, "race", "user.tags", opts.to_dict("intention:testing,disk_type:hdd"))
self.metrics_store.open(self.RACE_ID, self.RACE_TIMESTAMP, "test", "append", "defaults", create=True)

# Ensure we also merge in cluster level meta info
Expand Down Expand Up @@ -436,7 +412,7 @@ def test_put_doc_no_meta_data(self):

def test_put_doc_with_metadata(self):
# add a user-defined tag
self.cfg.add(config.Scope.application, "race", "user.tags", "intention:testing,disk_type:hdd")
self.cfg.add(config.Scope.application, "race", "user.tags", opts.to_dict("intention:testing,disk_type:hdd"))
self.metrics_store.open(self.RACE_ID, self.RACE_TIMESTAMP, "test", "append", "defaults", create=True)

# Ensure we also merge in cluster level meta info
Expand Down Expand Up @@ -1738,7 +1714,7 @@ def test_calculate_global_stats(self):
cfg.add(config.Scope.application, "mechanic", "car.names", ["unittest_car"])
cfg.add(config.Scope.application, "mechanic", "car.params", {})
cfg.add(config.Scope.application, "mechanic", "plugin.params", {})
cfg.add(config.Scope.application, "race", "user.tags", "")
cfg.add(config.Scope.application, "race", "user.tags", {})
cfg.add(config.Scope.application, "race", "pipeline", "from-sources")
cfg.add(config.Scope.application, "track", "params", {})

Expand Down Expand Up @@ -1906,7 +1882,7 @@ def test_calculate_system_stats(self):
cfg.add(config.Scope.application, "mechanic", "car.names", ["unittest_car"])
cfg.add(config.Scope.application, "mechanic", "car.params", {})
cfg.add(config.Scope.application, "mechanic", "plugin.params", {})
cfg.add(config.Scope.application, "race", "user.tags", "")
cfg.add(config.Scope.application, "race", "user.tags", {})
cfg.add(config.Scope.application, "race", "pipeline", "from-sources")
cfg.add(config.Scope.application, "track", "params", {})

Expand Down