def _trace_before_publish(self, *args, **kwargs):
        task = utils.retrieve_task_from_sender(kwargs)
        task_id = utils.retrieve_task_id_from_message(kwargs)

        if task is None or task_id is None:
            return

        operation_name = "{0}/{1}".format(_TASK_APPLY_ASYNC, task.name)
        span = self._tracer.start_span(
            operation_name, kind=trace.SpanKind.PRODUCER
        )

        # apply some attributes here because most of the data is not available
        if span.is_recording():
            span.set_attribute(_TASK_TAG_KEY, _TASK_APPLY_ASYNC)
            span.set_attribute(_MESSAGE_ID_ATTRIBUTE_NAME, task_id)
            span.set_attribute(_TASK_NAME_KEY, task.name)
            utils.set_attributes_from_context(span, kwargs)

        activation = self._tracer.use_span(span, end_on_exit=True)
        activation.__enter__()
        utils.attach_span(task, task_id, (span, activation), is_publish=True)

        headers = kwargs.get("headers")
        if headers:
            propagators.inject(type(headers).__setitem__, headers)
Esempio n. 2
0
    async def on_request_start(
        unused_session: aiohttp.ClientSession,
        trace_config_ctx: types.SimpleNamespace,
        params: aiohttp.TraceRequestStartParams,
    ):
        http_method = params.method.upper()
        if trace_config_ctx.span_name is None:
            request_span_name = http_method
        elif callable(trace_config_ctx.span_name):
            request_span_name = str(trace_config_ctx.span_name(params))
        else:
            request_span_name = str(trace_config_ctx.span_name)

        trace_config_ctx.span = trace_config_ctx.tracer.start_span(
            request_span_name,
            kind=SpanKind.CLIENT,
            attributes={
                "component": "http",
                "http.method": http_method,
                "http.url": trace_config_ctx.url_filter(params.url)
                if callable(trace_config_ctx.url_filter)
                else str(params.url),
            },
        )

        trace_config_ctx.token = context_api.attach(
            trace.propagation.set_span_in_context(trace_config_ctx.span)
        )

        propagators.inject(
            tracer, type(params.headers).__setitem__, params.headers
        )
def fetch_async(tracer, func, _, args, kwargs):
    start_time = time_ns()

    # Return immediately if no args were provided (error)
    # or original_request is set (meaning we are in a redirect step).
    if len(args) == 0 or hasattr(args[0], "original_request"):
        return func(*args, **kwargs)

    # Force the creation of a HTTPRequest object if needed,
    # so we can inject the context into the headers.
    args, kwargs = _normalize_request(args, kwargs)
    request = args[0]

    span = tracer.start_span(
        request.method, kind=trace.SpanKind.CLIENT, start_time=start_time,
    )

    if span.is_recording():
        attributes = {
            "component": "tornado",
            "http.url": request.url,
            "http.method": request.method,
        }
        for key, value in attributes.items():
            span.set_attribute(key, value)

    with tracer.use_span(span):
        propagators.inject(type(request.headers).__setitem__, request.headers)
        future = func(*args, **kwargs)
        future.add_done_callback(
            functools.partial(_finish_tracing_callback, span=span)
        )
        return future
    def instrumented_request(self, method, url, *args, **kwargs):
        if context.get_value("suppress_instrumentation"):
            return wrapped(self, method, url, *args, **kwargs)

        # See
        # https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md#http-client
        try:
            parsed_url = urlparse(url)
        except ValueError as exc:  # Invalid URL
            path = "<Unparsable URL: {}>".format(exc)
        else:
            if parsed_url is None:
                path = "<URL parses to None>"
            path = parsed_url.path

        with tracer.start_as_current_span(path, kind=SpanKind.CLIENT) as span:
            span.set_attribute("component", "http")
            span.set_attribute("http.method", method.upper())
            span.set_attribute("http.url", url)

            # TODO: Propagate the trace context via headers once we have a way
            # to access propagators.

            headers = kwargs.setdefault("headers", {})
            propagators.inject(tracer, type(headers).__setitem__, headers)
            result = wrapped(self, method, url, *args, **kwargs)  # *** PROCEED

            span.set_attribute("http.status_code", result.status_code)
            span.set_attribute("http.status_text", result.reason)

            return result
    def test_propagation(self):
        traceparent_value = "00-{trace_id}-{span_id}-00".format(
            trace_id=format(self.TRACE_ID, "032x"),
            span_id=format(self.SPAN_ID, "016x"),
        )
        tracestate_value = "foo=1,bar=2,baz=3"
        headers = {
            "otcorrelationcontext": ["key1=val1,key2=val2"],
            "traceparent": [traceparent_value],
            "tracestate": [tracestate_value],
        }
        ctx = extract(get_as_list, headers)
        correlations = correlationcontext.get_correlations(context=ctx)
        expected = {"key1": "val1", "key2": "val2"}
        self.assertEqual(correlations, expected)
        span_context = get_span_from_context(context=ctx).get_context()

        self.assertEqual(span_context.trace_id, self.TRACE_ID)
        self.assertEqual(span_context.span_id, self.SPAN_ID)

        span = trace.DefaultSpan(span_context)
        ctx = correlationcontext.set_correlation("key3", "val3")
        ctx = correlationcontext.set_correlation("key4", "val4", context=ctx)
        ctx = set_span_in_context(span, context=ctx)
        output = {}
        inject(dict.__setitem__, output, context=ctx)
        self.assertEqual(traceparent_value, output["traceparent"])
        self.assertIn("key3=val3", output["otcorrelationcontext"])
        self.assertIn("key4=val4", output["otcorrelationcontext"])
        self.assertIn("foo=1", output["tracestate"])
        self.assertIn("bar=2", output["tracestate"])
        self.assertIn("baz=3", output["tracestate"])
    def _instrumented_requests_call(method: str, url: str, call_wrapped,
                                    get_or_create_headers):
        if context.get_value("suppress_instrumentation") or context.get_value(
                _SUPPRESS_REQUESTS_INSTRUMENTATION_KEY):
            return call_wrapped()

        # See
        # https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-client
        method = method.upper()
        span_name = ""
        if name_callback is not None:
            span_name = name_callback(method, url)
        if not span_name or not isinstance(span_name, str):
            span_name = get_default_span_name(method)

        labels = {}
        labels["http.method"] = method
        labels["http.url"] = url

        with get_tracer(__name__, __version__,
                        tracer_provider).start_as_current_span(
                            span_name, kind=SpanKind.CLIENT) as span:
            exception = None
            if span.is_recording():
                span.set_attribute("http.method", method)
                span.set_attribute("http.url", url)

            headers = get_or_create_headers()
            propagators.inject(type(headers).__setitem__, headers)

            token = context.attach(
                context.set_value(_SUPPRESS_REQUESTS_INSTRUMENTATION_KEY,
                                  True))
            try:
                result = call_wrapped()  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "response", None)
            finally:
                context.detach(token)

            if isinstance(result, Response):
                if span.is_recording():
                    span.set_attribute("http.status_code", result.status_code)
                    span.set_attribute("http.status_text", result.reason)
                    span.set_status(
                        Status(http_status_to_status_code(result.status_code)))
                labels["http.status_code"] = str(result.status_code)
                if result.raw and result.raw.version:
                    labels["http.flavor"] = (str(result.raw.version)[:1] +
                                             "." +
                                             str(result.raw.version)[:-1])
            if span_callback is not None:
                span_callback(span, result)

            if exception is not None:
                raise exception.with_traceback(exception.__traceback__)

        return result
Esempio n. 7
0
def _inject_span_context(metadata: MutableMapping[str, str]) -> None:
    # pylint:disable=unused-argument
    def append_metadata(carrier: MutableMapping[str, str], key: str,
                        value: str):
        metadata[key] = value

    # Inject current active span from the context
    propagators.inject(append_metadata, metadata)
Esempio n. 8
0
 def to_header(self):  # pylint: disable=no-self-use
     # type: () -> Dict[str, str]
     """
     Returns a dictionary with the header labels and values.
     :return: A key value pair dictionary
     """
     temp_headers = {}  # type: Dict[str, str]
     inject(_set_headers_from_http_request_headers, temp_headers)
     return temp_headers
    def _instrumented_requests_call(
        method: str, url: str, call_wrapped, get_or_create_headers
    ):
        if context.get_value("suppress_instrumentation") or context.get_value(
            _SUPPRESS_REQUESTS_INSTRUMENTATION_KEY
        ):
            return call_wrapped()

        # See
        # https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#http-client
        method = method.upper()
        span_name = "HTTP {}".format(method)

        exception = None

        with get_tracer(
            __name__, __version__, tracer_provider
        ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
            span.set_attribute("component", "http")
            span.set_attribute("http.method", method.upper())
            span.set_attribute("http.url", url)

            headers = get_or_create_headers()
            propagators.inject(type(headers).__setitem__, headers)

            token = context.attach(
                context.set_value(_SUPPRESS_REQUESTS_INSTRUMENTATION_KEY, True)
            )
            try:
                result = call_wrapped()  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "response", None)
            finally:
                context.detach(token)

            if exception is not None:
                span.set_status(
                    Status(_exception_to_canonical_code(exception))
                )
                span.record_exception(exception)

            if result is not None:
                span.set_attribute("http.status_code", result.status_code)
                span.set_attribute("http.status_text", result.reason)
                span.set_status(
                    Status(http_status_to_canonical_code(result.status_code))
                )

            if span_callback is not None:
                span_callback(span, result)

        if exception is not None:
            raise exception.with_traceback(exception.__traceback__)

        return result
Esempio n. 10
0
 def to_header(self):
     # type: () -> Dict[str, str]
     """
     Returns a dictionary with the header labels and values.
     :return: A key value pair dictionary
     """
     temp_headers = {}  # type: Dict[str, str]
     inject(self.get_current_tracer(),
            _set_headers_from_http_request_headers, temp_headers)
     return temp_headers
Esempio n. 11
0
def deploy_to_orch():
    with tracer.start_as_current_span('deploy-to-orch') as span:
        headers = {}
        inject(dict.__setitem__, headers)
        print(span)
        print(headers)
        requested = get(
            "http://localhost:8081/deploy",
            headers=headers,
        )
        span.set_attribute("http.route", "/orch/deploy")
Esempio n. 12
0
async def _send_request(event: SendRequest) -> None:
    tracer = get_tracer(__name__)
    span = tracer.start_span(
        event.method_name,
        kind=SpanKind.CLIENT,
        attributes={
            "component": "grpc",
            "grpc.method": event.method_name
        },
    )
    _client_span.set(span)
    inject(type(event.metadata).__setitem__, event.metadata)
Esempio n. 13
0
    def instrumented_request(self, method, url, *args, **kwargs):
        if context.get_value("suppress_instrumentation"):
            return wrapped(self, method, url, *args, **kwargs)

        # See
        # https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#http-client
        try:
            parsed_url = urlparse(url)
            span_name = parsed_url.path
        except ValueError as exc:  # Invalid URL
            span_name = "<Unparsable URL: {}>".format(exc)

        exception = None

        with get_tracer(
            __name__, __version__, tracer_provider
        ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
            span.set_attribute("component", "http")
            span.set_attribute("http.method", method.upper())
            span.set_attribute("http.url", url)

            headers = kwargs.get("headers", {}) or {}
            propagators.inject(type(headers).__setitem__, headers)
            kwargs["headers"] = headers

            try:
                result = wrapped(
                    self, method, url, *args, **kwargs
                )  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "response", None)

            if exception is not None:
                span.set_status(
                    Status(_exception_to_canonical_code(exception))
                )

            if result is not None:
                span.set_attribute("http.status_code", result.status_code)
                span.set_attribute("http.status_text", result.reason)
                span.set_status(
                    Status(http_status_to_canonical_code(result.status_code))
                )

            if span_callback is not None:
                span_callback(span, result)

        if exception is not None:
            raise exception.with_traceback(exception.__traceback__)

        return result
Esempio n. 14
0
 def inject(self, url):
     if self.type == "open_telemetry":
         headers = {}
         propagators.inject(type(headers).__setitem__, headers)
         return headers
     elif self.type == "jaeger":
         # https://github.com/yurishkuro/opentracing-tutorial/blob/7ae271badb867635f6697d9dbe5510c798883ff8/python/lesson03/solution/hello.py#L26
         headers = {}
         span = self.tracer.active_span
         span.set_tag(tags.HTTP_METHOD, "POST")
         span.set_tag(tags.HTTP_URL, url)
         span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
         self.tracer.inject(span, Format.HTTP_HEADERS, headers)
         # span_header = self.tracer.inject(span, Format.HTTP_HEADERS, headers)
         # tracer.inject(child_span.context, 'zipkin-span-format', text_carrier)
         return headers
Esempio n. 15
0
    async def on_request_start(
        unused_session: aiohttp.ClientSession,
        trace_config_ctx: types.SimpleNamespace,
        params: aiohttp.TraceRequestStartParams,
    ):
        if context_api.get_value("suppress_instrumentation"):
            trace_config_ctx.span = None
            return

        http_method = params.method.upper()
        if trace_config_ctx.span_name is None:
            request_span_name = "HTTP {}".format(http_method)
        elif callable(trace_config_ctx.span_name):
            request_span_name = str(trace_config_ctx.span_name(params))
        else:
            request_span_name = str(trace_config_ctx.span_name)

        trace_config_ctx.span = trace_config_ctx.tracer.start_span(
            request_span_name,
            kind=SpanKind.CLIENT,
        )

        if trace_config_ctx.span.is_recording():
            attributes = {
                "component":
                "http",
                "http.method":
                http_method,
                "http.url":
                trace_config_ctx.url_filter(params.url)
                if callable(trace_config_ctx.url_filter) else str(params.url),
            }
            for key, value in attributes.items():
                trace_config_ctx.span.set_attribute(key, value)

        trace_config_ctx.token = context_api.attach(
            trace.set_span_in_context(trace_config_ctx.span))

        propagators.inject(type(params.headers).__setitem__, params.headers)
    def produce(self, *args, **kwargs):
        tracer = trace.get_tracer(__name__)
        with tracer.start_as_current_span(
                "confluent_kafka.produce",
                kind=trace.SpanKind.PRODUCER) as span:
            a = list(args)
            k = kwargs.copy()

            argmap = dict(topic=0, value=1, key=2, partition=3, timestamp=5)
            for name, pos in argmap.items():
                if name in kwargs:
                    span.set_attribute("kafka.%s" % name, kwargs[name])
                elif len(args) > pos:
                    span.set_attribute("kafka.%s" % name, args[pos])

            if "headers" in kwargs:
                headers = k["headers"] = kwargs["headers"].copy()
            elif len(args) > 7:
                headers = a[7] = args[7].copy()
            else:
                headers = k["headers"] = {}

            propagators.inject(type(headers).__setitem__, headers)
            return self._self_instance.produce(*a, **k)
def _patched_endpoint_prepare_request(wrapped, instance, args, kwargs):
    request = args[0]
    headers = request.headers
    propagators.inject(type(headers).__setitem__, headers)
    return wrapped(*args, **kwargs)
Esempio n. 18
0
 def inject_current_context() -> Dict[Any, Any]:
     """Inject trace context into otel propagator."""
     context_dict: Dict[Any, Any] = {}
     propagators.inject(dict.__setitem__, context_dict)
     return context_dict
    def _instrumented_open_call(_, request, call_wrapped,
                                get_or_create_headers):  # pylint: disable=too-many-locals
        if context.get_value("suppress_instrumentation") or context.get_value(
                _SUPPRESS_URLLIB_INSTRUMENTATION_KEY):
            return call_wrapped()

        method = request.get_method().upper()
        url = request.full_url

        span_name = ""
        if name_callback is not None:
            span_name = name_callback(method, url)
        if not span_name or not isinstance(span_name, str):
            span_name = get_default_span_name(method)

        recorder = URLLibInstrumentor().metric_recorder

        labels = {
            "http.method": method,
            "http.url": url,
        }

        with get_tracer(__name__, __version__,
                        tracer_provider).start_as_current_span(
                            span_name, kind=SpanKind.CLIENT) as span:
            exception = None
            with recorder.record_client_duration(labels):
                if span.is_recording():
                    span.set_attribute("http.method", method)
                    span.set_attribute("http.url", url)

                headers = get_or_create_headers()
                propagators.inject(type(headers).__setitem__, headers)

                token = context.attach(
                    context.set_value(_SUPPRESS_URLLIB_INSTRUMENTATION_KEY,
                                      True))
                try:
                    result = call_wrapped()  # *** PROCEED
                except Exception as exc:  # pylint: disable=W0703
                    exception = exc
                    result = getattr(exc, "file", None)
                finally:
                    context.detach(token)

                if result is not None:

                    code_ = result.getcode()
                    labels["http.status_code"] = str(code_)

                    if span.is_recording():
                        span.set_attribute("http.status_code", code_)
                        span.set_attribute("http.status_text", result.reason)
                        span.set_status(
                            Status(http_status_to_status_code(code_)))

                    ver_ = str(getattr(result, "version", ""))
                    if ver_:
                        labels["http.flavor"] = "{}.{}".format(
                            ver_[:1], ver_[:-1])

                if span_callback is not None:
                    span_callback(span, result)

            if exception is not None:
                raise exception.with_traceback(exception.__traceback__)

        return result
Esempio n. 20
0
from requests import get

from opentelemetry import propagators, trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleSpanProcessor,
)

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer_provider().get_tracer(__name__)

trace.get_tracer_provider().add_span_processor(
    SimpleSpanProcessor(ConsoleSpanExporter()))

assert len(argv) == 2

with tracer.start_as_current_span("client"):

    with tracer.start_as_current_span("client-server"):
        headers = {}
        propagators.inject(headers)
        requested = get(
            "http://localhost:8082/server_request",
            params={"param": argv[1]},
            headers=headers,
        )

        assert requested.status_code == 200
Esempio n. 21
0
    def request(  # type:ignore
        self,
        method,
        url,
        query_params=None,
        headers=None,
        post_params=None,
        body=None,
        _preload_content=True,
        _request_timeout=None,
    ):
        headers = {} if headers is None else headers

        span_attributes = {
            "http.method": method,
            "http.url": url,
        }

        with get_tracer(__name__, __version__).start_as_current_span(
                f"External Api Call {self.__class__.__name__}",
                kind=SpanKind.CLIENT,
                attributes=span_attributes) as span:
            try:
                self.add_client_creds_token_header(headers)

                if self._tracing_enabled and not _is_instrumentation_suppressed(
                ):
                    inject(type(headers).__setitem__, headers)

                with _suppress_further_instrumentation():
                    response = super().request(  # type:ignore
                        method, url, query_params, headers, post_params, body,
                        _preload_content, _request_timeout)
                _apply_response(span, response)
                return response
            except Exception as ex:
                if is_api_exception(ex) and ex.status in (
                        HTTPStatus.UNAUTHORIZED,
                        HTTPStatus.FORBIDDEN):  # type:ignore
                    logger.warning("Access Denied. Token expired? Retrying.",
                                   api_exception=str(ex))
                    loop = new_event_loop()
                    loop.run_until_complete(
                        self.refresh_client_creds_token(force=True))
                    self.add_client_creds_token_header(headers)

                    if self._tracing_enabled and not _is_instrumentation_suppressed(
                    ):
                        inject(type(headers).__setitem__, headers)

                    with _suppress_further_instrumentation():
                        response = super().request(  # type:ignore
                            method, url, query_params, headers, post_params,
                            body, _preload_content, _request_timeout)
                    _apply_response(span, response)
                    return response

                else:
                    logger.exception("Could not call API.",
                                     client=self.__class__.__name__)
                    _apply_response(span, ex)
                    raise
Esempio n. 22
0
from opentelemetry.ext.datadog import (
    DatadogExportSpanProcessor,
    DatadogSpanExporter,
)
from opentelemetry.sdk.trace import TracerProvider

trace.set_tracer_provider(TracerProvider())

trace.get_tracer_provider().add_span_processor(
    DatadogExportSpanProcessor(
        DatadogSpanExporter(agent_url="http://localhost:8126",
                            service="example-client")))

tracer = trace.get_tracer(__name__)

assert len(argv) == 2

with tracer.start_as_current_span("client"):

    with tracer.start_as_current_span("client-server"):
        headers = {}
        propagators.inject(dict.__setitem__, headers)
        requested = get(
            "http://localhost:8082/server_request",
            params={"param": argv[1]},
            headers=headers,
        )

        assert requested.status_code == 200
        print(requested.text)