Skip to content

Dockerized benchmarking framework#337

Merged
mum4k merged 70 commits intoenvoyproxy:masterfrom
oschaaf:ci-integration
Jun 26, 2020
Merged

Dockerized benchmarking framework#337
mum4k merged 70 commits intoenvoyproxy:masterfrom
oschaaf:ci-integration

Conversation

@oschaaf
Copy link
Copy Markdown
Member

@oschaaf oschaaf commented May 31, 2020

This PR has changes that make it easy to consume our integration testing as a benchmarking
tool framework for external repositories, allowing those to write custom tests for running in CI.

This probably needs to be split up into multiple PR's, but this allows reviewers to
have an early peek at what such PR's would lead up to.

The README.md in here has more context, but the primary goals are te be able to:

  • run the tests against arbitrary Envoy revisions
  • persist profile dumps, flamegraphs, and latency numbers per test
  • run the nighthawk tools via docker
  • offer stock tests, but also allow scaffolding consumer-specific tests

Example of a fully dockerized flow (more example in README.md):

# This script runs the dockerized benchmarking framework, which in
# turn will pull Nighthawk and Envoy in via docker. 

set -eo pipefail
set +x
set -u

# The benchmark logs and artifacts will be dropped here
OUTDIR="/home/oschaaf/code/envoy-perf-vscode/nighthawk/benchmarks/tmp/"
# Used to map the test that we want to see executed into the docker container
TEST_DIR="/home/oschaaf/code/envoy-perf-vscode/nighthawk/benchmarks/test/"

# Rebuild the docker in case something changed.
./docker_build.sh && 
docker run -it --rm \
  -v "/var/run/docker.sock:/var/run/docker.sock:rw" \
  -v "${OUTDIR}:${OUTDIR}:rw" \
  -v "${TEST_DIR}:/usr/local/bin/benchmarks/benchmarks.runfiles/nighthawk/benchmarks/external_tests/" \
  --network=host \
  --env NH_DOCKER_IMAGE="envoyproxy/nighthawk-dev:latest" \
  --env ENVOY_DOCKER_IMAGE_TO_TEST="envoyproxy/envoy-dev:f61b096f6a2dd3a9c74b9a9369a6ea398dbe1f0f" \
  --env TMPDIR="${OUTDIR}" \
  oschaaf/benchmark-dev:latest ./benchmarks --log-cli-level=info -vvvv 

Part of #245

Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
- Allow overriding some env vars so we can run outside of bazel
- Add a README.md detailing the plan & state

Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
oschaaf added 2 commits June 19, 2020 14:26
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
@oschaaf
Copy link
Copy Markdown
Member Author

oschaaf commented Jun 19, 2020

@mum4k thanks, I think I addressed everything. In addition, I added a small tweak to way docker gets run to avoid breakage in the docker flows when they use the latest Envoy revisions:
c24062f#diff-281f9acd4aa73a1b04f644ae61f98febR94

@oschaaf oschaaf added waiting-for-review A PR waiting for a review. and removed waiting-for-changes A PR waiting for comments to be resolved and changes to be applied. labels Jun 19, 2020
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
@oschaaf
Copy link
Copy Markdown
Member Author

oschaaf commented Jun 19, 2020

Another thing I should explicitly call out is that for benchmark/ I added some more python flake8 checks in CI.
Generally check more things, and specifically add docstring (format) checks.

https://github.com/envoyproxy/nighthawk/pull/337/files#diff-ae86159524d9bc451d3e3cc04dc48bb2

Copy link
Copy Markdown
Collaborator

@mum4k mum4k left a comment

Choose a reason for hiding this comment

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

Managed to complete the review now, sorry about any delay incurred.

from test.integration.nighthawk_test_server import NighthawkTestServer
from test.integration.nighthawk_grpc_service import NighthawkGrpcService

