wscall: logged error, add err code in summary (#68741)
gitea-wip/wcs/pipeline/head Build started... Details

This commit is contained in:
Lauréline Guérin 2022-09-13 10:37:55 +02:00
parent b7ecac9b42
commit 106c98192c
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
6 changed files with 109 additions and 17 deletions

View File

@ -954,6 +954,38 @@ def test_geojson_datasource_bad_url(pub, http_requests, error_email, emails):
assert logged_error.workflow_id is None
assert logged_error.summary == "[DATASOURCE] Error reading JSON data source output (err 1)"
datasource = {
'type': 'geojson',
'value': 'http://remote.example.net/json-list-err1bis',
'notify_on_errors': True,
'record_on_errors': True,
}
assert data_sources.get_items(datasource) == []
assert 'Error reading JSON data source output (err_desc :()' in emails.get_latest('subject')
assert pub.loggederror_class.count() == 5
logged_error = pub.loggederror_class.select(order_by='id')[4]
assert logged_error.workflow_id is None
assert logged_error.summary == "[DATASOURCE] Error reading JSON data source output (err_desc :()"
datasource = {
'type': 'geojson',
'value': 'http://remote.example.net/json-list-errstr',
'notify_on_errors': True,
'record_on_errors': True,
}
assert data_sources.get_items(datasource) == []
assert (
'Error reading JSON data source output (err_desc :(, err_class foo_bar, err bug)'
in emails.get_latest('subject')
)
assert pub.loggederror_class.count() == 6
logged_error = pub.loggederror_class.select(order_by='id')[5]
assert logged_error.workflow_id is None
assert (
logged_error.summary
== "[DATASOURCE] Error reading JSON data source output (err_desc :(, err_class foo_bar, err bug)"
)
def test_geojson_datasource_bad_url_scheme(pub, error_email, emails):
datasource = {'type': 'geojson', 'value': ''}

View File

@ -179,7 +179,7 @@ def test_webservice_delete(http_requests, pub):
@pytest.mark.parametrize('notify_on_errors', [True, False])
@pytest.mark.parametrize('record_on_errors', [True, False])
def test_webservice_on_error_with_sql(http_requests, emails, notify_on_errors, record_on_errors):
def test_webservice_on_error(http_requests, emails, notify_on_errors, record_on_errors):
pub = create_temporary_pub()
pub.cfg['debug'] = {'error_email': 'errors@localhost.invalid'}
pub.write_cfg()
@ -209,26 +209,40 @@ def test_webservice_on_error_with_sql(http_requests, emails, notify_on_errors, r
assert emails.count() == 0
assert pub.loggederror_class.count() == 0
for url_part in ['400', '400-json', '404', '404-json', '500', 'json-err1', 'json-errheader1']:
for url_part in [
'400',
'400-json',
'404',
'404-json',
'500',
'json-err1',
'json-errheader1',
'json-errheaderstr',
]:
msg_mapping = {
'400': '400 Bad Request',
'400-json': '400 Bad Request (err_desc :(, err_class foo_bar)',
'404': '404 Not Found',
'404-json': '404 Not Found (err not-found)',
'500': '500 Internal Server Error',
'json-err1': '(err_desc :()',
'json-errheader1': '(err 1)',
'json-errheaderstr': '(err bug)',
}
wscall.request = {'url': 'http://remote.example.net/%s' % url_part}
wscall.store()
resp = get_app(pub).get('/foobar/')
assert 'Foo Bar ' in resp.text
if notify_on_errors:
assert emails.count() == 1
if url_part.startswith('400'):
assert '[ERROR] [WSCALL] 400 Bad Request' in emails.emails
elif url_part.startswith('404'):
assert '[ERROR] [WSCALL] 404 Not Found' in emails.emails
elif url_part.startswith('500'):
assert '[ERROR] [WSCALL] 500 Internal Server Error' in emails.emails
else:
assert '[ERROR] [WSCALL] 200 OK' in emails.emails
assert emails.get_latest('subject') == '[ERROR] [WSCALL] %s' % msg_mapping[url_part]
emails.empty()
else:
assert emails.count() == 0
if record_on_errors:
assert pub.loggederror_class.count() == 1
logged_error = pub.loggederror_class.select()[0]
assert logged_error.summary == '[WSCALL] %s' % msg_mapping[url_part]
pub.loggederror_class.wipe()
else:
assert pub.loggederror_class.count() == 0

View File

@ -343,12 +343,20 @@ class HttpRequestsMocking:
self.requests_mock.get('http://remote.example.net/204', status=204)
self.requests_mock.get('http://remote.example.net/400', status=400, body='bad request')
self.requests_mock.get(
'http://remote.example.net/400-json', status=400, json={"err": 1, "err_desc": ":("}
'http://remote.example.net/400-json',
status=400,
json={
'err': 1,
'err_desc': ':(',
'err_class': 'foo_bar',
},
)
self.requests_mock.get('http://remote.example.net/404', status=404, body='page not found')
self.requests_mock.get('http://remote.example.net/404-json', status=404, json={"err": 1})
self.requests_mock.get('http://remote.example.net/404-json', status=404, json={'err': 'not-found'})
self.requests_mock.get('http://remote.example.net/500', status=500, body='internal server error')
self.requests_mock.get('http://remote.example.net/json-err1', json={'data': '', 'err': 1})
self.requests_mock.get(
'http://remote.example.net/json-err1', json={'data': '', 'err': 1, 'err_desc': ':('}
)
self.requests_mock.get('http://remote.example.net/json', json={"foo": "bar"})
self.requests_mock.post('http://remote.example.net/json', json={"foo": "bar"})
self.requests_mock.delete('http://remote.example.net/json', json={"foo": "bar"})
@ -382,7 +390,24 @@ class HttpRequestsMocking:
self.requests_mock.get(
'http://remote.example.net/json-list-err1', json={"data": [{"id": "a", "text": "b"}], "err": 1}
)
self.requests_mock.get('http://remote.example.net/json-errstr', json={"data": "", "err": "bug"})
self.requests_mock.get(
'http://remote.example.net/json-list-err1bis',
json={
'data': [{'id': 'a', 'text': 'b'}],
'err': 1,
'err_desc': ':(',
},
)
self.requests_mock.get(
'http://remote.example.net/json-list-errstr',
json={
'data': [{'id': 'a', 'text': 'b'}],
'err': 'bug',
'err_desc': ':(',
'err_class': 'foo_bar',
},
)
self.requests_mock.get('http://remote.example.net/json-errstr', json={'data': '', 'err': 'bug'})
self.requests_mock.get(
'http://remote.example.net/json-errheader0', json={"foo": "bar"}, headers={'x-error-code': '0'}
)

View File

@ -1734,7 +1734,7 @@ def test_webservice_call(http_requests, pub):
with pytest.raises(AbortActionException):
item.perform(formdata)
assert formdata.workflow_data.get('xxx_status') == 404
assert formdata.workflow_data.get('xxx_error_response') == {'err': 1}
assert formdata.workflow_data.get('xxx_error_response') == {'err': 'not-found'}
assert formdata.workflow_data.get('xxx_time')
assert 'xxx_response' not in formdata.workflow_data
formdata.workflow_data = None

View File

@ -252,7 +252,13 @@ def get_json_from_url(url, data_source=None, log_message_part='JSON data source'
if not isinstance(entries, dict):
raise ValueError('not a json dict')
if entries.get('err') not in (None, 0, "0"):
raise ValueError('err %s' % entries['err'])
details = []
for key in ['err_desc', 'err_class']:
if entries.get(key):
details.append('%s %s' % (key, entries[key]))
if not details or entries['err'] not in [1, '1']:
details.append('err %s' % entries['err'])
raise ValueError(', '.join(details))
if geojson:
if not isinstance(entries.get('features'), list):
raise ValueError('bad geojson format')

View File

@ -173,11 +173,26 @@ def call_webservice(
return (None, None, None)
app_error_code = get_app_error_code(response, data, 'json')
try:
json_data = json_loads(data)
if not isinstance(json_data, dict):
json_data = {}
except (ValueError, TypeError):
json_data = {}
if (app_error_code != 0 or status >= 400) and (notify_on_errors or record_on_errors):
summary = '<no response>'
if response is not None:
summary = '%s %s' % (status, response.reason)
summary = '%s %s' % (status, response.reason) if status != 200 else ''
if app_error_code != 0:
details = []
for key in ['err_desc', 'err_class']:
if json_data.get(key):
details.append('%s %s' % (key, json_data[key]))
if not details or app_error_code not in [1, '1']:
details.append('err %s' % app_error_code)
details = '(%s)' % ', '.join(details)
summary = '%s %s' % (summary, details) if summary else details
get_publisher().record_error(
summary, context='[WSCALL]', notify=notify_on_errors, record=record_on_errors
)