Skip to content

Commit

Permalink
Merge branch 'taegyunkim/prof-10916-gh-actions' into taegyunkim/prof-…
Browse files Browse the repository at this point in the history
…10916-sanitizer-fixes
  • Loading branch information
taegyunkim committed Dec 4, 2024
2 parents b8b94b9 + f90b8d3 commit b2b135f
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/profiling-native.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: ProfilingNativeTests

on:
push:
paths:
- ddtrace/internal/datadog/profiling/**
branches:
- main
- 'mq-working-branch**'
pull_request:
workflow_dispatch: {}

jobs:
profiling-native-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
sanitizer: ["safety", "thread"]

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1

- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install latest Rust
run: rustup update stable && rustup default stable

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Run profiling native tests
run: ./ddtrace/internal/datadog/profiling/build_standalone.sh --${{matrix.sanitizer}} RelWithDebInfo dd_wrapper_test
24 changes: 24 additions & 0 deletions ddtrace/internal/opentelemetry/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def attach(self, otel_context):
Datadog representation in the Global DDtrace Trace Context Provider.
"""
# Inline opentelemetry imports to avoid circular imports.
from opentelemetry.baggage import get_all
from opentelemetry.trace import Span as OtelSpan
from opentelemetry.trace import get_current_span

Expand All @@ -30,18 +31,29 @@ def attach(self, otel_context):
if otel_span:
if isinstance(otel_span, Span):
self._ddcontext_provider.activate(otel_span._ddspan)
ddcontext = otel_span._ddspan.context
elif isinstance(otel_span, OtelSpan):
trace_id, span_id, _, tf, ts, _ = otel_span.get_span_context()
trace_state = ts.to_header() if ts else None
ddcontext = _TraceContext._get_context(trace_id, span_id, tf, trace_state)
self._ddcontext_provider.activate(ddcontext)
else:
ddcontext = None
log.error(
"Programming ERROR: ddtrace does not support activating spans with the type: %s. Please open a "
"github issue at: https://github.com/Datadog/dd-trace-py and set DD_TRACE_OTEL_ENABLED=True.",
type(otel_span),
)

# get current open telemetry baggage and store it on the datadog context object
# fix: we need to support setting baggage when there is no active span
otel_baggage = get_all(otel_context)
if ddcontext:
ddcontext.remove_all_baggage_items()
if otel_baggage:
for key, value in otel_baggage.items():
ddcontext._baggage[key] = value # potentially convert to json

# A return value with the type `object` is required by the otel api to remove/deactivate spans.
# Since manually deactivating spans is not supported by ddtrace this object will never be used.
return object()
Expand All @@ -52,6 +64,7 @@ def get_current(self):
in a format that can be parsed by the OpenTelemetry API.
"""
# Inline opentelemetry imports to avoid circular imports.
from opentelemetry.baggage import set_baggage
from opentelemetry.context.context import Context as OtelContext
from opentelemetry.trace import NonRecordingSpan as OtelNonRecordingSpan
from opentelemetry.trace import SpanContext as OtelSpanContext
Expand All @@ -72,6 +85,17 @@ def get_current(self):
span_context = OtelSpanContext(ddactive.trace_id or 0, ddactive.span_id or 0, True, tf, ts)
span = OtelNonRecordingSpan(span_context)
context = set_span_in_context(span, context)

if isinstance(ddactive, DDSpan):
dd_baggage = ddactive.context._baggage
elif isinstance(ddactive, DDContext):
dd_baggage = ddactive._baggage
else:
dd_baggage = {}

for key, value in dd_baggage.items():
context = set_baggage(key, value, context)

return context

def detach(self, token):
Expand Down
50 changes: 50 additions & 0 deletions tests/opentelemetry/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import time

import opentelemetry
from opentelemetry.baggage import get_baggage
from opentelemetry.baggage import remove_baggage
from opentelemetry.baggage import set_baggage
from opentelemetry.context import attach
import pytest

import ddtrace
Expand Down Expand Up @@ -129,3 +133,49 @@ async def coro(i):
await coro(2)
await coro(3)
await coro(4)


def test_otel_baggage_propagation_to_ddtrace(oteltracer):
with oteltracer.start_as_current_span("otel-baggage-inject") as span: # noqa: F841
baggage_context = set_baggage("key1", "value1")
baggage_context = set_baggage("key2", "value2", baggage_context)
attach(baggage_context)
with ddtrace.tracer.trace("ddtrace-baggage-inject") as ddspan:
assert ddspan.context.get_baggage_item("key1") == "value1"
assert ddspan.context.get_baggage_item("key2") == "value2"


def test_ddtrace_baggage_propagation_to_otel(oteltracer):
with ddtrace.tracer.trace("ddtrace-baggage") as ddspan:
ddspan.context.set_baggage_item("key1", "value1")
ddspan.context.set_baggage_item("key2", "value2")
assert get_baggage("key1") == "value1"
assert get_baggage("key2") == "value2"


def test_conflicting_otel_and_ddtrace_baggage(oteltracer):
with ddtrace.tracer.trace("ddtrace-baggage") as ddspan:
ddspan.context.set_baggage_item("key1", "dd1")
attach(set_baggage("key1", "otel1"))
attach(set_baggage("key2", "otel2"))
ddspan.context.set_baggage_item("key2", "dd2")
assert get_baggage("key1") == "otel1"
assert get_baggage("key2") == "dd2"


def test_otel_baggage_removal_propagation_to_ddtrace(oteltracer):
with oteltracer.start_as_current_span("otel-baggage-inject") as span: # noqa: F841
baggage_context = set_baggage("key1", "value1")
baggage_context = set_baggage("key2", "value2", baggage_context)
attach(baggage_context)
baggage_context = set_baggage("key3", "value3")
baggage_context = set_baggage("key4", "value4", baggage_context)
baggage_context = remove_baggage("key1", baggage_context)
baggage_context = remove_baggage("key2", baggage_context)
attach(baggage_context)
with ddtrace.tracer.trace("ddtrace-baggage-inject") as ddspan:
# newest baggage set in otel should take precedence
assert ddspan.context.get_baggage_item("key3") == "value3"
assert ddspan.context.get_baggage_item("key4") == "value4"
assert ddspan.context.get_baggage_item("key1") is None
assert ddspan.context.get_baggage_item("key2") is None

0 comments on commit b2b135f

Please sign in to comment.