mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-08-01 06:33:52 +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))
|
([#817](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/817))
|
||||||
- `opentelemetry-instrumentation-kafka-python` added kafka-python module instrumentation.
|
- `opentelemetry-instrumentation-kafka-python` added kafka-python module instrumentation.
|
||||||
([#814](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/814))
|
([#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
|
### Fixed
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-django` Django: Conditionally create SERVER spans
|
- `opentelemetry-instrumentation-django` Django: Conditionally create SERVER spans
|
||||||
|
@ -107,10 +107,10 @@ from opentelemetry.instrumentation.propagators import (
|
|||||||
get_global_response_propagator,
|
get_global_response_propagator,
|
||||||
)
|
)
|
||||||
from opentelemetry.instrumentation.utils import (
|
from opentelemetry.instrumentation.utils import (
|
||||||
|
_start_internal_or_server_span,
|
||||||
extract_attributes_from_object,
|
extract_attributes_from_object,
|
||||||
http_status_to_status_code,
|
http_status_to_status_code,
|
||||||
)
|
)
|
||||||
from opentelemetry.propagate import extract
|
|
||||||
from opentelemetry.semconv.trace import SpanAttributes
|
from opentelemetry.semconv.trace import SpanAttributes
|
||||||
from opentelemetry.trace.status import Status
|
from opentelemetry.trace.status import Status
|
||||||
from opentelemetry.util._time import _time_ns
|
from opentelemetry.util._time import _time_ns
|
||||||
@ -195,12 +195,14 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
|
|||||||
|
|
||||||
start_time = _time_ns()
|
start_time = _time_ns()
|
||||||
|
|
||||||
token = context.attach(extract(env, getter=otel_wsgi.wsgi_getter))
|
span, token = _start_internal_or_server_span(
|
||||||
span = self._tracer.start_span(
|
tracer=self._tracer,
|
||||||
otel_wsgi.get_default_span_name(env),
|
span_name=otel_wsgi.get_default_span_name(env),
|
||||||
kind=trace.SpanKind.SERVER,
|
|
||||||
start_time=start_time,
|
start_time=start_time,
|
||||||
|
context_carrier=env,
|
||||||
|
context_getter=otel_wsgi.wsgi_getter,
|
||||||
)
|
)
|
||||||
|
|
||||||
if span.is_recording():
|
if span.is_recording():
|
||||||
attributes = otel_wsgi.collect_request_attributes(env)
|
attributes = otel_wsgi.collect_request_attributes(env)
|
||||||
for key, value in attributes.items():
|
for key, value in attributes.items():
|
||||||
@ -216,7 +218,8 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
|
|||||||
status, response_headers, *args, **kwargs
|
status, response_headers, *args, **kwargs
|
||||||
)
|
)
|
||||||
activation.__exit__(None, None, None)
|
activation.__exit__(None, None, None)
|
||||||
context.detach(token)
|
if token is not None:
|
||||||
|
context.detach(token)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -227,7 +230,8 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
|
|||||||
exc,
|
exc,
|
||||||
getattr(exc, "__traceback__", None),
|
getattr(exc, "__traceback__", None),
|
||||||
)
|
)
|
||||||
context.detach(token)
|
if token is not None:
|
||||||
|
context.detach(token)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from unittest.mock import Mock, patch
|
|||||||
|
|
||||||
from falcon import testing
|
from falcon import testing
|
||||||
|
|
||||||
|
from opentelemetry import trace
|
||||||
from opentelemetry.instrumentation.falcon import FalconInstrumentor
|
from opentelemetry.instrumentation.falcon import FalconInstrumentor
|
||||||
from opentelemetry.instrumentation.propagators import (
|
from opentelemetry.instrumentation.propagators import (
|
||||||
TraceResponsePropagator,
|
TraceResponsePropagator,
|
||||||
@ -264,3 +265,18 @@ class TestFalconInstrumentationHooks(TestFalconBase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
span.attributes["request_hook_attr"], "value from hook"
|
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 wrapt import ObjectProxy
|
||||||
|
|
||||||
|
from opentelemetry import context, trace
|
||||||
|
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
# pylint: disable=E0611
|
# pylint: disable=E0611
|
||||||
from opentelemetry.context import _SUPPRESS_INSTRUMENTATION_KEY # noqa: F401
|
from opentelemetry.context import _SUPPRESS_INSTRUMENTATION_KEY # noqa: F401
|
||||||
|
from opentelemetry.propagate import extract
|
||||||
from opentelemetry.trace import StatusCode
|
from opentelemetry.trace import StatusCode
|
||||||
|
|
||||||
|
|
||||||
@ -67,3 +70,39 @@ def unwrap(obj, attr: str):
|
|||||||
func = getattr(obj, attr, None)
|
func = getattr(obj, attr, None)
|
||||||
if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"):
|
if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"):
|
||||||
setattr(obj, attr, 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