-
Notifications
You must be signed in to change notification settings - Fork 0
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
send Honeybadger alert on nonzero script exit #78
Merged
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
867ee19
add a wrapper that invokes a command, and sends a honeybadger alert i…
jmartin-sul 6834321
docker image entrypoint: use error_reporting_wrapper.py to run speech…
jmartin-sul 6d27f28
tests for error_reporting_wrapper.py
jmartin-sul b70ee41
add subprocess support to code coverage
jmartin-sul 9bf0d6a
notify honeybadger upon deployment
jmartin-sul File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
[run] | ||
cov-report = term,html | ||
omit = tests/* | ||
concurrency = multiprocessing | ||
parallel = true | ||
sigterm = true | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import dotenv | ||
import logging | ||
import os | ||
import sys | ||
|
||
from honeybadger import honeybadger | ||
from subprocess import run, CalledProcessError | ||
|
||
|
||
# This must be invoked before the logger is invoked for the first time | ||
def configure() -> None: | ||
dotenv.load_dotenv() | ||
|
||
# TODO: HB and logging config copied from speech_to_text.py, may eventually want | ||
# to centralize more and start organizing codebase as a package? | ||
honeybadger.configure( | ||
api_key=os.environ.get("HONEYBADGER_API_KEY", ""), | ||
environment=os.environ.get("HONEYBADGER_ENV", "stage"), | ||
) | ||
|
||
logging.basicConfig( | ||
level=logging.INFO, | ||
format="%(asctime)s :: %(levelname)s :: %(message)s", | ||
datefmt="%Y-%m-%dT%H:%M:%S%z", | ||
) | ||
|
||
|
||
# advantages of this vs using the `honeybadger exec` subcommand | ||
# of the honeybadger gem/command (see https://docs.honeybadger.io/lib/ruby/gem-reference/cli/): | ||
# 1. a little more control over what the error reporting sends along | ||
# 2. more honest reporting of error code: in my testing, a script that exited with a | ||
# return code of '1' was reported as having a return code of '256' by honeybadger | ||
# exec (but was correctly reported by this, when compared to running the command by itself and doing `echo $?`) | ||
# 3. this script will bubble up the return code of the wrapped script, whereas honeybadger exec always returns 0, | ||
# even when the wrapped script exits non-zero | ||
# 4. one or two fewer dependencies to add to the docker image (maybe ruby, depending on the base image; definitely | ||
# the honeybadger gem regardless, whereas we already have the python package in our python deps) | ||
# | ||
# disadvantages of this approach: a little more code of our own to maintain | ||
def run_with_error_reporting(cmd_with_args: list) -> int: | ||
returncode: int | ||
|
||
try: | ||
completed_process = run(cmd_with_args, check=True) | ||
returncode = completed_process.returncode | ||
|
||
logging.info(completed_process) | ||
except KeyboardInterrupt: | ||
logging.info(f"exiting {sys.argv[0]}") | ||
sys.exit() | ||
except CalledProcessError as e: | ||
returncode = e.returncode | ||
|
||
error_context = { | ||
"message": str(e), | ||
"cmd": e.cmd, | ||
"returncode": e.returncode, | ||
} | ||
logging.error(error_context) | ||
honeybadger.notify(e, context=error_context) | ||
|
||
return returncode | ||
|
||
|
||
if __name__ == "__main__": | ||
configure() | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this complaint is spurious, and that the tests do actually cover this? |
||
cmd_with_args = sys.argv[1:] # argv[0] is this script's name | ||
logging.info(f"command and args: {cmd_with_args}") | ||
|
||
# bubble up the exit code from the wrapped call | ||
sys.exit(run_with_error_reporting(cmd_with_args)) | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import error_reporting_wrapper | ||
import pytest | ||
|
||
from subprocess import run, CalledProcessError, CompletedProcess | ||
|
||
from unittest.mock import patch | ||
|
||
|
||
def test_error_reporting_wrapper_exit_zero(): | ||
completed_process = run(["cat", "Dockerfile"], check=True) | ||
assert completed_process.returncode == 0, "return code for successful command is 0" | ||
|
||
|
||
def test_error_reporting_wrapper_exit_nonzero(): | ||
completed_process = run(["cat", "foooooo"]) | ||
assert completed_process.returncode == 1, ( | ||
"return code for unsuccessful command is bubbled up through wrapper" | ||
) | ||
|
||
|
||
@patch("error_reporting_wrapper.honeybadger") | ||
def test_run_with_error_reporting_on_error_honeybadger(mock_honeybadger): | ||
returncode = error_reporting_wrapper.run_with_error_reporting(["cat", "foooooo"]) | ||
|
||
mock_honeybadger.notify.assert_called_once() | ||
args, kwargs = mock_honeybadger.notify.call_args | ||
context = kwargs["context"] | ||
assert isinstance(args[0], CalledProcessError) | ||
assert "returned non-zero exit status" in context["message"] | ||
assert context["cmd"] == ["cat", "foooooo"] | ||
assert context["returncode"] == 1 | ||
assert returncode == 1 | ||
|
||
|
||
# ignore utcnow warning from within honeybadger | ||
@pytest.mark.filterwarnings("ignore:datetime.datetime.utcnow") | ||
@patch("error_reporting_wrapper.logging") | ||
def test_run_with_error_reporting_on_error_logging(mock_logging): | ||
returncode = error_reporting_wrapper.run_with_error_reporting(["cat", "foooooo"]) | ||
|
||
mock_logging.error.assert_called_once() | ||
args, kwargs = mock_logging.error.call_args | ||
assert "returned non-zero exit status" in args[0]["message"] | ||
assert args[0]["cmd"] == ["cat", "foooooo"] | ||
assert args[0]["returncode"] == 1 | ||
assert returncode == 1 | ||
|
||
|
||
@patch("error_reporting_wrapper.logging") | ||
@patch("error_reporting_wrapper.honeybadger") | ||
def test_run_with_error_reporting_on_success(mock_honeybadger, mock_logging): | ||
returncode = error_reporting_wrapper.run_with_error_reporting(["cat", "Dockerfile"]) | ||
|
||
mock_honeybadger.notify.assert_not_called() | ||
mock_logging.error.assert_not_called() | ||
mock_logging.info.assert_called_once() | ||
args = mock_logging.info.call_args.args | ||
assert isinstance(args[0], CompletedProcess) | ||
assert returncode == 0 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggested by the docs: https://pytest-cov.readthedocs.io/en/latest/subprocess-support.html
but the tests still didn't seem to detect that
error_reporting_wrapper.py
's__main__
code did in fact get invoked.