def generic_rpc_response_handler(self, response_headers: dict, response_body, span: Span) -> Span: '''Add extended response rpc data to span''' logger.debug( 'Entering BaseInstrumentationWrapper.genericRpcResponseHandler().') try: # is the span currently recording? if not span.is_recording(): return span logger.debug('Span is Recording!') lowercased_headers = self.lowercase_headers(response_headers) # Log rpc metadata if requested? if self._process_response_headers: logger.debug('Dumping Response Headers:') self.add_headers_to_span(self.RPC_RESPONSE_METADATA_PREFIX, span, lowercased_headers) # Log rpc body if requested if self._process_response_body: response_body_str = str(response_body) logger.debug('Processing response body') response_body_str = self.grab_first_n_bytes(response_body_str) span.set_attribute(self.RPC_RESPONSE_BODY_PREFIX, response_body_str) except: # pylint: disable=W0702 logger.debug( 'An error occurred in genericResponseHandler: exception=%s, stacktrace=%s', sys.exc_info()[0], traceback.format_exc()) # Not rethrowing to avoid causing runtime errors finally: return span # pylint: disable=W0150
def _apply_response_attributes(span: Span, result): if result is None or not span.is_recording(): return metadata = result.get("ResponseMetadata") if metadata is None: return request_id = metadata.get("RequestId") if request_id is None: headers = metadata.get("HTTPHeaders") if headers is not None: request_id = (headers.get("x-amzn-RequestId") or headers.get("x-amz-request-id") or headers.get("x-amz-id-2")) if request_id: # TODO: update when semantic conventions exist span.set_attribute("aws.request_id", request_id) retry_attempts = metadata.get("RetryAttempts") if retry_attempts is not None: # TODO: update when semantic conventinos exists span.set_attribute("retry_attempts", retry_attempts) status_code = metadata.get("HTTPStatusCode") if status_code is not None: span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code)
def on_success(self, span: Span, result: _BotoResultT): if not span.is_recording(): return if self._op is None: return self._add_attributes(result, self._op.response_attributes, span.set_attribute)
def before_service_call(self, span: Span): if not span.is_recording() or self._op is None: return self._add_attributes( self._call_context.params, self._op.request_attributes, span.set_attribute, )
def use_span( span: Span, end_on_exit: bool = False, record_exception: bool = True, set_status_on_exception: bool = True, ) -> Iterator[Span]: """Takes a non-active span and activates it in the current context. Args: span: The span that should be activated in the current context. end_on_exit: Whether to end the span automatically when leaving the context manager scope. record_exception: Whether to record any exceptions raised within the context as error event on the span. set_status_on_exception: Only relevant if the returned span is used in a with/context manager. Defines wether the span status will be automatically set to ERROR when an uncaught exception is raised in the span with block. The span status won't be set by this mechanism if it was previously set manually. """ try: token = context_api.attach(context_api.set_value(_SPAN_KEY, span)) try: yield span finally: context_api.detach(token) except Exception as exc: # pylint: disable=broad-except if isinstance(span, Span) and span.is_recording(): # Record the exception as an event if record_exception: span.record_exception(exc) # Set status in case exception was raised if set_status_on_exception: span.set_status( Status( status_code=StatusCode.ERROR, description=f"{type(exc).__name__}: {exc}", ) ) raise finally: if end_on_exit: span.end()
def _generic_handler( self, record_headers: bool, header_prefix: str, # pylint:disable=R0913 record_body: bool, body_prefix: str, span: Span, headers: dict, body): logger.debug('Entering BaseInstrumentationWrapper.generic_handler().') try: # pylint: disable=R1702 if not span.is_recording(): return span logger.debug('Span is Recording!') lowercased_headers = self.lowercase_headers(headers) if record_headers: self.add_headers_to_span(header_prefix, span, lowercased_headers) if record_body: content_type = self.eligible_based_on_content_type( lowercased_headers) if content_type is False: return span body_str = None if isinstance(body, bytes): body_str = body.decode('UTF8', 'backslashreplace') else: body_str = body request_body_str = self.grab_first_n_bytes(body_str) span.set_attribute(body_prefix, request_body_str) except: # pylint: disable=W0702 logger.debug( 'An error occurred in genericRequestHandler: exception=%s, stacktrace=%s', sys.exc_info()[0], traceback.format_exc()) finally: return span # pylint: disable=W0150
def _apply_status_code(span: Span, status_code: int) -> None: if not span.is_recording(): return span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) span.set_status(Status(http_status_to_status_code(status_code)))