def _report_exc_info(exc_info, request, extra_data, payload_data, level=None): """ Called by report_exc_info() wrapper """ # check if exception is marked ignored cls, exc, trace = exc_info if getattr(exc, '_rollbar_ignore', False) or _is_ignored(exc): return if not _check_config(): return data = _build_base_data(request) filtered_level = _filtered_level(exc) if filtered_level: data['level'] = filtered_level # explicitly override the level with provided level if level: data['level'] = level # walk the trace chain to collect cause and context exceptions trace_chain = _walk_trace_chain(cls, exc, trace) extra_trace_data = None if len(trace_chain) > 1: data['body'] = { 'trace_chain': trace_chain } if payload_data and payload_data['body'] and payload_data['body']['trace']: extra_trace_data = payload_data['body']['trace'] del payload_data['body']['trace'] else: data['body'] = { 'trace': trace_chain[0] } if extra_data: extra_data = extra_data if not isinstance(extra_data, dict): extra_data = {'value': extra_data} if extra_trace_data: extra_data = dict_merge(extra_data, extra_trace_data) data['custom'] = extra_data if extra_trace_data and not extra_data: data['custom'] = extra_trace_data _add_request_data(data, request) _add_person_data(data, request) _add_lambda_context_data(data) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, data.get('access_token')) return data['uuid']
def _report_message(message, level, request, extra_data, payload_data): """ Called by report_message() wrapper """ if not _check_config(): return data = _build_base_data(request, level=level) # message data['body'] = {'message': {'body': message}} if extra_data: extra_data = extra_data data['body']['message'].update(extra_data) _add_request_data(data, request) _add_person_data(data, request) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, data.get('access_token')) return data['uuid']
def _report_message(message, level, request, extra_data, payload_data): """ Called by report_message() wrapper """ if not _check_config(): return data = _build_base_data(request, level=level) # message data['body'] = { 'message': { 'body': message } } if extra_data: extra_data = extra_data data['body']['message'].update(extra_data) _add_request_data(data, request) _add_person_data(data, request) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, data.get('access_token')) return data['uuid']
def _add_lambda_context_data(data): """ Attempts to add information from the lambda context if it exists """ global _CURRENT_LAMBDA_CONTEXT context = _CURRENT_LAMBDA_CONTEXT if context is None: return try: lambda_data = { 'lambda': { 'remaining_time_in_millis': context.get_remaining_time_in_millis(), 'function_name': context.function_name, 'function_version': context.function_version, 'arn': context.invoked_function_arn, 'request_id': context.aws_request_id, } } if 'custom' in data: data['custom'] = dict_merge(data['custom'], lambda_data) else: data['custom'] = lambda_data except Exception as e: log.exception("Exception while adding lambda context data: %r", e) finally: _CURRENT_LAMBDA_CONTEXT = None
def test_dict_merge_dicts_second_wins(self): a = {'a': {'b': 42}} b = {'a': {'b': 99}} result = dict_merge(a, b) self.assertIn('a', result) self.assertIn('b', result['a']) self.assertEqual(99, result['a']['b'])
def _report_exc_info(exc_info, request, extra_data, payload_data, level=None): """ Called by report_exc_info() wrapper """ # check if exception is marked ignored cls, exc, trace = exc_info if getattr(exc, '_rollbar_ignore', False) or _is_ignored(exc): return if not _check_config(): return data = _build_base_data(request) filtered_level = _filtered_level(exc) if filtered_level: data['level'] = filtered_level # explicitly override the level with provided level if level: data['level'] = level # exception info # most recent call last raw_frames = traceback.extract_tb(trace) frames = [{'filename': f[0], 'lineno': f[1], 'method': f[2], 'code': f[3]} for f in raw_frames] data['body'] = { 'trace': { 'frames': frames, 'exception': { 'class': cls.__name__, 'message': text(exc), } } } if extra_data: extra_data = extra_data if isinstance(extra_data, dict): data['custom'] = extra_data else: data['custom'] = {'value': extra_data} _add_locals_data(data, exc_info) _add_request_data(data, request) _add_person_data(data, request) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, data.get('access_token')) return data['uuid']
def test_dict_merge_dicts_independent(self): a = {'a': {'b': 42}} b = {'x': {'y': 99}} result = dict_merge(a, b) self.assertIn('a', result) self.assertIn('b', result['a']) self.assertEqual(42, result['a']['b']) self.assertIn('x', result) self.assertIn('y', result['x']) self.assertEqual(99, result['x']['y'])
def test_dict_merge_dicts_select_poll(self): import select poll = getattr(select, 'poll', None) if poll is None: return p = poll() a = {'a': {'b': 42}} b = {'a': {'y': p}} result = dict_merge(a, b) self.assertIn('a', result) self.assertIn('b', result['a']) self.assertEqual(42, result['a']['b']) self.assertIn('y', result['a']) self.assertRegex(result['a']['y'], r'Uncopyable obj')
def test_dict_merge_dicts_select_poll(self): import select poll = getattr(select, 'poll', None) if poll is None: return p = poll() a = {'a': {'b': 42}} b = {'a': {'y': p}} result = dict_merge(a, b, silence_errors=True) self.assertIn('a', result) self.assertIn('b', result['a']) self.assertEqual(42, result['a']['b']) self.assertIn('y', result['a']) self.assertRegex(result['a']['y'], r'Uncopyable obj')
def _report_message(message, level, request, extra_data, payload_data): """ Called by report_message() wrapper """ if not _check_config(): return filtered_message = events.on_message(message, request=request, extra_data=extra_data, payload_data=payload_data, level=level) if filtered_message is False: return data = _build_base_data(request, level=level) # message data['body'] = { 'message': { 'body': filtered_message } } if extra_data: extra_data = extra_data data['body']['message'].update(extra_data) request = _get_actual_request(request) _add_request_data(data, request) _add_person_data(data, request) _add_lambda_context_data(data) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, data.get('access_token')) return data['uuid']
def _report_message(message, level, request, extra_data, payload_data): """ Called by report_message() wrapper """ if not _check_config(): return filtered_message = events.on_message(message, request=request, extra_data=extra_data, payload_data=payload_data, level=level) if filtered_message is False: return data = _build_base_data(request, level=level) # message data['body'] = { 'message': { 'body': filtered_message } } if extra_data: extra_data = extra_data data['body']['message'].update(extra_data) request = _get_actual_request(request) _add_request_data(data, request) _add_person_data(data, request) _add_lambda_context_data(data) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, payload.get('access_token')) return data['uuid']
def __init__(self, access_token, environment=None, **kw): """ Creates a standalone Rollbar instance. Allows for more flexibility in multiple tools reporting to rollbar in the same runtime. access_token: project access token. Get this from the Rollbar UI: - click "Settings" in the top nav - click "Projects" in the left nav - copy-paste the appropriate token. environment: environment name. Can be any string; suggestions: 'production', 'development', 'staging', 'yourname' **kw: provided keyword arguments will override keys in SETTINGS. """ # We will perform these transforms in order: # 1. Serialize the payload to be all python built-in objects # 2. Scrub the payloads based on the key suffixes in SETTINGS['scrub_fields'] # 3. Scrub URLs in the payload for keys that end with 'url' # 4. Optional - If local variable gathering is enabled, transform the # trace frame values using the ShortReprTransform. self._serialize_transform = SerializableTransform(safe_repr=self.settings['locals']['safe_repr'], whitelist_types=self.settings['locals']['whitelisted_types']) self.settings = copy.deepcopy(self.settings) self._update_transforms() self.settings['access_token'] = access_token if not environment: # Allow settings via environment variable environment = os.environ.get('ROLLBAR_ENV', 'production') self.settings['environment'] = environment # Merge the extra config settings into self.settings self.settings = dict_merge(self.settings, kw) # TODO - (bchapman) if self.settings.get('allow_logging_basic_config'): logging.basicConfig() if self.settings.get('handler') == 'agent': self.agent_log = self._create_agent_log()
def _report_exc_info(exc_info, request, extra_data, payload_data, level=None): """ Called by report_exc_info() wrapper """ if not _check_config(): return filtered_level = _filtered_level(exc_info[1]) if level is None: level = filtered_level filtered_exc_info = events.on_exception_info(exc_info, request=request, extra_data=extra_data, payload_data=payload_data, level=level) if filtered_exc_info is False: return cls, exc, trace = filtered_exc_info data = _build_base_data(request) if level is not None: data['level'] = level # walk the trace chain to collect cause and context exceptions trace_chain = _walk_trace_chain(cls, exc, trace) extra_trace_data = None if len(trace_chain) > 1: data['body'] = { 'trace_chain': trace_chain } if payload_data and ('body' in payload_data) and ('trace' in payload_data['body']): extra_trace_data = payload_data['body']['trace'] del payload_data['body']['trace'] else: data['body'] = { 'trace': trace_chain[0] } if extra_data: extra_data = extra_data if not isinstance(extra_data, dict): extra_data = {'value': extra_data} if extra_trace_data: extra_data = dict_merge(extra_data, extra_trace_data) data['custom'] = extra_data if extra_trace_data and not extra_data: data['custom'] = extra_trace_data request = _get_actual_request(request) _add_request_data(data, request) _add_person_data(data, request) _add_lambda_context_data(data) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, payload.get('access_token')) return data['uuid']
def _report_exc_info(exc_info, request, extra_data, payload_data, level=None): """ Called by report_exc_info() wrapper """ if not _check_config(): return filtered_level = _filtered_level(exc_info[1]) if level is None: level = filtered_level filtered_exc_info = events.on_exception_info(exc_info, request=request, extra_data=extra_data, payload_data=payload_data, level=level) if filtered_exc_info is False: return cls, exc, trace = filtered_exc_info data = _build_base_data(request) if level is not None: data['level'] = level # walk the trace chain to collect cause and context exceptions trace_chain = _walk_trace_chain(cls, exc, trace) extra_trace_data = None if len(trace_chain) > 1: data['body'] = { 'trace_chain': trace_chain } if payload_data and ('body' in payload_data) and ('trace' in payload_data['body']): extra_trace_data = payload_data['body']['trace'] del payload_data['body']['trace'] else: data['body'] = { 'trace': trace_chain[0] } if extra_data: extra_data = extra_data if not isinstance(extra_data, dict): extra_data = {'value': extra_data} if extra_trace_data: extra_data = dict_merge(extra_data, extra_trace_data) data['custom'] = extra_data if extra_trace_data and not extra_data: data['custom'] = extra_trace_data _add_request_data(data, request) _add_person_data(data, request) _add_lambda_context_data(data) data['server'] = _build_server_data() if payload_data: data = dict_merge(data, payload_data) payload = _build_payload(data) send_payload(payload, data.get('access_token')) return data['uuid']
def init(access_token, environment='production', **kw): """ Saves configuration variables in this module's SETTINGS. access_token: project access token. Get this from the Rollbar UI: - click "Settings" in the top nav - click "Projects" in the left nav - copy-paste the appropriate token. environment: environment name. Can be any string; suggestions: 'production', 'development', 'staging', 'yourname' **kw: provided keyword arguments will override keys in SETTINGS. """ global SETTINGS, agent_log, _initialized, _transforms, _serialize_transform, _threads # Merge the extra config settings into SETTINGS SETTINGS = dict_merge(SETTINGS, kw) if _initialized: # NOTE: Temp solution to not being able to re-init. # New versions of pyrollbar will support re-initialization # via the (not-yet-implemented) configure() method. if not SETTINGS.get('suppress_reinit_warning'): log.warning('Rollbar already initialized. Ignoring re-init.') return SETTINGS['access_token'] = access_token SETTINGS['environment'] = environment if SETTINGS.get('allow_logging_basic_config'): logging.basicConfig() if SETTINGS.get('handler') == 'agent': agent_log = _create_agent_log() # We will perform these transforms in order: # 1. Serialize the payload to be all python built-in objects # 2. Scrub the payloads based on the key suffixes in SETTINGS['scrub_fields'] # 3. Scrub URLs in the payload for keys that end with 'url' # 4. Optional - If local variable gathering is enabled, transform the # trace frame values using the ShortReprTransform. _serialize_transform = SerializableTransform(safe_repr=SETTINGS['locals']['safe_repr'], whitelist_types=SETTINGS['locals']['whitelisted_types']) _transforms = [ ScrubRedactTransform(), _serialize_transform, ScrubTransform(suffixes=[(field,) for field in SETTINGS['scrub_fields']], redact_char='*'), ScrubUrlTransform(suffixes=[(field,) for field in SETTINGS['url_fields']], params_to_scrub=SETTINGS['scrub_fields']) ] # A list of key prefixes to apply our shortener transform to. The request # being included in the body key is old behavior and is being retained for # backwards compatibility. shortener_keys = [ ('request', 'POST'), ('request', 'json'), ('body', 'request', 'POST'), ('body', 'request', 'json'), ] if SETTINGS['locals']['enabled']: shortener_keys.append(('body', 'trace', 'frames', '*', 'code')) shortener_keys.append(('body', 'trace', 'frames', '*', 'args', '*')) shortener_keys.append(('body', 'trace', 'frames', '*', 'kwargs', '*')) shortener_keys.append(('body', 'trace', 'frames', '*', 'locals', '*')) shortener_keys.extend(SETTINGS['shortener_keys']) shortener = ShortenerTransform(safe_repr=SETTINGS['locals']['safe_repr'], keys=shortener_keys, **SETTINGS['locals']['sizes']) _transforms.append(shortener) _threads = queue.Queue() events.reset() filters.add_builtin_filters(SETTINGS) _initialized = True
def test_dict_merge_not_dict(self): a = {'a': {'b': 42}} b = 99 result = dict_merge(a, b) self.assertEqual(99, result)
def init(access_token, environment='production', **kw): """ Saves configuration variables in this module's SETTINGS. access_token: project access token. Get this from the Rollbar UI: - click "Settings" in the top nav - click "Projects" in the left nav - copy-paste the appropriate token. environment: environment name. Can be any string; suggestions: 'production', 'development', 'staging', 'yourname' **kw: provided keyword arguments will override keys in SETTINGS. """ global SETTINGS, agent_log, _initialized, _transforms, _serialize_transform if _initialized: # NOTE: Temp solution to not being able to re-init. # New versions of pyrollbar will support re-initialization # via the (not-yet-implemented) configure() method. log.warn('Rollbar already initialized. Ignoring re-init.') return SETTINGS['access_token'] = access_token SETTINGS['environment'] = environment # Merge the extra config settings into SETTINGS SETTINGS = dict_merge(SETTINGS, kw) if SETTINGS.get('allow_logging_basic_config'): logging.basicConfig() if SETTINGS.get('handler') == 'agent': agent_log = _create_agent_log() # We will perform these transforms in order: # 1. Serialize the payload to be all python built-in objects # 2. Scrub the payloads based on the key suffixes in SETTINGS['scrub_fields'] # 3. Scrub URLs in the payload for keys that end with 'url' # 4. Optional - If local variable gathering is enabled, transform the # trace frame values using the ShortReprTransform. _serialize_transform = SerializableTransform(safe_repr=SETTINGS['locals']['safe_repr'], whitelist_types=SETTINGS['locals']['whitelisted_types']) _transforms = [ ScrubRedactTransform(), _serialize_transform, ScrubTransform(suffixes=[(field,) for field in SETTINGS['scrub_fields']], redact_char='*'), ScrubUrlTransform(suffixes=[(field,) for field in SETTINGS['url_fields']], params_to_scrub=SETTINGS['scrub_fields']) ] # A list of key prefixes to apply our shortener transform to shortener_keys = [ ('body', 'request', 'POST'), ('body', 'request', 'json'), ] if SETTINGS['locals']['enabled']: shortener_keys.append(('body', 'trace', 'frames', '*', 'code')) shortener_keys.append(('body', 'trace', 'frames', '*', 'args', '*')) shortener_keys.append(('body', 'trace', 'frames', '*', 'kwargs', '*')) shortener_keys.append(('body', 'trace', 'frames', '*', 'locals', '*')) shortener = ShortenerTransform(safe_repr=SETTINGS['locals']['safe_repr'], keys=shortener_keys, **SETTINGS['locals']['sizes']) _transforms.append(shortener) _initialized = True