Exemple #1
0
        def call_wrapper(service, parent, *args, **kwargs):
            """Wraps ServiceAction.__call__"""

            service_name = parent.meta.service_name
            operation_name = 'boto3:{}:{}'.format(
                service_name,
                xform_name(service._action_model.request.operation))
            span = utils.start_child_span(operation_name=operation_name,
                                          parent=get_current_span())

            span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
            span.set_tag(tags.COMPONENT, 'boto3')
            span.set_tag('boto3.service_name', service_name)

            with span:
                try:
                    response = _service_action_call(service, parent, *args,
                                                    **kwargs)
                except ClientError as error:
                    self.set_request_id_tag(span, error.response)
                    raise
                else:
                    if isinstance(response, dict):
                        self.set_request_id_tag(span, response)

            return response
        def produce_wrapper(producer, value, key=None, **kwargs):
            """Wraps Producer._produce"""

            parent_ctx = get_current_span()
            if parent_ctx:
                span = start_child_span(
                    operation_name='kafka:produce',
                    parent=parent_ctx,
                )

                span.set_tag(tags.MESSAGE_BUS_DESTINATION, producer.get_topic_name())
                if key is not None:
                    span.set_tag('key', str(key))

                headers = kwargs.pop('headers', {})
                try:
                    opentracing.tracer.inject(span_context=span.context,
                                              format=Format.TEXT_MAP,
                                              carrier=headers)
                except opentracing.UnsupportedFormatException:
                    pass

                with span:
                    try:
                        _Producer_produce(producer, value, key=key, headers=headers, **kwargs)
                    except Exception as error:
                        span.set_tag(tags.ERROR, True)
                        span.log_kv({
                            'event': tags.ERROR,
                            'error.object': error,
                        })
                        raise
            else:
                _Producer_produce(producer, value, key=key, **kwargs)
Exemple #3
0
    def before_client_send(target, context, method, kwargs, operation):
        """
        A hook to be executed before RPC request is sent from the client side.
        It returns a Span object that can be used as a context manager around
        the actual RPC call implementation, or in case of async callback,
        it needs its `finish()` method to be called explicitly.
        Also, loads the child span context to the service's context object.
        Expects context object to have span attribute.
        :param target: RPC target object
        :param context: context object
        :param method: RPM method name
        :param kwargs: RPM method kwargs
        :return: returns child tracing span encapsulating this request
        """
        # try to extract parent span, using request_context's get_current_span
        # for api service or rpc_context_span_extractor for other services.
        req_context_span = get_current_span()
        rpc_span = rpc_context_span_extractor(context)
        parent_span = req_context_span or rpc_span
        log.debug(
            "req_context_span: {}, rpc_span: {} ... Parent span: {}".format(
                req_context_span, rpc_span, parent_span))

        span = utils.start_child_span(operation_name=operation,
                                      parent=parent_span)

        # Set the needed tags for the span
        span.set_tag(ext_tags.SPAN_KIND, ext_tags.SPAN_KIND_RPC_CLIENT)
        span.set_tag('rpc_method', method)
        span.set_tag('kwargs', str(kwargs))

        request_id = context.request_id
        if request_id:
            span.set_tag('request.id', request_id)

        try:
            carrier = {}
            opentracing.tracer.inject(span_context=span.context,
                                      format=Format.TEXT_MAP,
                                      carrier=carrier)
            log.debug(
                "context object to be used for injecting {}".format(context))
            span_dict = dict()
            for key, value in six.iteritems(carrier):
                span_dict[key] = value
            context.span = span_dict
        except opentracing.UnsupportedFormatException:
            log.warn("Error injecting opentracing span to context")

        return span
Exemple #4
0
 def patched_run(*args, **kwargs):
     span = start_child_span(
         operation_name=operation,
         parent=parent_ctx,
     )
     with span, span_in_context(span):
         try:
             return run(*args, **kwargs)
         except Exception as error:
             span.set_tag(tags.ERROR, True)
             span.log_kv({
                 'event': tags.ERROR,
                 'error.object': error,
             })
             raise
Exemple #5
0
    def before_request(cmd, name):
        """
        A common method to record the memcache calls
        :param cmd: either 'get' or 'set'
        :param name: name of the key gettting or setting (Added as a tag)
        :return: the created span
        """
        operation_name = 'memcache:%s' % (cmd)
        span = utils.start_child_span(operation_name=operation_name,
                                      parent=get_current_span())
        span.set_tag(ext_tags.SPAN_KIND, ext_tags.SPAN_KIND_RPC_CLIENT)

        # TODO: What is the PEER_SERVICE ?
        span.set_tag(ext_tags.PEER_SERVICE, 'memcache')
        span.set_tag('memcache_key', name)
        return span
