Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workflow to run performance tests using opensearch-benchmark #3415

Merged
merged 8 commits into from
May 3, 2023
Merged

Workflow to run performance tests using opensearch-benchmark #3415

merged 8 commits into from
May 3, 2023

Conversation

rishabh6788
Copy link
Collaborator

Description

This PR adds support to run performance tests against OpenSearch cluster using opensearch-benchmark. The workflow is very similar to perf-tests with below mentioned updates and improvements:

  • Uses public cdk infra package opensearch-cluster-cdk instead of private opensearch-infra repo.
  • Uses opensearch-benchmark for running and analyzing performance run tests instead of custom internal tool.
  • Supports single and as well as multi-node clusters.
  • Supports adding additional OS config from the command line.

Issues Resolved

opensearch-project/opensearch-benchmark#102

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@codecov-commenter
Copy link

codecov-commenter commented Apr 18, 2023

Codecov Report

Merging #3415 (babffab) into main (8028342) will increase coverage by 0.09%.
The diff coverage is 93.59%.

❗ Current head babffab differs from pull request most recent head 9a7f6cb. Consider uploading reports for the commit 9a7f6cb to get more accurate results

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

@@            Coverage Diff             @@
##             main    #3415      +/-   ##
==========================================
+ Coverage   91.74%   91.84%   +0.09%     
==========================================
  Files         172      181       +9     
  Lines        4991     5272     +281     
==========================================
+ Hits         4579     4842     +263     
- Misses        412      430      +18     
Impacted Files Coverage Δ
...k_test/benchmark_test_runner_opensearch_plugins.py 83.33% <83.33%> (ø)
..._workflow/benchmark_test/benchmark_test_cluster.py 85.22% <85.22%> (ø)
src/run_benchmark_test.py 92.30% <92.30%> (ø)
...t_workflow/benchmark_test/benchmark_test_runner.py 95.00% <95.00%> (ø)
...benchmark_test/benchmark_test_runner_opensearch.py 96.55% <96.55%> (ø)
src/test_workflow/benchmark_test/benchmark_args.py 100.00% <100.00%> (ø)
..._workflow/benchmark_test/benchmark_test_runners.py 100.00% <100.00%> (ø)
...st_workflow/benchmark_test/benchmark_test_suite.py 100.00% <100.00%> (ø)
src/test_workflow/test_jsonargs.py 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty clean! Some nits.

Please document this in .md as part of this PR?

src/test_workflow/benchmark_test/benchmark_test_cluster.py Outdated Show resolved Hide resolved
src/test_workflow/benchmark_test/benchmark_args.py Outdated Show resolved Hide resolved
src/test_workflow/benchmark_test/benchmark_test_cluster.py Outdated Show resolved Hide resolved
subprocess.check_call(command, cwd=os.getcwd(), shell=True)
with open(self.output_file, "r") as read_file:
load_output = json.load(read_file)
print(load_output[self.stack_name])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use logging if you need to print something.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required, removed.

"minDistribution": "true" if self.args.minDistribution else "false",
"serverAccessType": config["Constants"]["serverAccessType"],
"restrictServerAccessTo": config["Constants"]["restrictServerAccessTo"],
"additionalConfig": self.args.additionalConfig,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of pass through params. I wonder whether we're better off not exposing all these command line options and only accepting a config file and passing it through here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please give an example here, not sure if I understood the comment properly.
@dblock

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm saying that almost all Count arguments come from args. I don't know whether that's the right answer, but a config file that contained all these options could be passed as 1 single argument --config foobar.yml. Then this code doesn't need to know about dataNodeCount for example, that would be contained inside foobar.yml.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea to keep them as args is that there may be cases where a user wants to try different cluster configurations for running benchmark in parallel with different node counts for each cluster. Another is the ML use case where a user wants to have ML node enabled.
@dblock

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. I think we're just arguing command line params vs. a config file.

src/run_benchmark_test.py Show resolved Hide resolved
src/test_workflow/benchmark_test/benchmark_args.py Outdated Show resolved Hide resolved
src/test_workflow/benchmark_test/benchmark_test_cluster.py Outdated Show resolved Hide resolved
"minDistribution": "true" if self.args.minDistribution else "false",
"serverAccessType": config["Constants"]["serverAccessType"],
"restrictServerAccessTo": config["Constants"]["restrictServerAccessTo"],
"additionalConfig": self.args.additionalConfig,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm saying that almost all Count arguments come from args. I don't know whether that's the right answer, but a config file that contained all these options could be passed as 1 single argument --config foobar.yml. Then this code doesn't need to know about dataNodeCount for example, that would be contained inside foobar.yml.

@rishabh6788 rishabh6788 requested a review from dblock April 25, 2023 00:03
Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still have the camelCase variables all over the place, that's not the convention in the rest of the project. Example: https://github.com/opensearch-project/opensearch-build/blob/main/src/test_workflow/perf_test/perf_args.py#L21

self.stack_name = f"opensearch-infra-stack-{self.args.stack_suffix}-{self.manifest.build.id}-{self.manifest.build.architecture}"

def start(self) -> None:
# os.chdir(self.work_dir)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented code

