Skip to content

Commit bb5d9e8

Browse files
authored
fix: include stacktrace when handling an error (#51)
1 parent 2a4298b commit bb5d9e8

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

src/sagemaker_inference/transformer.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@
1616
"""
1717
from __future__ import absolute_import
1818

19-
try:
20-
import http.client as http_client
21-
except ImportError:
22-
import httplib as http_client
19+
import importlib
20+
import traceback
2321

2422
try:
25-
from importlib.util import find_spec
23+
from importlib.util import find_spec # pylint: disable=ungrouped-imports
2624
except ImportError:
2725
import imp # noqa: F401
2826

@@ -42,7 +40,7 @@ def find_spec(module_name):
4240
return None
4341

4442

45-
import importlib # pylint: disable=ungrouped-imports
43+
from six.moves import http_client
4644

4745
from sagemaker_inference import content_types, environment, utils
4846
from sagemaker_inference.default_inference_handler import DefaultInferenceHandler
@@ -75,21 +73,22 @@ def __init__(self, default_inference_handler=None):
7573
self._output_fn = None
7674

7775
@staticmethod
78-
def handle_error(context, inference_exception):
76+
def handle_error(context, inference_exception, trace):
7977
"""Set context appropriately for error response.
8078
8179
Args:
82-
context: Inference context
83-
inference_exception: A subclass of BaseInferenceToolkitError that
84-
has information for error response
80+
context (mms.context.Context): The inference context.
81+
inference_exception (sagemaker_inference.errors.BaseInferenceToolkitError): An exception
82+
raised during inference, with information for the error response.
83+
trace (traceback): The stacktrace of the error.
8584
8685
Returns:
87-
str: error message
86+
str: The error message and stacktrace from the exception.
8887
"""
8988
context.set_response_status(
9089
code=inference_exception.status_code, phrase=inference_exception.phrase
9190
)
92-
return [inference_exception.message]
91+
return ["{}\n{}".format(inference_exception.message, trace)]
9392

9493
def transform(self, data, context):
9594
"""Take a request with input data, deserialize it, make a prediction, and return a
@@ -136,11 +135,14 @@ def transform(self, data, context):
136135
context.set_response_content_type(0, response_content_type)
137136
return [response]
138137
except Exception as e: # pylint: disable=broad-except
138+
trace = traceback.format_exc()
139139
if isinstance(e, BaseInferenceToolkitError):
140-
return self.handle_error(context, e)
140+
return self.handle_error(context, e, trace)
141141
else:
142142
return self.handle_error(
143-
context, GenericInferenceToolkitError(http_client.INTERNAL_SERVER_ERROR, str(e))
143+
context,
144+
GenericInferenceToolkitError(http_client.INTERNAL_SERVER_ERROR, str(e)),
145+
trace,
144146
)
145147

146148
def validate_and_initialize(self, model_dir=environment.model_dir): # type: () -> None

test/container/dummy/mme_handler_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def initialize(self, context):
9898
)
9999
self.mx_model.set_params(arg_params, aux_params, allow_missing=True)
100100
with open("synset.txt", "r") as f:
101-
self.labels = [l.rstrip() for l in f]
101+
self.labels = [line.rstrip() for line in f]
102102
except (mx.base.MXNetError, RuntimeError) as error:
103103
if re.search("Failed to allocate (.*) Memory", str(error), re.IGNORECASE):
104104
logging.error("Memory allocation exception: {}".format(error))

test/unit/test_transfomer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ def test_handle_validate_and_initialize_error(env, validate_user_module):
234234

235235
response = transformer.transform(data, context)
236236
assert test_error_message in str(response)
237+
assert "Traceback (most recent call last)" in str(response)
237238
context.set_response_status.assert_called_with(
238239
code=http_client.INTERNAL_SERVER_ERROR, phrase=test_error_message
239240
)
@@ -268,6 +269,7 @@ def __init__(self, status_code, message):
268269

269270
response = transformer.transform(data, context)
270271
assert test_error_message in str(response)
272+
assert "Traceback (most recent call last)" in str(response)
271273
context.set_response_status.assert_called_with(
272274
code=http_client.FORBIDDEN, phrase=test_error_message
273275
)

0 commit comments

Comments
 (0)