Exemple #6
0
 def group_join_wrapper(group, timeout=None, raise_error=False):
     parent_ctx = get_current_span()
     if parent_ctx:
         operation = 'gevent:{}:join'.format(group.__class__.__name__)
         tags_dict = {
             'greenlets': self._get_greenlet_names(group.greenlets),
             'timeout': timeout,
             'raise_error': raise_error,
         }
         span = start_child_span(
             operation_name=operation,
             parent=parent_ctx,
             tags=tags_dict,
         )
         with span:
             return _Group_join(group, timeout, raise_error)
     else:
         return _Group_join(group, timeout, raise_error)
Exemple #7
0
def before_http_request(request, current_span_extractor):
    """
    A hook to be executed before HTTP request is executed.
    It returns a Span object that can be used as a context manager around
    the actual HTTP call implementation, or in case of async callback,
    it needs its `finish()` method to be called explicitly.

    :param request: request must match API defined by AbstractRequestWrapper
    :param current_span_extractor: function that extracts current span
        from some context
    :return: returns child tracing span encapsulating this request
    """

    span = utils.start_child_span(operation_name=request.operation,
                                  parent=current_span_extractor())

    span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
    span.set_tag(tags.HTTP_URL, request.full_url)

    service_name = request.service_name
    host, port = request.host_port
    if service_name:
        span.set_tag(tags.PEER_SERVICE, service_name)
    if host:
        span.set_tag(tags.PEER_HOST_IPV4, host)
    if port:
        span.set_tag(tags.PEER_PORT, port)

    # fire interceptors
    for interceptor in ClientInterceptors.get_interceptors():
        interceptor.process(request=request, span=span)

    try:
        carrier = {}
        opentracing.tracer.inject(span_context=span.context,
                                  format=Format.HTTP_HEADERS,
                                  carrier=carrier)
        for key, value in six.iteritems(carrier):
            request.add_header(key, value)
    except opentracing.UnsupportedFormatException:
        pass

    return span
Exemple #8
0
 def joinall_wrapper(greenlets, timeout=None, raise_error=False, count=None):
     parent_ctx = get_current_span()
     if parent_ctx:
         operation = 'gevent:joinall'
         tags_dict = {
             'greenlets': self._get_greenlet_names(greenlets),
             'timeout': timeout,
             'raise_error': raise_error,
             'count': count,
         }
         span = start_child_span(
             operation_name=operation,
             parent=parent_ctx,
             tags=tags_dict,
         )
         with span:
             return _joinall(greenlets, timeout, raise_error, count)
     else:
         return _joinall(greenlets, timeout, raise_error, count)
Exemple #9
0
    def decorator(*args, **kwargs):
        parent_span = get_current_span()
        if parent_span is None and require_active_trace:
            return func(*args, **kwargs)

        span = utils.start_child_span(operation_name=operation_name,
                                      parent=parent_span)
        if callable(on_start):
            on_start(span, *args, **kwargs)

        with span, span_in_context(span):
            try:
                return func(*args, **kwargs)
            except Exception as error:
                span.set_tag(tags.ERROR, True)
                span.log_kv({
                    'event': tags.ERROR,
                    'error.object': error,
                })
                raise
Exemple #10
0
    def decorator(*args, **kwargs):
        parent_span = get_current_span()
        if parent_span is None and require_active_trace:
            return func(*args, **kwargs)

        span = utils.start_child_span(
            operation_name=operation_name, parent=parent_span)
        if callable(on_start):
            on_start(span, *args, **kwargs)

        with span, span_in_context(span):
            try:
                return func(*args, **kwargs)
            except Exception as error:
                span.set_tag(tags.ERROR, True)
                span.log_kv({
                    'event': tags.ERROR,
                    'error.object': error,
                })
                raise
