Skip to content

Commit

Permalink
PAPP-27340: Improve error logs
Browse files Browse the repository at this point in the history
  • Loading branch information
mmomin-crest committed Sep 6, 2022
2 parents 9b52b0a + 6a43c24 commit 7abc161
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 39 deletions.
1 change: 1 addition & 0 deletions release_notes/unreleased.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
**Unreleased**
* Improve error logging
18 changes: 13 additions & 5 deletions splunk.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"description": "This app integrates with Splunk to update data on the device, in addition to investigate and ingestion actions",
"publisher": "Splunk",
"contributors": [
{
"name": "Jeff Berry"
},
{
"name": "Mayur Pipaliya"
},
Expand Down Expand Up @@ -400,24 +403,29 @@
"parameters": {
"container_id": {
"description": "Parameter ignored in this app",
"data_type": "numeric"
"data_type": "numeric",
"order": 0
},
"start_time": {
"description": "Parameter ignored in this app",
"data_type": "numeric"
"data_type": "numeric",
"order": 1
},
"end_time": {
"description": "Parameter ignored in this app",
"data_type": "numeric"
"data_type": "numeric",
"order": 2
},
"container_count": {
"description": "Maximum number of events to query for",
"data_type": "numeric",
"default": 100
"default": 100,
"order": 3
},
"artifact_count": {
"description": "Parameter ignored in this app",
"data_type": "numeric"
"data_type": "numeric",
"order": 4
}
},
"output": [],
Expand Down
73 changes: 39 additions & 34 deletions splunk_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,23 @@ def _get_error_message_from_exception(self, e):
error_msg = e.args[1]
elif len(e.args) == 1:
error_msg = e.args[0]
else:
error_msg = consts.SPLUNK_ERR_MSG_UNAVAILABLE

if error_msg == consts.SPLUNK_ERR_MSG_UNAVAILABLE:
error_msg = str(e).strip().replace("'", '').replace("\"", '').replace("\n", '').replace("\r", '')
if len(error_msg) > 500:
error_msg = '{} - truncated'.format(error_msg[:500])
error_msg = '{} ({})'.format(error_msg, sys.exc_info()[-1].tb_lineno)
except Exception as e:
self.debug_print("Error occurred while fetching exception information. Details: {}".format(str(e)))
self._dump_error_log(e, "Error occurred while fetching exception information")

if not error_code:
error_text = "Error Message: {}".format(error_msg)
else:
error_text = "Error Code: {}. Error Message: {}".format(error_code, error_msg)
if not error_code:
error_msg = "Error Message: {}".format(error_msg)
else:
error_msg = "Error Code: {}. Error Message: {}".format(error_code, error_msg)

return error_text
return error_msg

def initialize(self):

Expand All @@ -118,7 +126,7 @@ def initialize(self):
return self.set_status(phantom.APP_ERROR, "Error occurred while getting the Phantom server's Python major version")

try:
self.splunk_server = self._handle_py_ver_compat_for_input_str(config[phantom.APP_JSON_DEVICE])
self.splunk_server = config[phantom.APP_JSON_DEVICE]
except Exception:
return phantom.APP_ERROR

Expand Down Expand Up @@ -205,6 +213,9 @@ def finalize(self):
self.save_state(self._state)
return phantom.APP_SUCCESS

def _dump_error_log(self, error, message="Exception occurred."):
self.error_print(message, dump_object=error)

def request(self, url, message, **kwargs):
"""Splunk SDK Proxy handler"""
method = message['method'].lower()
Expand Down Expand Up @@ -287,13 +298,14 @@ def _connect(self, action_result):
self._service = splunk_client.connect(**kwargs_config_flags)
except splunk_binding.HTTPError as e:
error_text = self._get_error_message_from_exception(e)
self.debug_print("Error occurred while connecting to the Splunk server. Details: {}".format(error_text))
self._dump_error_log(e, "Error occurred while connecting to the Splunk server.")
if '405 Method Not Allowed' in error_text:
return action_result.set_status(phantom.APP_ERROR, "Error occurred while connecting to the Splunk server")
else:
return action_result.set_status(phantom.APP_ERROR,
"Error occurred while connecting to the Splunk server. Details: {}".format(error_text))
except Exception as e:
self._dump_error_log(e)
error_text = consts.SPLUNK_EXCEPTION_ERR_MESSAGE.format(msg=consts.SPLUNK_ERR_CONNECTION_FAILED,
error_text=self._get_error_message_from_exception(e))
return action_result.set_status(phantom.APP_ERROR, error_text)
Expand All @@ -318,21 +330,6 @@ def _validate_integer(self, action_result, parameter, key, allow_zero=False):

return phantom.APP_SUCCESS, parameter

def _handle_py_ver_compat_for_input_str(self, input_str, always_encode=False):
"""
This method returns the encoded|original string based on the Python version.
:param input_str: Input string to be processed
:return: input_str (Processed input string based on following logic 'input_str - Python 3; encoded input_str - Python 2')
"""

try:
if input_str and (self._python_version == 2 or always_encode):
input_str = UnicodeDammit(input_str).unicode_markup.encode('utf-8')
except Exception:
self.debug_print("Error occurred while handling python 2to3 compatibility for the input string")

return input_str

def _make_rest_call_retry(self, action_result, endpoint, data, params=None, method=requests.post):
if params is None:
params = {}
Expand Down Expand Up @@ -481,8 +478,9 @@ def _process_html_response(self, response, action_result):
split_lines = error_text.split('\n')
split_lines = [x.strip() for x in split_lines if x.strip()]
error_text = '\n'.join(split_lines)
except:
error_text = consts.SPLUNK_ERR_UNABLE_TO_PARSE_JSON_RESPONSE
except Exception as e:
error_msg = self._get_error_message_from_exception(e)
error_text = consts.SPLUNK_ERR_UNABLE_TO_PARSE_HTML_RESPONSE.format(error=error_msg)

if not error_text:
error_text = "Empty response and no information received"
Expand Down Expand Up @@ -677,7 +675,7 @@ def _post_data(self, param):
index = param.get(consts.SPLUNK_JSON_INDEX)
source = param.get(consts.SPLUNK_JSON_SOURCE, consts.SPLUNK_DEFAULT_SOURCE)
source_type = param.get(consts.SPLUNK_JSON_SOURCE_TYPE, consts.SPLUNK_DEFAULT_SOURCE_TYPE)
post_data = self._handle_py_ver_compat_for_input_str(param[consts.SPLUNK_JSON_DATA], always_encode=True)
post_data = param[consts.SPLUNK_JSON_DATA], always_encode=True

get_params = {'source': source, 'sourcetype': source_type}

Expand Down Expand Up @@ -950,11 +948,11 @@ def _on_poll(self, param):
for k, v in list(item.items()):
cef[consts.CIM_CEF_MAP.get(k, k)] = v

raw = self._handle_py_ver_compat_for_input_str(item.get("_raw", ""))
raw = item.get("_raw", "")
if raw:
index = self._handle_py_ver_compat_for_input_str(item.get("index", ""))
source = self._handle_py_ver_compat_for_input_str(item.get("source", ""))
sourcetype = self._handle_py_ver_compat_for_input_str(item.get("sourcetype", ""))
index = item.get("index", "")
source = item.get("source", "")
sourcetype = item.get("sourcetype", "")
input_str = "{}{}{}{}".format(raw, source, index, sourcetype)
else:
input_str = json.dumps(item)
Expand Down Expand Up @@ -1028,11 +1026,13 @@ def _get_event_start(self, start_time):
datetime_obj = dateutil_parse(start_time)
return datetime_obj.astimezone(pytz.utc).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
except ParserError as parse_err:
self._dump_error_log(e, "ParserError while parsing _time.")
error_text = consts.SPLUNK_EXCEPTION_ERR_MESSAGE.format(msg="ParserError while parsing _time",
error_text=self._get_error_message_from_exception(parse_err))
self.save_progress(error_text)
return None
except Exception as e:
self._dump_error_log(e, "Exception while parsing _time.")
error_text = consts.SPLUNK_EXCEPTION_ERR_MESSAGE.format(msg="Exception while parsing _time",
error_text=self._get_error_message_from_exception(e))
self.save_progress(error_text)
Expand Down Expand Up @@ -1119,7 +1119,8 @@ def _handle_run_query(self, param):
search_query = search_string
else:
search_query = '{0} {1}'.format(search_command.strip(), search_string.strip())
except Exception:
except Exception as e:
self._dump_error_log(e)
return action_result.set_status(phantom.APP_ERROR, "Error occurred while parsing the search query")

self.debug_print("search_query: {0}".format(search_query))
Expand Down Expand Up @@ -1235,15 +1236,15 @@ def _run_query(self, search_query, action_result, attach_result=False, kwargs_cr
self._service.parse(search_query, parse_only=parse_only)
break
except HTTPError as e:
self.debug_print('Failed to validate search query: Reason: %s' % e)
self._dump_error_log(e, 'Failed to validate search query.')
if (phantom.is_fail(self._connect(action_result))):
return action_result.get_status()
if attempt_count == RETRY_LIMIT - 1:
error_text = consts.SPLUNK_EXCEPTION_ERR_MESSAGE.format(msg=consts.SPLUNK_ERR_INVALID_QUERY,
error_text=self._get_error_message_from_exception(e))
return action_result.set_status(phantom.APP_ERROR, error_text, query=search_query)
except Exception as e:
self.debug_print('Failed to validate search query: Reason: %s' % e)
self._dump_error_log(e, 'Failed to validate search query.')
if (phantom.is_fail(self._connect(action_result))):
return action_result.get_status()
if attempt_count == RETRY_LIMIT - 1:
Expand All @@ -1265,9 +1266,10 @@ def _run_query(self, search_query, action_result, attach_result=False, kwargs_cr
for attempt_count in range(0, RETRY_LIMIT):
try:
job = self._service.jobs.create(search_query, **kwargs_create)
self.debug_print("Job ---> {}".format(job))
break
except Exception as e:
self.debug_print('Failed to create job: Reason: %s' % e)
self._dump_error_log(e, 'Failed to create job.')
if attempt_count == RETRY_LIMIT - 1:
error_text = consts.SPLUNK_EXCEPTION_ERR_MESSAGE.format(msg=consts.SPLUNK_ERR_UNABLE_TO_CREATE_JOB,
error_text=self._get_error_message_from_exception(e))
Expand Down Expand Up @@ -1310,6 +1312,7 @@ def _run_query(self, search_query, action_result, attach_result=False, kwargs_cr
try:
results = splunk_results.ResultsReader(job.results(count=kwargs_create.get('max_count', 0)))
except Exception as e:
self._dump_error_log(e)
error_text = consts.SPLUNK_EXCEPTION_ERR_MESSAGE.format(msg="Error retrieving results",
error_text=self._get_error_message_from_exception(e))
return action_result.set_status(phantom.APP_ERROR, error_text)
Expand Down Expand Up @@ -1350,6 +1353,7 @@ def add_json_result(self, action_result, data):
json.dump(data, f)

except Exception as e:
self._dump_error_log(e, "Error occurred while adding file to Vault.")
error_msg = self._get_error_message_from_exception(e)
msg = "Error occurred while adding file to Vault. Error Details: {}".format(error_msg)
self.debug_print(msg)
Expand All @@ -1363,6 +1367,7 @@ def add_json_result(self, action_result, data):
vault_ret = Vault.add_attachment(file_path, container_id, 'splunk_run_query_result.json', vault_attach_dict)

except Exception as e:
self._dump_error_log(e)
err = self._get_error_message_from_exception(e)
self.debug_print(phantom.APP_ERR_FILE_ADD_TO_VAULT.format(err))
return action_result.set_status(phantom.APP_ERROR, phantom.APP_ERR_FILE_ADD_TO_VAULT.format(err))
Expand Down
1 change: 1 addition & 0 deletions splunk_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"Resetting the state file with the default format. Please try again."
)
SPLUNK_ERR_UNABLE_TO_PARSE_JSON_RESPONSE = "Unable to parse response as JSON. {error}"
SPLUNK_ERR_UNABLE_TO_PARSE_HTML_RESPONSE = "Unable to parse HTML response. {error}"
SPLUNK_ERR_EMPTY_RESPONSE = "Status Code {code}. Empty response and no information in the header."

# Progress messages
Expand Down

0 comments on commit 7abc161

Please sign in to comment.