Skip to content

Commit ab4d980

Browse files
authored
Validate every event created by the elasticapm_client test client (#1091)
* Validate every event created by the elasticapm_client test client So far, only when using sending_elasticapm_client, events were validated. This made us miss things like #1088 and #1089. With this change, every single event is validated against the apm-server JSONSchema. * fix encoding error in tornado revealed by validation
1 parent 0326148 commit ab4d980

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

elasticapm/contrib/tornado/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def get_data_from_request(request_handler, request, config, event_type):
6060
try:
6161
body = tornado.escape.json_decode(request.body)
6262
except Exception:
63-
body = request.body
63+
body = str(request.body, errors="ignore")
6464

6565
if body is not None:
6666
result["body"] = body if config.capture_body in ("all", event_type) else "[REDACTED]"

tests/contrib/asyncio/tornado/tornado_tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,10 @@ async def test_capture_headers_body_is_dynamic(app, base_url, http_client):
220220
errors = elasticapm_client.events[constants.ERROR]
221221

222222
assert "headers" in transactions[0]["context"]["request"]
223-
assert transactions[0]["context"]["request"]["body"] == b"xyz"
223+
assert transactions[0]["context"]["request"]["body"] == "xyz"
224224
assert "headers" in transactions[0]["context"]["response"]
225225
assert "headers" in errors[0]["context"]["request"]
226-
assert errors[0]["context"]["request"]["body"] == b"xyz"
226+
assert errors[0]["context"]["request"]["body"] == "xyz"
227227

228228
assert "headers" not in transactions[2]["context"]["request"]
229229
assert "headers" not in transactions[2]["context"]["response"]

tests/fixtures.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,15 @@
6767
ERRORS_SCHEMA = os.path.join(cur_dir, "upstream", "json-specs", "error.json")
6868
TRANSACTIONS_SCHEMA = os.path.join(cur_dir, "upstream", "json-specs", "transaction.json")
6969
SPAN_SCHEMA = os.path.join(cur_dir, "upstream", "json-specs", "span.json")
70+
METRICSET_SCHEMA = os.path.join(cur_dir, "upstream", "json-specs", "metricset.json")
7071
METADATA_SCHEMA = os.path.join(cur_dir, "upstream", "json-specs", "metadata.json")
7172

7273

7374
with codecs.open(ERRORS_SCHEMA, encoding="utf8") as errors_json, codecs.open(
7475
TRANSACTIONS_SCHEMA, encoding="utf8"
7576
) as transactions_json, codecs.open(SPAN_SCHEMA, encoding="utf8") as span_json, codecs.open(
77+
METRICSET_SCHEMA, encoding="utf8"
78+
) as metricset_json, codecs.open(
7679
METADATA_SCHEMA, encoding="utf8"
7780
) as metadata_json:
7881
VALIDATORS = {
@@ -95,6 +98,12 @@
9598
base_uri="file:" + pathname2url(SPAN_SCHEMA), referrer="file:" + pathname2url(SPAN_SCHEMA)
9699
),
97100
),
101+
"metricset": jsonschema.Draft4Validator(
102+
json.load(metricset_json),
103+
resolver=jsonschema.RefResolver(
104+
base_uri="file:" + pathname2url(METRICSET_SCHEMA), referrer="file:" + pathname2url(METRICSET_SCHEMA)
105+
),
106+
),
98107
"metadata": jsonschema.Draft4Validator(
99108
json.load(metadata_json),
100109
resolver=jsonschema.RefResolver(
@@ -187,6 +196,7 @@ def elasticapm_client(request):
187196
sys.excepthook = original_exceptionhook
188197
execution_context.set_transaction(None)
189198
execution_context.set_span(None)
199+
assert not client._transport.validation_errors
190200

191201

192202
@pytest.fixture()
@@ -295,12 +305,19 @@ class DummyTransport(HTTPTransportBase):
295305
def __init__(self, url, *args, **kwargs):
296306
super(DummyTransport, self).__init__(url, *args, **kwargs)
297307
self.events = defaultdict(list)
308+
self.validation_errors = defaultdict(list)
298309

299310
def queue(self, event_type, data, flush=False):
300311
self._flushed.clear()
301312
data = self._process_event(event_type, data)
302313
self.events[event_type].append(data)
303314
self._flushed.set()
315+
if data is not None:
316+
validator = VALIDATORS[event_type]
317+
try:
318+
validator.validate(data)
319+
except jsonschema.ValidationError as e:
320+
self.validation_errors[event_type].append(e.message)
304321

305322
def start_thread(self, pid=None):
306323
# don't call the parent method, but the one from ThreadManager

0 commit comments

Comments
 (0)