def before_http_request(request, current_span_extractor):
    """
    A hook to be executed before HTTP request is executed.
    It returns a Span object that can be used as a context manager around
    the actual HTTP call implementation, or in case of async callback,
    it needs its `finish()` method to be called explicitly.

    :param request: request must match API defined by AbstractRequestWrapper
    :param current_span_extractor: function that extracts current span
        from some context
    :return: returns child tracing span encapsulating this request
    """

    span = utils.start_child_span(
        operation_name=request.operation,
        parent=current_span_extractor()
    )

    span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
    span.set_tag(tags.HTTP_URL, request.full_url)

    service_name = request.service_name
    host, port = request.host_port
    if service_name:
        span.set_tag(tags.PEER_SERVICE, service_name)
    if host:
        span.set_tag(tags.PEER_HOST_IPV4, host)
    if port:
        span.set_tag(tags.PEER_PORT, port)

    try:
        carrier = {}
        opentracing.tracer.inject(span_context=span.context,
                                  format=Format.HTTP_HEADERS,
                                  carrier=carrier)
        for key, value in carrier.iteritems():
            request.add_header(key, value)
    except opentracing.UnsupportedFormatException:
        pass

    return span
Exemple #12
0
    def perform_call(self, original_func, kind, service_name, operation_name,
                     *args, **kwargs):
        span = utils.start_child_span(operation_name='boto3:{}:{}:{}'.format(
            kind, service_name, operation_name),
                                      parent=get_current_span())

        span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
        span.set_tag(tags.COMPONENT, 'boto3')
        span.set_tag('boto3.service_name', service_name)

        with span, span_in_stack_context(span):
            try:
                response = original_func(*args, **kwargs)
            except ClientError as error:
                self.set_request_id_tag(span, error.response)
                raise
            else:
                if isinstance(response, dict):
                    self.set_request_id_tag(span, response)

        return response
        def produce_wrapper(producer, value, key=None, **kwargs):
            """Wraps Producer._produce"""

            parent_ctx = get_current_span()
            if parent_ctx:
                span = start_child_span(
                    operation_name='kafka:produce',
                    parent=parent_ctx,
                )

                span.set_tag(tags.MESSAGE_BUS_DESTINATION,
                             producer.get_topic_name())
                if key is not None:
                    span.set_tag('key', str(key))

                headers = kwargs.pop('headers', {})
                try:
                    opentracing.tracer.inject(span_context=span.context,
                                              format=Format.TEXT_MAP,
                                              carrier=headers)
                except opentracing.UnsupportedFormatException:
                    pass

                with span:
                    try:
                        _Producer_produce(producer,
                                          value,
                                          key=key,
                                          headers=headers,
                                          **kwargs)
                    except Exception as error:
                        span.set_tag(tags.ERROR, True)
                        span.log_kv({
                            'event': tags.ERROR,
                            'error.object': error,
                        })
                        raise
            else:
                _Producer_produce(producer, value, key=key, **kwargs)
Exemple #14
0
def func_span(func, tags=None, require_active_trace=True):
    """
    Creates a new local span for execution of the given `func`.
    The returned span is best used as a context manager, e.g.

    .. code-block:: python

        with func_span('my_function'):
            return my_function(...)

    At this time the func should be a string name. In the future this code
    can be enhanced to accept a real function and derive its qualified name.

    :param func: name of the function or method
    :param tags: optional tags to add to the child span
    :param require_active_trace: controls what to do when there is no active
        trace. If require_active_trace=True, then no span is created.
        If require_active_trace=False, a new trace is started.
    :return: new child span, or a dummy context manager if there is no
        active/current parent span
    """
    current_span = get_current_span()

    if current_span is None and require_active_trace:

        @contextlib.contextmanager
        def empty_ctx_mgr():
            yield None

        return empty_ctx_mgr()

    # TODO convert func to a proper name: module:class.func
    operation_name = str(func)
    span = utils.start_child_span(operation_name=operation_name,
                                  parent=current_span,
                                  tags=tags)
    with span_in_context(span):
        return span
Exemple #15
0
def func_span(func, tags=None, require_active_trace=True):
    """
    Creates a new local span for execution of the given `func`.
    The returned span is best used as a context manager, e.g.

    .. code-block:: python

        with func_span('my_function'):
            return my_function(...)

    At this time the func should be a string name. In the future this code
    can be enhanced to accept a real function and derive its qualified name.

    :param func: name of the function or method
    :param tags: optional tags to add to the child span
    :param require_active_trace: controls what to do when there is no active
        trace. If require_active_trace=True, then no span is created.
        If require_active_trace=False, a new trace is started.
    :return: new child span, or a dummy context manager if there is no
        active/current parent span
    """
    current_span = get_current_span()

    if current_span is None and require_active_trace:
        @contextlib.contextmanager
        def empty_ctx_mgr():
            yield None

        return empty_ctx_mgr()

    # TODO convert func to a proper name: module:class.func
    operation_name = str(func)
    span = utils.start_child_span(
        operation_name=operation_name, parent=current_span, tags=tags)
    with span_in_context(span):
        return span