##// END OF EJS Templates
ini: added new key
ini: added new key

File last commit:

r112:998f0d14
r129:489ce37b
Show More
sentry.py
296 lines | 9.4 KiB | text/x-python | PythonLexer
# -*- coding: utf-8 -*-
# Copyright 2010 - 2017 RhodeCode GmbH and the AppEnlight project authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from datetime import timedelta
from appenlight.lib.enums import LogLevelPython, ParsedSentryEventType
EXCLUDED_LOG_VARS = [
'args', 'asctime', 'created', 'exc_info', 'exc_text', 'filename',
'funcName', 'levelname', 'levelno', 'lineno', 'message', 'module', 'msecs',
'msg', 'name', 'pathname', 'process', 'processName', 'relativeCreated',
'thread', 'threadName']
EXCLUDE_SENTRY_KEYS = [
'csp',
'culprit',
'event_id',
'exception',
'extra',
'level',
'logentry',
'logger',
'message',
'modules',
'platform',
'query',
'release',
'request',
'sentry.interfaces.Csp', 'sentry.interfaces.Exception',
'sentry.interfaces.Http', 'sentry.interfaces.Message',
'sentry.interfaces.Query',
'sentry.interfaces.Stacktrace',
'sentry.interfaces.Template', 'sentry.interfaces.User',
'sentry.interfaces.csp.Csp',
'sentry.interfaces.exception.Exception',
'sentry.interfaces.http.Http',
'sentry.interfaces.message.Message',
'sentry.interfaces.query.Query',
'sentry.interfaces.stacktrace.Stacktrace',
'sentry.interfaces.template.Template',
'sentry.interfaces.user.User', 'server_name',
'stacktrace',
'tags',
'template',
'time_spent',
'timestamp',
'user']
def get_keys(list_of_keys, json_body):
for k in list_of_keys:
if k in json_body:
return json_body[k]
def get_logentry(json_body):
key_names = ['logentry',
'sentry.interfaces.message.Message',
'sentry.interfaces.Message'
]
logentry = get_keys(key_names, json_body)
return logentry
def get_exception(json_body):
parsed_exception = {}
key_names = ['exception',
'sentry.interfaces.exception.Exception',
'sentry.interfaces.Exception'
]
exception = get_keys(key_names, json_body) or {}
if exception:
if isinstance(exception, dict):
exception = exception['values'][0]
else:
exception = exception[0]
parsed_exception['type'] = exception.get('type')
parsed_exception['value'] = exception.get('value')
parsed_exception['module'] = exception.get('module')
parsed_stacktrace = get_stacktrace(exception) or {}
parsed_exception = exception or {}
return parsed_exception, parsed_stacktrace
def get_stacktrace(json_body):
parsed_stacktrace = []
key_names = ['stacktrace',
'sentry.interfaces.stacktrace.Stacktrace',
'sentry.interfaces.Stacktrace'
]
stacktrace = get_keys(key_names, json_body)
if stacktrace:
for frame in stacktrace['frames']:
parsed_stacktrace.append(
{"cline": frame.get('context_line', ''),
"file": frame.get('filename', ''),
"module": frame.get('module', ''),
"fn": frame.get('function', ''),
"line": frame.get('lineno', ''),
"vars": list(frame.get('vars', {}).items())
}
)
return parsed_stacktrace
def get_template(json_body):
parsed_template = {}
key_names = ['template',
'sentry.interfaces.template.Template',
'sentry.interfaces.Template'
]
template = get_keys(key_names, json_body)
if template:
for frame in template['frames']:
parsed_template.append(
{"cline": frame.get('context_line', ''),
"file": frame.get('filename', ''),
"fn": '',
"line": frame.get('lineno', ''),
"vars": []
}
)
return parsed_template
def get_request(json_body):
parsed_http = {}
key_names = ['request',
'sentry.interfaces.http.Http',
'sentry.interfaces.Http'
]
http = get_keys(key_names, json_body) or {}
for k, v in http.items():
if k == 'headers':
parsed_http['headers'] = {}
for sk, sv in http['headers'].items():
parsed_http['headers'][sk.title()] = sv
else:
parsed_http[k.lower()] = v
return parsed_http
def get_user(json_body):
parsed_user = {}
key_names = ['user',
'sentry.interfaces.user.User',
'sentry.interfaces.User'
]
user = get_keys(key_names, json_body)
if user:
parsed_user['id'] = user.get('id')
parsed_user['username'] = user.get('username')
parsed_user['email'] = user.get('email')
parsed_user['ip_address'] = user.get('ip_address')
return parsed_user
def get_query(json_body):
query = None
key_name = ['query',
'sentry.interfaces.query.Query',
'sentry.interfaces.Query'
]
query = get_keys(key_name, json_body)
return query
def parse_sentry_event(json_body):
request_id = json_body.get('event_id')
# required
message = json_body.get('message')
log_timestamp = json_body.get('timestamp')
level = json_body.get('level')
if isinstance(level, int):
level = LogLevelPython.key_from_value(level)
namespace = json_body.get('logger')
language = json_body.get('platform')
# optional
server_name = json_body.get('server_name')
culprit = json_body.get('culprit')
release = json_body.get('release')
tags = json_body.get('tags', {})
if hasattr(tags, 'items'):
tags = list(tags.items())
extra = json_body.get('extra', {})
if hasattr(extra, 'items'):
extra = list(extra.items())
parsed_req = get_request(json_body)
user = get_user(json_body)
template = get_template(json_body)
query = get_query(json_body)
# other unidentified keys found
other_keys = [(k, json_body[k]) for k in json_body.keys()
if k not in EXCLUDE_SENTRY_KEYS]
logentry = get_logentry(json_body)
if logentry:
message = logentry['message']
exception, stacktrace = get_exception(json_body)
alt_stacktrace = get_stacktrace(json_body)
event_type = None
if not exception and not stacktrace and not alt_stacktrace and not template:
event_type = ParsedSentryEventType.LOG
event_dict = {
'log_level': level,
'message': message,
'namespace': namespace,
'request_id': request_id,
'server': server_name,
'date': log_timestamp,
'tags': tags
}
event_dict['tags'].extend(
[(k, v) for k, v in extra if k not in EXCLUDED_LOG_VARS])
# other keys can be various object types
event_dict['tags'].extend([(k, v) for k, v in other_keys
if isinstance(v, str)])
if culprit:
event_dict['tags'].append(('sentry_culprit', culprit))
if language:
event_dict['tags'].append(('sentry_language', language))
if release:
event_dict['tags'].append(('sentry_release', release))
if exception or stacktrace or alt_stacktrace or template:
event_type = ParsedSentryEventType.ERROR_REPORT
event_dict = {
'client': 'sentry',
'error': message,
'namespace': namespace,
'request_id': request_id,
'server': server_name,
'start_time': log_timestamp,
'end_time': None,
'tags': tags,
'extra': extra,
'language': language,
'view_name': json_body.get('culprit'),
'http_status': None,
'username': None,
'url': parsed_req.get('url'),
'ip': None,
'user_agent': None,
'request': None,
'slow_calls': None,
'request_stats': None,
'traceback': None
}
event_dict['extra'].extend(other_keys)
if release:
event_dict['tags'].append(('sentry_release', release))
event_dict['request'] = parsed_req
if 'headers' in parsed_req:
event_dict['user_agent'] = parsed_req['headers'].get('User-Agent')
if 'env' in parsed_req:
event_dict['ip'] = parsed_req['env'].get('REMOTE_ADDR')
ts_ms = int(json_body.get('time_spent') or 0)
if ts_ms > 0:
event_dict['end_time'] = event_dict['start_time'] + \
timedelta(milliseconds=ts_ms)
if stacktrace or alt_stacktrace or template:
event_dict['traceback'] = stacktrace or alt_stacktrace or template
for k in list(event_dict.keys()):
if event_dict[k] is None:
del event_dict[k]
if user:
event_dict['username'] = user['username'] or user['id'] \
or user['email']
return event_dict, event_type