TIMESTAMP = time.strftime('%Y-%m-%d-%H-%M-%S')
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(nit) Can we either make this private (i.e. _TIMESTAMP), or document it?

"""

def __init__(self, ip_version, backend_count=1):
def __init__(self, ip_version, server_config, backend_count=1):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we document server_config in the Args: section of the docstring?

self.nighthawk_test_server_path = os.path.join(self.test_rundir, "nighthawk_test_server")
self.nighthawk_test_config_path = None
self.nighthawk_client_path = os.path.join(self.test_rundir, "nighthawk_client")
self.confdir = "nighthawk/test/integration/configurations/"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are adding some public attributes, can we document them in the class docstring? It will ideally have an "Attributes:" section.

This is partially pre-existing since none of the other attributes are documented there. Up to you if we document all now, or leave a todo for the pre-existing ones. We should still prefer making anything that can be private.

"[", "_").replace("]", "")
self.parameters["test_id"] = test_id
if os.getenv("NH_DOCKER_IMAGE", "") == "":
assert (os.path.exists(self.nighthawk_test_server_path))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we amend these assertions with some error message that would help the receiver of this error message understand what wen't wrong?

Something like:
assert False, "custom error message"

assert (os.path.exists(self.nighthawk_test_server_path))
assert (os.path.exists(self.nighthawk_client_path))

self.test_id = os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0].replace(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ideally attributes on classes are all initialized (and documented if public) inside the init method. Crating attributes "dynamically" in other methods makes it harder to find the complete list (API) of the class.

Can we initialize self.test_id to some useful value inside init? If nothing else, we can set it to the zero value of the same type (an empty string?).

args = [
args = []
if self.docker_image != "":
# TODO(XXX): As of https://github.com/envoyproxy/envoy/commit/e8a2d1e24dc9a0da5273442204ec3cdfad1e7ca8
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did we mean to replace XXX with a value?


Path(self.tmpdir).mkdir(parents=True, exist_ok=True)

with tempfile.NamedTemporaryFile(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Are there any parts of this function that we could move out so that we make init shorter and easier to follow?

ip_version, "--config-path", parameters)
ip_version, "--config-path", parameters, tag)

def getCliVersionString(self):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we document this method?

import pytest

from test.integration.integration_test_fixtures import http_test_server_fixture
from test.integration.integration_test_fixtures import (http_test_server_fixture, server_config)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(optional for this PR) comment about only importing modules / packages applies here too.

Optional, because it is pre-existing and we probably don't want to increase the scope of this PR.

@mum4k mum4k added waiting-for-changes A PR waiting for comments to be resolved and changes to be applied. and removed waiting-for-review A PR waiting for a review. labels Jun 22, 2020
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
@oschaaf oschaaf added waiting-for-review A PR waiting for a review. and removed waiting-for-changes A PR waiting for comments to be resolved and changes to be applied. labels Jun 24, 2020
oschaaf added 2 commits June 24, 2020 23:44
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Copy link
Copy Markdown
Collaborator

@mum4k mum4k left a comment

Choose a reason for hiding this comment

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

Last comment and a complete review.

"""
Base class for running a server in a separate process.

Arguments:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(nit) The "Args:" section of a class docstring actually belongs to the docstring of the initializer (init). Would you mind moving it there?

I am also happy to do this in a follow-up PR since this is minor, just let me know.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I prefer to do it in a follow up: this file exists out of benchmarks/, I'm hoping to tighten up the format checking so that I can get all the python to comply with the check format rules that are now specific to benchmark/. Being backed by that makes it easier, as the doc string format isn't in my muscle memory yet. Added a note to #371 as a reminder.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Forgot to mark this is ready for review after posting the comment above - just did so.