"minDistribution": "true" if self.args.minDistribution else "false",
"serverAccessType": config["Constants"]["serverAccessType"],
"restrictServerAccessTo": config["Constants"]["restrictServerAccessTo"],
"additionalConfig": self.args.additionalConfig,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. I think we're just arguing command line params vs. a config file.

@rishabh6788
Copy link
Collaborator Author

You still have the camelCase variables all over the place, that's not the convention in the rest of the project. Example: https://github.com/opensearch-project/opensearch-build/blob/main/src/test_workflow/perf_test/perf_args.py#L21

Got it! let me refactor everything and update accordingly. Too much coding in TS got me into this habit :-|

@rishabh6788
Copy link
Collaborator Author

You still have the camelCase variables all over the place, that's not the convention in the rest of the project. Example: https://github.com/opensearch-project/opensearch-build/blob/main/src/test_workflow/perf_test/perf_args.py#L21

Fixed it. Also added the TODO to get rid of hack I put to quote the json input argument.
@dblock

@rishabh6788 rishabh6788 requested a review from dblock April 27, 2023 17:49
Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs documentation in .md files for these new tests.

Code: I'm down to nits. Address those and it's ready to merge.

help="Do not delete the working temporary directory.")
parser.add_argument("--single-node", dest="single_node", action="store_true",
help="Is this a single node cluster")
parser.add_argument("--min-distribution", dest="min_distribution", action="store_true", help="Is it the "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put each argument such as help on its own line and it won't need to be wrapped like this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

getattr(namespace, self.dest)[key] = value


JsonArgs.__test__ = False # type:ignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call this file json_args.py and this won't be needed. It's also the convention.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, done!

class JsonArgs(argparse.Action):
def __call__(self, parser: Any, namespace: argparse.Namespace, values: Union[str, Sequence[Any], None], option_string: str = None) -> None:
setattr(namespace, self.dest, dict())
print(f"values are {values}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stray printf, remove.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

self.command = (
f"{base_command} opensearchproject/opensearch-benchmark:latest execute_test "
f"--workload={self.args.workload} --test-mode --pipeline=benchmark-only --target-hosts={endpoint}"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks messy, and uses an unnecessary local base_command variable.

self.command = "docker run"
if args.benchmark_config:
   self.command += " -v ..."
self.command += "opensearchproject/opensearch-benchmark:latest execute_test:
...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, done!


if args.user_tag:
user_tag = f"--user-tag=\"{args.user_tag}\""
self.command = f"{self.command} {user_tag}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.command += ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@rishabh6788
Copy link
Collaborator Author

rishabh6788 commented May 1, 2023

Needs documentation in .md files for these new tests.

Code: I'm down to nits. Address those and it's ready to merge.

Added README for benchmarking test. Have a TODO for adding jenkins job details once it is ready. It is still WIP. Will be updating the README as and when i get more clarity on requirements and different use-cases.
Addressed the comments.
@dblock

@rishabh6788 rishabh6788 requested a review from dblock May 2, 2023 06:15
Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor stuff for the markdown please.

@@ -174,6 +174,17 @@ Internal tools provide dashboards for monitoring cluster behavior during these t
|Indexing Latency|Consistent during each test iteration|upward trends|
|Query Latency|Varies based on the query being issued|upward trends|

### Benchmarking Tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update TOC

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that, updated!

@@ -174,6 +174,17 @@ Internal tools provide dashboards for monitoring cluster behavior during these t
|Indexing Latency|Consistent during each test iteration|upward trends|
|Query Latency|Varies based on the query being issued|upward trends|

### Benchmarking Tests
Runs benchmarking test on a remote opensource OpenSearch cluster. Uses [OpenSearch Benchmark](https://github.com/opensearch-project/OpenSearch-Benchmark) to run benchmark tests.
At a high-level the benchmarking test workflow uses [opensearch-cluster-cdk](https://github.com/opensearch-project/opensearch-cluster-cdk.git) to first set-up an OpenSearch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack! fixed!

@@ -174,6 +174,17 @@ Internal tools provide dashboards for monitoring cluster behavior during these t
|Indexing Latency|Consistent during each test iteration|upward trends|
|Query Latency|Varies based on the query being issued|upward trends|

### Benchmarking Tests
Runs benchmarking test on a remote opensource OpenSearch cluster. Uses [OpenSearch Benchmark](https://github.com/opensearch-project/OpenSearch-Benchmark) to run benchmark tests.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test or tests?

you can remove "to run benchmark tests", that's what it does

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

cluster (single/multi-node) and then executes `opensearch-benchmark` to run benchmark test against that cluster. The performance metric that opensearch-benchmark generates
during the run are ingested into another OS cluster for further analysis and dashboarding purpose.

The benchmarking tests will be run nightly and if you have a feature in any released/un-released OS version that you want to benchmark periodically please create an issue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we don't abbreviate OS, spell OpenSearch.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

@@ -237,6 +248,9 @@ After the performance test completes, it will report back the test results as we

The development is tracked by meta issue [#126](https://github.com/opensearch-project/opensearch-build/issues/126)

#### benchmarkTest job
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalize Like Other Titles

You can remove this for now since we don't have content.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed for now. Will add once we have the job ready to be merged.

Signed-off-by: Rishabh Singh <[email protected]>
@rishabh6788 rishabh6788 requested a review from dblock May 2, 2023 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants