def wrapper(*args, **kwargs): @meiga def run_command(*args, **kwargs) -> Result: return func(*args, **kwargs) event = kwargs.get("event") if not event or not issubclass(event.__class__, Event): raise TypeError( "@command_handler only decorates function with at least one event as input" ) log_message = LogMessage( layer="command", operation=f"{func.__name__}", correlation_id=event.correlation_id, ) try: log_message.message = f"Event received: {event}" self.logger.log(INFO, log_message.to_json()) result = run_command(*args, **kwargs) if result.is_success: log_message.message = f"{result}" self.logger.log(INFO, log_message.to_json()) else: log_message.message = f"{result}" self.logger.log(ERROR, log_message.to_json()) return result except Exception as e: log_message.message = f"Error {func.__name__}: {repr(e.__class__)} {e} | {traceback.format_exc()}" self.logger.log(ERROR, log_message.to_json()) return isFailure
def _log_filter_by_routing_key(self, log_message: LogMessage): self.logger.log( WARNING, log_message.set_message( f"Message rejected (filtering by routing_key {self.filter_routing_key})" ), )
def _log_nack_simulation(self, log_message: LogMessage): self.logger.log( WARNING, log_message.set_message( f"Message rejected (Simulation rejecting {self.percentage_simulate_nack * 100}% of the messages)" ), )
def get_controller( operation: str = None, info_id: InfoId = None, message: str = None ) -> LogMessage: return LogMessage( layer="controller", operation=operation, info_id=info_id, data={"message": message}, )
def get_use_case( operation: str = None, correlation_id: str = None, message: Any = None ) -> LogMessage: return LogMessage( layer="use_case", operation=operation, correlation_id=correlation_id, message=message, )
def get_controller( operation: str = None, correlation_id: str = None, message: str = None ) -> LogMessage: return LogMessage( layer="controller", operation=operation, correlation_id=correlation_id, message=message, )
def get_use_case( operation: str = None, info_id: InfoId = None, message: Any = None ) -> LogMessage: return LogMessage( layer="use_case", operation=operation, info_id=info_id, data={"message": message}, )
def execute(self, *args, **kwargs): info_id = kwargs.get("info_id") log_message = LogMessage(layer="use_case", operation=f"{cls.__name__}", info_id=info_id) self.logger.log(DEBUG, log_message.set_message(f"Running Use Case")) if self.logging_parameters_whitelist: loggable_kwargs = {} for key, value in kwargs.items(): if key not in self.logging_parameters_whitelist: continue if getattr(value, "to_json", None): loggable_kwargs[key] = value.to_json() else: loggable_kwargs[key] = value if loggable_kwargs: self.logger.log( DEBUG, log_message.set_message(loggable_kwargs)) try: result = self._run_execute(*args, **kwargs) except Exception as exception: result = Failure( UnknownError( exception=exception, input_parameters=kwargs if len(kwargs) > 0 else args, executor=f"{cls.__name__} (Use Case)", traceback=traceback.format_exc(), filter_parameters=["headers"], )) if not isinstance(result, Result): return result detail = getattr(result.value, "message", None) if detail: detail = f"-> {detail}" else: detail = "" if result.is_failure: self.logger.log( ERROR, log_message.set_message(f"{result} {detail}")) self.notify(result, info_id) else: if not self._is_logging_type(result.value): message = ( f"Success result of type: {type(result.value).__name__}" ) else: message = f"{result.value}" self.logger.log(DEBUG, log_message.set_message(message)) return result
def wrapper(*args, **kwargs): @meiga def run_event_handler(*args, **kwargs) -> Result: return func(*args, **kwargs) self._check_logger() self._check_notifier() event: Event = args[0] log_message = LogMessage(layer="event_handler", operation=f"{func.__name__}") self.logger.log( DEBUG, log_message.set_message({ "event": event.event_name, "body": event.to_json() }), ) try: result = run_event_handler(*args, **kwargs) except Exception as exception: result = Failure( CriticalError( exception=exception, input_parameters=kwargs if len(kwargs) > 0 else args, executor=f"{func.__name__} (Event Handler)", traceback=traceback.format_exc(), )) self.logger.log(DEBUG, log_message.set_message({"result": result})) self.notify(result) return result
def handle_failure( self, log_message: LogMessage, result: Result ) -> Tuple[dict, int]: self.logger.log(ERROR, log_message.set_message(f"{result}")) known_result_failure_handler = KnownResultFailureHandler(result) http_response = DEFAULT_ERROR_MESSAGE if not known_result_failure_handler.is_a_result_known_error: if self.error_handler: http_error = self.error_handler(result) if not issubclass(http_error.__class__, HttpError): raise TypeError( "Returned object from error_handler must be subclasses of HttpError" ) http_response = http_error.handle() else: http_response = known_result_failure_handler.http_error.handle() return http_response
def log(self, logging_level, log_message: LogMessage): message = log_message.to_dict() if logging_level == INFO: message["meta"]["level"] = "info" self.logger.info(message) elif logging_level == DEBUG: message["meta"]["level"] = "debug" self.logger.debug(message) elif logging_level == CRITICAL: message["meta"]["level"] = "critical" self.logger.critical(message) elif logging_level == FATAL: message["meta"]["level"] = "fatal" self.logger.fatal(message) elif logging_level == ERROR: message["meta"]["level"] = "error" self.logger.error(message) elif logging_level == WARN: message["meta"]["level"] = "warning" self.logger.warn(message) elif logging_level == WARNING: message["meta"]["level"] = "warning" self.logger.warning(message)
def execute(self, *args, **kwargs): correlation_id = kwargs.get("correlation_id") log_message = LogMessage( layer="use_case", operation=f"{cls.__name__}", correlation_id=correlation_id, ) log_message.message = f"Start" self.logger.log(INFO, log_message.to_json()) if self.logging_parameters_whitelist: loggable_kwargs = [ (k, v) for k, v in kwargs.items() if k in self.logging_parameters_whitelist ] if loggable_kwargs: log_message.message = dict(loggable_kwargs) self.logger.log(INFO, log_message.to_json()) result = self._run_execute(*args, **kwargs) if not isinstance(result, Result): return result detail = getattr(result.value, "message", None) if detail: detail = f"-> {detail}" else: detail = "" if result.is_failure: log_message.message = f"{result} {detail}" self.logger.log(ERROR, log_message.to_json()) else: if not self._is_logging_type(result.value): log_message.message = ( f"Object of type: {type(result.value).__name__}" ) else: log_message.message = f"{result.value}" self.logger.log(INFO, log_message.to_json()) return result
def wrapper(*args, **kwargs): @timer @meiga def run_controller(*args, **kwargs) -> Tuple[Result, float]: params = inspect.getfullargspec(func).args kwargs = {k: v for k, v in kwargs.items() if k in params} return func(*args, **kwargs) self._configure_petisco_dependencies() info_id = None is_success = False elapsed_time = None try: kwargs = add_petisco(kwargs) kwargs = add_headers(kwargs) result_kwargs = add_info_id(kwargs) self.notify(result_kwargs, info_id) log_message = LogMessage( layer="controller", operation=f"{func.__name__}" ) if result_kwargs.is_failure: http_response = self.handle_failure(log_message, result_kwargs) else: kwargs, info_id = result_kwargs.value log_message.info_id = info_id self.logger.log( DEBUG, log_message.set_message("Processing Request") ) result_controller, elapsed_time = run_controller(*args, **kwargs) self.notify(result_controller, info_id) if result_controller.is_failure: http_response = self.handle_failure( log_message, result_controller ) else: message = self._get_success_message(result_controller) self.logger.log(DEBUG, log_message.set_message(message)) http_response = ( self.success_handler(result_controller) if self.success_handler else DEFAULT_SUCCESS_MESSAGE ) is_success = True except Exception as e: log_message = LogMessage( layer="controller", operation=f"{func.__name__}" ) log_message.info_id = info_id if info_id else None message = f"Error {func.__name__}: {repr(e.__class__)} {e} | {traceback.format_exc()}" self.logger.log(ERROR, log_message.set_message(message)) http_response = InternalHttpError().handle() self.notifier.publish( NotifierExceptionMessage( exception=e, executor=func.__name__, traceback=traceback.format_exc(), info_id=info_id, info_petisco=Petisco.get_info(), ) ) if self.send_request_responded_event: request_responded = RequestResponded( app_name=self.app_name, app_version=self.app_version, controller=f"{func.__name__}", is_success=is_success, http_response=http_response, elapsed_time=elapsed_time, ).add_info_id(info_id) self.event_bus.publish(request_responded) return http_response
def get_subscriber(operation: str = None, message: str = None) -> LogMessage: return LogMessage( layer="subscriber", operation=operation, data={"message": message} )
def get_event_handler(operation: str = None, message: str = None) -> LogMessage: return LogMessage( layer="event_handler", operation=operation, data={"message": message} )
def _get_base_message(self, handler: Callable): return LogMessage(layer="rabbitmq_event_consumer", operation=f"{handler.__name__}")
def wrapper(*args, **kwargs): @meiga @jwt(jwt_config=self.jwt_config) def run_controller(*args, **kwargs) -> Result: return func(*args, **kwargs) correlation_id, kwargs = update_correlation_id(kwargs) log_message = LogMessage( layer="controller", operation=f"{func.__name__}", correlation_id=correlation_id, ) try: log_message.message = "Start" self.logger.log(INFO, log_message.to_json()) result = run_controller(*args, **kwargs) if result.is_success: if isinstance(result.value, tuple(self.logging_types_blacklist)): log_message.message = ( f"Success result of type: {type(result.value).__name__}" ) else: log_message.message = f"{result}" self.logger.log(INFO, log_message.to_json()) return (self.success_handler(result) if self.success_handler else DEFAULT_SUCCESS_MESSAGE) else: log_message.message = f"{result}" self.logger.log(ERROR, log_message.to_json()) known_result_failure_handler = KnownResultFailureHandler( result) if not known_result_failure_handler.is_a_result_known_error: if not self.error_handler: return DEFAULT_ERROR_MESSAGE http_error = self.error_handler(result) if not issubclass(http_error.__class__, HttpError): raise TypeError( "Returned object from error_handler must be subclasses of HttpError" ) return http_error.handle() else: return known_result_failure_handler.http_error.handle() except Exception as e: log_message.message = f"Error {func.__name__}: {repr(e.__class__)} {e} | {traceback.format_exc()}" self.logger.log(ERROR, log_message.to_json()) return InternalHttpError().handle()
def wrapper(*args, **kwargs): @meiga def run_subscriber(**kwargs) -> Result: params = inspect.getfullargspec(func).args kwargs = {k: v for k, v in kwargs.items() if k in params} return func(**kwargs) self._check_logger() self._check_notifier() ch, method, properties, body = args log_message = LogMessage(layer="subscriber", operation=f"{func.__name__}") self.logger.log( DEBUG, log_message.set_message( {"routing_key": method.routing_key, "body": json.loads(body)} ), ) if self._nack_simulation(): ch.basic_nack(delivery_tag=method.delivery_tag) self._log_nack_simulation(log_message) return if self._filter_by_routing_key(method.routing_key): ch.basic_nack(delivery_tag=method.delivery_tag) self._log_filter_by_routing_key(log_message) return try: event = Event.from_json(body) except TypeError: event = Event.from_deprecated_json(body) except: # noqa E722 self._log_invalid_event_format(log_message, body) return ch.basic_nack(delivery_tag=method.delivery_tag) kwargs = dict(event=event, routing_key=RoutingKey(method.routing_key)) try: result = run_subscriber(**kwargs) except Exception as exception: result = Failure( UnknownError( exception=exception, input_parameters=kwargs if len(kwargs) > 0 else args, executor=f"{func.__name__} (Subscriber)", traceback=traceback.format_exc(), ) ) if self.delay_after: time.sleep(self.delay_after) self.notify(result) if result is None or result.is_failure: message = f"{result}: {traceback.format_exc()}" self.logger.log(ERROR, log_message.set_message(message)) ch.basic_nack(delivery_tag=method.delivery_tag) else: ch.basic_ack(delivery_tag=method.delivery_tag)
def _log_invalid_event_format(self, log_message: LogMessage, body: Dict): self.logger.log( ERROR, log_message.set_message(f"Invalid event format: {body})") )