in esrally/rally.py [0:0]
def create_arg_parser():
def valid_date(v):
pattern = "%Y%m%d"
try:
datetime.datetime.strptime(v, pattern)
# don't convert, just check that the format is correct, we'll use the string value later on anyway
return v
except ValueError:
msg = f"[{v}] does not conform to the pattern [yyyyMMdd]"
raise argparse.ArgumentTypeError(msg)
def positive_number(v):
value = int(v)
if value <= 0:
raise argparse.ArgumentTypeError(f"must be positive but was {value}")
return value
def non_empty_list(arg):
lst = opts.csv_to_list(arg)
if len(lst) < 1:
raise argparse.ArgumentError(argument=None, message="At least one argument required!")
return lst
def runtime_jdk(v):
if v == "bundled":
return v
else:
try:
return positive_number(v)
except argparse.ArgumentTypeError:
raise argparse.ArgumentTypeError(f"must be a positive number or 'bundled' but was {v}")
def supported_es_version(v):
if v:
min_es_version = versions.Version.from_string(version.minimum_es_version())
specified_version = versions.Version.from_string(v)
if specified_version < min_es_version:
raise argparse.ArgumentTypeError(f"must be at least {min_es_version} but was {v}")
return v
def revision(v):
return v.strip()
def add_track_source(subparser):
track_source_group = subparser.add_mutually_exclusive_group()
track_source_group.add_argument(
"--track-repository",
help="Define the repository from where Rally will load tracks (default: default).",
# argparse is smart enough to use this default only if the user did not use --track-path and also did not specify anything
default="default",
)
track_source_group.add_argument(
"--track-path",
help="Define the path to a track.",
)
subparser.add_argument(
"--track-revision",
help="Define a specific revision in the track repository that Rally should use.",
default=None,
type=revision,
)
# try to preload configurable defaults, but this does not work together with `--configuration-name` (which is undocumented anyway)
cfg = config.Config()
if cfg.config_present():
cfg.load_config()
preserve_install = cfg.opts("defaults", "preserve_benchmark_candidate", default_value=False, mandatory=False)
else:
preserve_install = False
parser = argparse.ArgumentParser(
prog=PROGRAM_NAME,
description=BANNER + "\n\n You Know, for Benchmarking Elasticsearch.",
epilog=f"Find out more about Rally at {console.format.link(doc_link())}",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"--version",
action="version",
version="%(prog)s " + version.version(),
)
subparsers = parser.add_subparsers(title="subcommands", dest="subcommand", help="")
race_parser = subparsers.add_parser("race", help="Run a benchmark")
# change in favor of "list telemetry", "list tracks", "list pipelines"
list_parser = subparsers.add_parser("list", help="List configuration options")
list_parser.add_argument(
"configuration",
metavar="configuration",
help="The configuration for which Rally should show the available options. "
"Possible values are: telemetry, tracks, pipelines, races, cars, elasticsearch-plugins, annotations",
choices=["telemetry", "tracks", "pipelines", "races", "cars", "elasticsearch-plugins", "annotations"],
)
list_parser.add_argument(
"--limit",
help="Limit the number of search results for recent races (default: 10).",
default=10,
)
list_parser.add_argument(
"--track",
help="Show only records from this track",
default=None,
)
list_parser.add_argument(
"--benchmark-name",
help="Show only records from with corresponding 'name' or 'benchmark-name' user tag",
default=None,
)
list_parser.add_argument(
"--from-date",
help="Show only records on or after this date (format: yyyyMMdd)",
type=valid_date,
default=None,
)
list_parser.add_argument(
"--to-date",
help="Show only records before or on this date (format: yyyyMMdd)",
type=valid_date,
default=None,
)
list_parser.add_argument(
"--challenge",
help="Show only records from this challenge",
default=None,
)
add_track_source(list_parser)
delete_parser = subparsers.add_parser("delete", help="Delete records")
delete_parser.add_argument(
"configuration",
metavar="configuration",
help="The configuration for which Rally should delete the available records. Possible values are: race, annotation",
choices=["race", "annotation"],
)
delete_parser.add_argument(
"--dry-run", help="Just show what would be done but do not apply the operation.", default=False, action="store_true"
)
delete_parser.add_argument("--id", help="Ids of the items to delete. Separate multiple ids with a comma.", required=True)
add_track_source(delete_parser)
info_parser = subparsers.add_parser("info", help="Show info about a track")
add_track_source(info_parser)
info_parser.add_argument(
"--track",
help=f"Define the track to use. List possible tracks with `{PROGRAM_NAME} list tracks`.",
# we set the default value later on because we need to determine whether the user has provided this value.
# default="geonames"
)
info_parser.add_argument(
"--track-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to the track as variables.",
default="",
)
info_parser.add_argument(
"--challenge",
help=f"Define the challenge to use. List possible challenges for tracks with `{PROGRAM_NAME} list tracks`.",
)
info_task_filter_group = info_parser.add_mutually_exclusive_group()
info_task_filter_group.add_argument(
"--include-tasks",
help="Defines a comma-separated list of tasks to run. By default all tasks of a challenge are run.",
)
info_task_filter_group.add_argument(
"--exclude-tasks",
help="Defines a comma-separated list of tasks not to run. By default all tasks of a challenge are run.",
)
create_track_parser = subparsers.add_parser("create-track", help="Create a Rally track from existing data")
create_track_parser.add_argument(
"--track",
required=True,
help="Name of the generated track",
)
create_track_parser.add_argument(
"--batch-size",
default=1000,
help="Number of documents to collect per call to Elasticsearch.",
)
indices_or_data_streams_group = create_track_parser.add_mutually_exclusive_group(required=True)
indices_or_data_streams_group.add_argument(
"--indices",
type=non_empty_list,
help="Comma-separated list of indices to include in the track",
)
indices_or_data_streams_group.add_argument(
"--data-streams",
type=non_empty_list,
help="Comma-separated list of data streams to include in the track",
)
create_track_parser.add_argument(
"--target-hosts",
default="",
required=True,
help="Comma-separated list of host:port pairs which should be targeted",
)
create_track_parser.add_argument(
"--client-options",
default=opts.ClientOptions.DEFAULT_CLIENT_OPTIONS,
help=f"Comma-separated list of client options to use. (default: {opts.ClientOptions.DEFAULT_CLIENT_OPTIONS})",
)
create_track_parser.add_argument(
"--output-path",
default=os.path.join(os.getcwd(), "tracks"),
help="Track output directory (default: tracks/)",
)
compare_parser = subparsers.add_parser("compare", help="Compare two races")
compare_parser.add_argument(
"--baseline",
required=True,
help=f"Race ID of the baseline (see {PROGRAM_NAME} list races).",
)
compare_parser.add_argument(
"--contender",
required=True,
help=f"Race ID of the contender (see {PROGRAM_NAME} list races).",
)
compare_parser.add_argument(
"--report-format",
help="Define the output format for the command line report (default: markdown).",
choices=["markdown", "csv"],
default="markdown",
)
compare_parser.add_argument(
"--report-numbers-align",
help="Define the output column number alignment for the command line report (default: decimal).",
choices=["right", "center", "left", "decimal"],
default="decimal",
)
compare_parser.add_argument(
"--report-file",
help="Write the command line report also to the provided file.",
default="",
)
compare_parser.add_argument(
"--show-in-report",
help="Whether to include the comparison in the results file.",
default=True,
)
build_parser = subparsers.add_parser("build", help="Builds an artifact")
build_parser.add_argument(
"--revision",
help="Define the source code revision for building the benchmark candidate. 'current' uses the source tree as is,"
" 'latest' fetches the latest version on the main branch. It is also possible to specify a commit id or a timestamp."
' The timestamp must be specified as: "@ts" where "ts" must be a valid ISO 8601 timestamp, '
'e.g. "@2013-07-27T10:37:00Z" (default: current). A combination of branch and timestamp is also possible,'
'e.g. "feature-branch@2023-04-06T14:52:31Z".',
default="current",
type=revision,
) # optimized for local usage, don't fetch sources
build_parser.add_argument(
"--target-os",
help="The name of the target operating system for which an artifact should be downloaded (default: current OS)",
)
build_parser.add_argument(
"--target-arch",
help="The name of the CPU architecture for which an artifact should be downloaded (default: current architecture)",
)
build_parser.add_argument(
"--team-repository",
help="Define the repository from where Rally will load teams and cars (default: default).",
default="default",
)
build_parser.add_argument(
"--team-revision",
help="Define a specific revision in the team repository that Rally should use.",
default=None,
type=revision,
)
build_parser.add_argument(
"--team-path",
help="Define the path to the car and plugin configurations to use.",
)
build_parser.add_argument(
"--car",
help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
default="defaults",
) # optimized for local usage
build_parser.add_argument(
"--car-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
default="",
)
build_parser.add_argument(
"--elasticsearch-plugins",
help="Define the Elasticsearch plugins to install. (default: install no plugins).",
default="",
)
build_parser.add_argument(
"--plugin-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to all plugins as variables.",
default="",
)
build_parser.add_argument(
"--source-build-method",
help="Method with which to build Elasticsearch and plugins from source",
choices=["docker", "default"],
default="default",
)
download_parser = subparsers.add_parser("download", help="Downloads an artifact")
download_parser.add_argument(
"--team-repository",
help="Define the repository from where Rally will load teams and cars (default: default).",
default="default",
)
download_parser.add_argument(
"--team-revision",
help="Define a specific revision in the team repository that Rally should use.",
default=None,
type=revision,
)
download_parser.add_argument(
"--team-path",
help="Define the path to the car and plugin configurations to use.",
)
download_parser.add_argument(
"--distribution-version",
type=supported_es_version,
help="Define the version of the Elasticsearch distribution to download. "
"Check https://www.elastic.co/downloads/elasticsearch for released versions.",
default="",
)
download_parser.add_argument(
"--distribution-repository",
help="Define the repository from where the Elasticsearch distribution should be downloaded (default: release).",
default="release",
)
download_parser.add_argument(
"--car",
help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
default="defaults",
) # optimized for local usage
download_parser.add_argument(
"--car-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
default="",
)
download_parser.add_argument(
"--target-os",
help="The name of the target operating system for which an artifact should be downloaded (default: current OS)",
)
download_parser.add_argument(
"--target-arch",
help="The name of the CPU architecture for which an artifact should be downloaded (default: current architecture)",
)
install_parser = subparsers.add_parser("install", help="Installs an Elasticsearch node locally")
install_parser.add_argument(
"--revision",
help="Define the source code revision for building the benchmark candidate. 'current' uses the source tree as is,"
" 'latest' fetches the latest version on the main branch. It is also possible to specify a commit id or a timestamp."
' The timestamp must be specified as: "@ts" where "ts" must be a valid ISO 8601 timestamp, '
'e.g. "@2013-07-27T10:37:00Z" (default: current).',
default="current",
type=revision,
) # optimized for local usage, don't fetch sources
# Intentionally undocumented as we do not consider Docker a fully supported option.
install_parser.add_argument(
"--build-type",
help=argparse.SUPPRESS,
choices=["tar", "docker"],
default="tar",
)
install_parser.add_argument(
"--team-repository",
help="Define the repository from where Rally will load teams and cars (default: default).",
default="default",
)
install_parser.add_argument(
"--team-revision",
help="Define a specific revision in the team repository that Rally should use.",
default=None,
type=revision,
)
install_parser.add_argument(
"--team-path",
help="Define the path to the car and plugin configurations to use.",
)
install_parser.add_argument(
"--runtime-jdk",
type=runtime_jdk,
help="The major version of the runtime JDK to use during installation.",
default=None,
)
install_parser.add_argument(
"--distribution-repository",
help="Define the repository from where the Elasticsearch distribution should be downloaded (default: release).",
default="release",
)
install_parser.add_argument(
"--distribution-version",
type=supported_es_version,
help="Define the version of the Elasticsearch distribution to download. "
"Check https://www.elastic.co/downloads/elasticsearch for released versions.",
default="",
)
install_parser.add_argument(
"--car",
help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
default="defaults",
) # optimized for local usage
install_parser.add_argument(
"--car-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
default="",
)
install_parser.add_argument(
"--elasticsearch-plugins",
help="Define the Elasticsearch plugins to install. (default: install no plugins).",
default="",
)
install_parser.add_argument(
"--plugin-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to all plugins as variables.",
default="",
)
install_parser.add_argument(
"--network-host",
help="The IP address to bind to and publish",
default="127.0.0.1",
)
install_parser.add_argument(
"--http-port",
help="The port to expose for HTTP traffic",
default="39200",
)
install_parser.add_argument(
"--node-name",
help="The name of this Elasticsearch node",
default="rally-node-0",
)
install_parser.add_argument(
"--master-nodes",
help="A comma-separated list of the initial master node names",
default="",
)
install_parser.add_argument(
"--seed-hosts",
help="A comma-separated list of the initial seed host IPs",
default="",
)
install_parser.add_argument(
"--source-build-method",
help="Method with which to build Elasticsearch and plugins from source",
choices=["docker", "default"],
default="default",
)
install_parser.add_argument(
"--installation-id",
required=False,
help="The id to use for the installation",
default=str(uuid.uuid4()),
)
for p in [race_parser, install_parser]:
p.add_argument(
"--cluster-name",
help="The name of this Elasticsearch cluster",
default="rally-benchmark",
)
start_parser = subparsers.add_parser("start", help="Starts an Elasticsearch node locally")
start_parser.add_argument(
"--installation-id",
required=True,
help="The id of the installation to start",
# the default will be dynamically derived by racecontrol based on the presence / absence of other command line options
default="",
)
start_parser.add_argument(
"--race-id",
required=True,
help="Define a unique id for this race.",
default="",
)
start_parser.add_argument(
"--runtime-jdk",
type=runtime_jdk,
help="The major version of the runtime JDK to use.",
default=None,
)
start_parser.add_argument(
"--telemetry",
help=f"Enable the provided telemetry devices, provided as a comma-separated list. List possible telemetry "
f"devices with `{PROGRAM_NAME} list telemetry`.",
default="",
)
start_parser.add_argument(
"--telemetry-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to the telemetry devices as parameters.",
default="",
)
stop_parser = subparsers.add_parser("stop", help="Stops an Elasticsearch node locally")
stop_parser.add_argument(
"--installation-id",
required=True,
help="The id of the installation to stop",
# the default will be dynamically derived by racecontrol based on the presence / absence of other command line options
default="",
)
stop_parser.add_argument(
"--preserve-install",
help=f"Keep the benchmark candidate and its index. (default: {str(preserve_install).lower()}).",
default=preserve_install,
action="store_true",
)
for p in [list_parser, race_parser]:
p.add_argument(
"--distribution-version",
type=supported_es_version,
help="Define the version of the Elasticsearch distribution to download. "
"Check https://www.elastic.co/downloads/elasticsearch for released versions.",
default="",
)
p.add_argument(
"--team-path",
help="Define the path to the car and plugin configurations to use.",
)
p.add_argument(
"--team-repository",
help="Define the repository from where Rally will load teams and cars (default: default).",
default="default",
)
p.add_argument(
"--team-revision",
help="Define a specific revision in the team repository that Rally should use.",
default=None,
type=revision,
)
race_parser.add_argument(
"--race-id",
help="Define a unique id for this race.",
default=str(uuid.uuid4()),
)
race_parser.add_argument(
"--pipeline",
help="Select the pipeline to run.",
# the default will be dynamically derived by racecontrol based on the presence / absence of other command line options
default="",
)
race_parser.add_argument(
"--revision",
help="Define the source code revision for building the benchmark candidate. 'current' uses the source tree as is,"
" 'latest' fetches the latest version on master. It is also possible to specify a commit id or a timestamp."
' The timestamp must be specified as: "@ts" where "ts" must be a valid ISO 8601 timestamp, '
'e.g. "@2013-07-27T10:37:00Z" (default: current).',
default="current",
type=revision,
) # optimized for local usage, don't fetch sources
add_track_source(race_parser)
race_parser.add_argument(
"--track",
help=f"Define the track to use. List possible tracks with `{PROGRAM_NAME} list tracks`.",
)
race_parser.add_argument(
"--track-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to the track as variables.",
default="",
)
race_parser.add_argument(
"--challenge",
help=f"Define the challenge to use. List possible challenges for tracks with `{PROGRAM_NAME} list tracks`.",
)
race_parser.add_argument(
"--car",
help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
default="defaults",
) # optimized for local usage
race_parser.add_argument(
"--car-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
default="",
)
race_parser.add_argument(
"--runtime-jdk",
type=runtime_jdk,
help="The major version of the runtime JDK to use.",
default=None,
)
race_parser.add_argument(
"--elasticsearch-plugins",
help="Define the Elasticsearch plugins to install. (default: install no plugins).",
default="",
)
race_parser.add_argument(
"--plugin-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to all plugins as variables.",
default="",
)
race_parser.add_argument(
"--target-hosts",
help="Define a comma-separated list of host:port pairs which should be targeted if using the pipeline 'benchmark-only' "
"(default: localhost:9200).",
default="",
) # actually the default is pipeline specific and it is set later
race_parser.add_argument(
"--load-driver-hosts",
help="Define a comma-separated list of hosts which should generate load (default: localhost).",
default="localhost",
)
race_parser.add_argument(
"--client-options",
help=f"Define a comma-separated list of client options to use. The options will be passed to the Elasticsearch "
f"Python client (default: {opts.ClientOptions.DEFAULT_CLIENT_OPTIONS}).",
default=opts.ClientOptions.DEFAULT_CLIENT_OPTIONS,
)
race_parser.add_argument(
"--on-error",
choices=["continue", "abort"],
help="Controls how Rally behaves on response errors (default: continue).",
default="continue",
)
race_parser.add_argument(
"--telemetry",
help=f"Enable the provided telemetry devices, provided as a comma-separated list. List possible telemetry "
f"devices with `{PROGRAM_NAME} list telemetry`.",
default="",
)
race_parser.add_argument(
"--telemetry-params",
help="Define a comma-separated list of key:value pairs that are injected verbatim to the telemetry devices as parameters.",
default="",
)
race_parser.add_argument(
"--distribution-repository",
help="Define the repository from where the Elasticsearch distribution should be downloaded (default: release).",
default="release",
)
task_filter_group = race_parser.add_mutually_exclusive_group()
task_filter_group.add_argument(
"--include-tasks",
help="Defines a comma-separated list of tasks to run. By default all tasks of a challenge are run.",
)
task_filter_group.add_argument(
"--exclude-tasks",
help="Defines a comma-separated list of tasks not to run. By default all tasks of a challenge are run.",
)
race_parser.add_argument(
"--user-tag",
"--user-tags",
help="Define a user-specific key-value pair (separated by ':'). It is added to each metric record as meta info. "
"Example: intention:baseline-ticket-12345",
default="",
)
race_parser.add_argument(
"--report-format",
help="Define the output format for the command line report (default: markdown).",
choices=["markdown", "csv"],
default="markdown",
)
race_parser.add_argument(
"--report-numbers-align",
help="Define the output column number alignment for the command line report (default: decimal).",
choices=["right", "center", "left", "decimal"],
default="decimal",
)
race_parser.add_argument(
"--show-in-report",
help="Define which values are shown in the summary report (default: available).",
choices=["available", "all-percentiles", "all"],
default="available",
)
race_parser.add_argument(
"--report-file",
help="Write the command line report also to the provided file.",
default="",
)
race_parser.add_argument(
"--preserve-install",
help=f"Keep the benchmark candidate and its index. (default: {str(preserve_install).lower()}).",
default=preserve_install,
action="store_true",
)
race_parser.add_argument(
"--test-mode",
help="Runs the given track in 'test mode'. Meant to check a track for errors but not for real benchmarks (default: false).",
default=False,
action="store_true",
)
race_parser.add_argument(
"--enable-driver-profiling",
help="Enables a profiler for analyzing the performance of calls in Rally's driver (default: false).",
default=False,
action="store_true",
)
race_parser.add_argument(
"--enable-assertions",
help="Enables assertion checks for tasks (default: false).",
default=False,
action="store_true",
)
race_parser.add_argument(
"--kill-running-processes",
action="store_true",
default=False,
help="If any processes is running, it is going to kill them and allow Rally to continue to run.",
)
race_parser.add_argument(
"--source-build-method",
help="Method with which to build Elasticsearch and plugins from source",
choices=["docker", "default"],
default="default",
)
###############################################################################
#
# The options below are undocumented and can be removed or changed at any time.
#
###############################################################################
# This option is intended to tell Rally to assume a different start date than 'now'. This is effectively just useful for things like
# backtesting or a benchmark run across environments (think: comparison of EC2 and bare metal) but never for the typical user.
race_parser.add_argument(
"--effective-start-date",
help=argparse.SUPPRESS,
type=lambda s: datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S"),
default=None,
)
# Skips checking that the REST API is available before proceeding with the benchmark
race_parser.add_argument(
"--skip-rest-api-check",
help=argparse.SUPPRESS,
action="store_true",
default=False,
)
add_parser = subparsers.add_parser("add", help="Add records")
add_parser.add_argument(
"configuration",
metavar="configuration",
help="The configuration for which Rally should add records. " "Possible values are: annotation",
choices=["annotation"],
)
add_parser.add_argument(
"--dry-run", help="Just show what would be done but do not apply the operation.", default=False, action="store_true"
)
add_parser.add_argument("--race-timestamp", help="Race timestamp", required=True)
add_parser.add_argument("--track", help="Track. If none given, applies to all tracks", default=None)
add_parser.add_argument(
"--chart-type",
help="Chart type to target. If none given, applies to all charts.",
choices=[
"query",
"script",
"stats",
"indexing",
"gc",
"index_times",
"merge_times",
"merge_count",
"refresh_times",
"segment_count",
"io",
"ml_processing_time",
],
default=None,
)
add_parser.add_argument("--chart-name", help="A chart name to target. If none given, applies to all charts.", default=None)
add_parser.add_argument("--message", help="Annotation message", required=True)
for p in [
list_parser,
delete_parser,
add_parser,
race_parser,
compare_parser,
build_parser,
download_parser,
install_parser,
start_parser,
stop_parser,
info_parser,
create_track_parser,
]:
# This option is needed to support a separate configuration for the integration tests on the same machine
p.add_argument(
"--configuration-name",
help=argparse.SUPPRESS,
default=None,
)
p.add_argument(
"--quiet",
help="Suppress as much as output as possible (default: false).",
default=False,
action="store_true",
)
p.add_argument(
"--offline",
help="Assume that Rally has no connection to the Internet (default: false).",
default=False,
action="store_true",
)
return parser