@mum4k mum4k added waiting-for-changes A PR waiting for comments to be resolved and changes to be applied. and removed waiting-for-review A PR waiting for a review. labels Jun 25, 2020
@oschaaf oschaaf added waiting-for-review A PR waiting for a review. and removed waiting-for-changes A PR waiting for comments to be resolved and changes to be applied. labels Jun 26, 2020
@mum4k mum4k merged commit 6747458 into envoyproxy:master Jun 26, 2020
wjuan-AFK pushed a commit to wjuan-AFK/nighthawk that referenced this pull request Jul 14, 2020
This PR has changes that make it easy to consume our integration testing as a benchmarking
tool framework for external repositories, allowing those to write custom tests for running in CI.

This probably needs to be split up into multiple PR's, but this allows reviewers to
have an early peek at what such PR's would lead up to.

The `README.md` in here has more context, but the primary goals are te be able to:
- run the tests against arbitrary Envoy revisions
- persist profile dumps, flamegraphs, and latency numbers per test
- run the nighthawk tools via docker
- offer stock tests, but also allow scaffolding consumer-specific tests

Example of a fully dockerized flow (more example in `README.md`):

```

set -eo pipefail
set +x
set -u

OUTDIR="/home/oschaaf/code/envoy-perf-vscode/nighthawk/benchmarks/tmp/"
TEST_DIR="/home/oschaaf/code/envoy-perf-vscode/nighthawk/benchmarks/test/"

./docker_build.sh &&
docker run -it --rm \
  -v "/var/run/docker.sock:/var/run/docker.sock:rw" \
  -v "${OUTDIR}:${OUTDIR}:rw" \
  -v "${TEST_DIR}:/usr/local/bin/benchmarks/benchmarks.runfiles/nighthawk/benchmarks/external_tests/" \
  --network=host \
  --env NH_DOCKER_IMAGE="envoyproxy/nighthawk-dev:latest" \
  --env ENVOY_DOCKER_IMAGE_TO_TEST="envoyproxy/envoy-dev:f61b096f6a2dd3a9c74b9a9369a6ea398dbe1f0f" \
  --env TMPDIR="${OUTDIR}" \
  oschaaf/benchmark-dev:latest ./benchmarks --log-cli-level=info -vvvv
```

Part of envoyproxy#245
oschaaf added a commit that referenced this pull request Jul 16, 2020
In #337 some review comments related to doc comments have been postponed to a followup.

- Adds more flake8 convention checks. This broadens the checks we introduced in the
benchmarking flow to cover the global code base, and exclude a few
files that we either don't own or care about.
- Updates yapf & flake8 version requirements, which enhances automatic formatting,
as well as fixes a python 3.8 compatibility bug.

Fixes #371
Fixes #400

Summary of compliance failures under the proposed checks before this change:

13    D100 Missing docstring in public module
2     D101 Missing docstring in public class
9     D102 Missing docstring in public method
46    D103 Missing docstring in public function
4     D107 Missing docstring in __init__
29    D200 One-line docstring should fit on one line with quotes
9     D202 No blank lines allowed after function docstring
32    D205 1 blank line required between summary line and description
3     D208 Docstring is over-indented
1     D209 Multi-line docstring closing quotes should be on a separate line
1     D210 No whitespaces allowed surrounding docstring text
1     D300 Use """triple double quotes"""
39    D400 First line should end with a period
16    D401 First line should be in imperative mood
1     E124 closing bracket does not match visual indentation
2     E125 continuation line with same indent as next logical line
7     E126 continuation line over-indented for hanging indent
1     E401 multiple imports on one line
2     E714 test for object identity should be 'is not'
4     F403 'from test.integration.utility import *' used; unable to detect undefined names
152   F405 'assertCounterEqual' may be undefined, or defined from star imports: test.integration.utility
2     F841 local variable 'logs' is assigned to but never used
8     W291 trailing whitespace
1     W293 blank line contains whitespace
3     W504 line break after binary operator
1     W605 invalid escape sequence '\:'
389

Signed-off-by: Otto van der Schaaf oschaaf@we-amp.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P1 waiting-for-review A PR waiting for a review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants