mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-29 21:23:55 +08:00
Conditionally create server spans for falcon (#867)
* Making span as internal for falcon in presence of a span in current context * Updating changelog * Fixing lint and generate build failures * Resolving comments: Converting snippet to re-usable function * Fixing build failures * Resolving comments: Creating wrapper for start span to make internal/server span * Rerun docker tests * Resolving comments: Refactoring
This commit is contained in:
@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
([#817](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/817))
|
||||
- `opentelemetry-instrumentation-kafka-python` added kafka-python module instrumentation.
|
||||
([#814](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/814))
|
||||
|
||||
- `opentelemetry-instrumentation-falcon` Falcon: Conditionally create SERVER spans
|
||||
([#867](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/867))
|
||||
### Fixed
|
||||
|
||||
- `opentelemetry-instrumentation-django` Django: Conditionally create SERVER spans
|
||||
|
@ -107,10 +107,10 @@ from opentelemetry.instrumentation.propagators import (
|
||||
get_global_response_propagator,
|
||||
)
|
||||
from opentelemetry.instrumentation.utils import (
|
||||
_start_internal_or_server_span,
|
||||
extract_attributes_from_object,
|
||||
http_status_to_status_code,
|
||||
)
|
||||
from opentelemetry.propagate import extract
|
||||
from opentelemetry.semconv.trace import SpanAttributes
|
||||
from opentelemetry.trace.status import Status
|
||||
from opentelemetry.util._time import _time_ns
|
||||
@ -195,12 +195,14 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
|
||||
|
||||
start_time = _time_ns()
|
||||
|
||||
token = context.attach(extract(env, getter=otel_wsgi.wsgi_getter))
|
||||
span = self._tracer.start_span(
|
||||
otel_wsgi.get_default_span_name(env),
|
||||
kind=trace.SpanKind.SERVER,
|
||||
span, token = _start_internal_or_server_span(
|
||||
tracer=self._tracer,
|
||||
span_name=otel_wsgi.get_default_span_name(env),
|
||||
start_time=start_time,
|
||||
context_carrier=env,
|
||||
context_getter=otel_wsgi.wsgi_getter,
|
||||
)
|
||||
|
||||
if span.is_recording():
|
||||
attributes = otel_wsgi.collect_request_attributes(env)
|
||||
for key, value in attributes.items():
|
||||
@ -216,7 +218,8 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
|
||||
status, response_headers, *args, **kwargs
|
||||
)
|
||||
activation.__exit__(None, None, None)
|
||||
context.detach(token)
|
||||
if token is not None:
|
||||
context.detach(token)
|
||||
return response
|
||||
|
||||
try:
|
||||
@ -227,7 +230,8 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
|
||||
exc,
|
||||
getattr(exc, "__traceback__", None),
|
||||
)
|
||||
context.detach(token)
|
||||
if token is not None:
|
||||
context.detach(token)
|
||||
raise
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@ from unittest.mock import Mock, patch
|
||||
|
||||
from falcon import testing
|
||||
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.instrumentation.falcon import FalconInstrumentor
|
||||
from opentelemetry.instrumentation.propagators import (
|
||||
TraceResponsePropagator,
|
||||
@ -264,3 +265,18 @@ class TestFalconInstrumentationHooks(TestFalconBase):
|
||||
self.assertEqual(
|
||||
span.attributes["request_hook_attr"], "value from hook"
|
||||
)
|
||||
|
||||
|
||||
class TestFalconInstrumentationWrappedWithOtherFramework(TestFalconBase):
|
||||
def test_mark_span_internal_in_presence_of_span_from_other_framework(self):
|
||||
tracer = trace.get_tracer(__name__)
|
||||
with tracer.start_as_current_span(
|
||||
"test", kind=trace.SpanKind.SERVER
|
||||
) as parent_span:
|
||||
self.client().simulate_request(method="GET", path="/hello")
|
||||
span = self.memory_exporter.get_finished_spans()[0]
|
||||
assert span.status.is_ok
|
||||
self.assertEqual(trace.SpanKind.INTERNAL, span.kind)
|
||||
self.assertEqual(
|
||||
span.parent.span_id, parent_span.get_span_context().span_id
|
||||
)
|
||||
|
@ -16,9 +16,12 @@ from typing import Dict, Sequence
|
||||
|
||||
from wrapt import ObjectProxy
|
||||
|
||||
from opentelemetry import context, trace
|
||||
|
||||
# pylint: disable=unused-import
|
||||
# pylint: disable=E0611
|
||||
from opentelemetry.context import _SUPPRESS_INSTRUMENTATION_KEY # noqa: F401
|
||||
from opentelemetry.propagate import extract
|
||||
from opentelemetry.trace import StatusCode
|
||||
|
||||
|
||||
@ -67,3 +70,39 @@ def unwrap(obj, attr: str):
|
||||
func = getattr(obj, attr, None)
|
||||
if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"):
|
||||
setattr(obj, attr, func.__wrapped__)
|
||||
|
||||
|
||||
def _start_internal_or_server_span(
|
||||
tracer, span_name, start_time, context_carrier, context_getter
|
||||
):
|
||||
"""Returns internal or server span along with the token which can be used by caller to reset context
|
||||
|
||||
|
||||
Args:
|
||||
tracer : tracer in use by given instrumentation library
|
||||
name (string): name of the span
|
||||
start_time : start time of the span
|
||||
context_carrier : object which contains values that are
|
||||
used to construct a Context. This object
|
||||
must be paired with an appropriate getter
|
||||
which understands how to extract a value from it.
|
||||
context_getter : an object which contains a get function that can retrieve zero
|
||||
or more values from the carrier and a keys function that can get all the keys
|
||||
from carrier.
|
||||
"""
|
||||
|
||||
token = ctx = span_kind = None
|
||||
if trace.get_current_span() is trace.INVALID_SPAN:
|
||||
ctx = extract(context_carrier, getter=context_getter)
|
||||
token = context.attach(ctx)
|
||||
span_kind = trace.SpanKind.SERVER
|
||||
else:
|
||||
ctx = context.get_current()
|
||||
span_kind = trace.SpanKind.INTERNAL
|
||||
span = tracer.start_span(
|
||||
name=span_name,
|
||||
context=ctx,
|
||||
kind=span_kind,
|
||||
start_time=start_time,
|
||||
)
|
||||
return span, token
|
||||
|
Reference in New Issue
Block a user