mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-30 05:32:30 +08:00
218 lines
7.3 KiB
Python
218 lines
7.3 KiB
Python
import gevent
|
|
import pytest
|
|
from opentracing.scope_managers.gevent import GeventScopeManager
|
|
|
|
import ddtrace
|
|
from ddtrace.contrib.gevent import patch, unpatch
|
|
from ddtrace.opentracer.utils import get_context_provider_for_scope_manager
|
|
|
|
|
|
@pytest.fixture()
|
|
def ot_tracer(ot_tracer_factory):
|
|
"""Fixture providing an opentracer configured for gevent usage."""
|
|
# patch gevent
|
|
patch()
|
|
yield ot_tracer_factory(
|
|
'gevent_svc', {}, GeventScopeManager(), ddtrace.contrib.gevent.context_provider
|
|
)
|
|
# unpatch gevent
|
|
unpatch()
|
|
|
|
|
|
class TestTracerGevent(object):
|
|
"""Converted Gevent tests for the regular tracer.
|
|
|
|
Ensures that greenlets are properly traced when using
|
|
the opentracer.
|
|
"""
|
|
|
|
def test_no_threading(self, ot_tracer):
|
|
with ot_tracer.start_span('span') as span:
|
|
span.set_tag('tag', 'value')
|
|
|
|
assert span.finished
|
|
|
|
def test_greenlets(self, ot_tracer, writer):
|
|
def f():
|
|
with ot_tracer.start_span('f') as span:
|
|
gevent.sleep(0.04)
|
|
span.set_tag('f', 'yes')
|
|
|
|
def g():
|
|
with ot_tracer.start_span('g') as span:
|
|
gevent.sleep(0.03)
|
|
span.set_tag('g', 'yes')
|
|
|
|
with ot_tracer.start_span('root'):
|
|
gevent.joinall([gevent.spawn(f), gevent.spawn(g)])
|
|
|
|
traces = writer.pop_traces()
|
|
assert len(traces) == 3
|
|
|
|
def test_trace_greenlet(self, ot_tracer, writer):
|
|
# a greenlet can be traced using the trace API
|
|
def greenlet():
|
|
with ot_tracer.start_span('greenlet'):
|
|
pass
|
|
|
|
gevent.spawn(greenlet).join()
|
|
traces = writer.pop_traces()
|
|
assert len(traces) == 1
|
|
assert len(traces[0]) == 1
|
|
assert traces[0][0].name == 'greenlet'
|
|
|
|
def test_trace_later_greenlet(self, ot_tracer, writer):
|
|
# a greenlet can be traced using the trace API
|
|
def greenlet():
|
|
with ot_tracer.start_span('greenlet'):
|
|
pass
|
|
|
|
gevent.spawn_later(0.01, greenlet).join()
|
|
traces = writer.pop_traces()
|
|
|
|
assert len(traces) == 1
|
|
assert len(traces[0]) == 1
|
|
assert traces[0][0].name == 'greenlet'
|
|
|
|
def test_trace_concurrent_calls(self, ot_tracer, writer):
|
|
# create multiple futures so that we expect multiple
|
|
# traces instead of a single one
|
|
def greenlet():
|
|
with ot_tracer.start_span('greenlet'):
|
|
gevent.sleep(0.01)
|
|
|
|
jobs = [gevent.spawn(greenlet) for x in range(100)]
|
|
gevent.joinall(jobs)
|
|
|
|
traces = writer.pop_traces()
|
|
|
|
assert len(traces) == 100
|
|
assert len(traces[0]) == 1
|
|
assert traces[0][0].name == 'greenlet'
|
|
|
|
def test_trace_concurrent_spawn_later_calls(self, ot_tracer, writer):
|
|
# create multiple futures so that we expect multiple
|
|
# traces instead of a single one, even if greenlets
|
|
# are delayed
|
|
def greenlet():
|
|
with ot_tracer.start_span('greenlet'):
|
|
gevent.sleep(0.01)
|
|
|
|
jobs = [gevent.spawn_later(0.01, greenlet) for x in range(100)]
|
|
gevent.joinall(jobs)
|
|
|
|
traces = writer.pop_traces()
|
|
assert len(traces) == 100
|
|
assert len(traces[0]) == 1
|
|
assert traces[0][0].name == 'greenlet'
|
|
|
|
|
|
class TestTracerGeventCompatibility(object):
|
|
"""Ensure the opentracer works in tandem with the ddtracer and gevent."""
|
|
|
|
def test_trace_spawn_multiple_greenlets_multiple_traces_ot_parent(
|
|
self, ot_tracer, dd_tracer, writer
|
|
):
|
|
"""
|
|
Copy of gevent test with the same name but testing with mixed usage of
|
|
the opentracer and datadog tracers.
|
|
|
|
Uses an opentracer span as the parent span.
|
|
"""
|
|
# multiple greenlets must be part of the same trace
|
|
def entrypoint():
|
|
with ot_tracer.start_active_span('greenlet.main'):
|
|
jobs = [gevent.spawn(green_1), gevent.spawn(green_2)]
|
|
gevent.joinall(jobs)
|
|
|
|
def green_1():
|
|
with dd_tracer.trace('greenlet.worker') as span:
|
|
span.set_tag('worker_id', '1')
|
|
gevent.sleep(0.01)
|
|
|
|
def green_2():
|
|
with ot_tracer.start_span('greenlet.worker') as span:
|
|
span.set_tag('worker_id', '2')
|
|
gevent.sleep(0.01)
|
|
|
|
gevent.spawn(entrypoint).join()
|
|
traces = writer.pop_traces()
|
|
assert len(traces) == 3
|
|
assert len(traces[0]) == 1
|
|
parent_span = traces[2][0]
|
|
worker_1 = traces[0][0]
|
|
worker_2 = traces[1][0]
|
|
# check spans data and hierarchy
|
|
assert parent_span.name == 'greenlet.main'
|
|
assert worker_1.get_tag('worker_id') == '1'
|
|
assert worker_1.name == 'greenlet.worker'
|
|
assert worker_1.resource == 'greenlet.worker'
|
|
assert worker_1.parent_id == parent_span.span_id
|
|
assert worker_2.get_tag('worker_id') == '2'
|
|
assert worker_2.name == 'greenlet.worker'
|
|
assert worker_2.resource == 'greenlet.worker'
|
|
assert worker_2.parent_id == parent_span.span_id
|
|
|
|
def test_trace_spawn_multiple_greenlets_multiple_traces_dd_parent(
|
|
self, ot_tracer, dd_tracer, writer
|
|
):
|
|
"""
|
|
Copy of gevent test with the same name but testing with mixed usage of
|
|
the opentracer and datadog tracers.
|
|
|
|
Uses an opentracer span as the parent span.
|
|
"""
|
|
# multiple greenlets must be part of the same trace
|
|
def entrypoint():
|
|
with dd_tracer.trace('greenlet.main'):
|
|
jobs = [gevent.spawn(green_1), gevent.spawn(green_2)]
|
|
gevent.joinall(jobs)
|
|
|
|
def green_1():
|
|
with ot_tracer.start_span('greenlet.worker') as span:
|
|
span.set_tag('worker_id', '1')
|
|
gevent.sleep(0.01)
|
|
|
|
def green_2():
|
|
with dd_tracer.trace('greenlet.worker') as span:
|
|
span.set_tag('worker_id', '2')
|
|
gevent.sleep(0.01)
|
|
|
|
gevent.spawn(entrypoint).join()
|
|
traces = writer.pop_traces()
|
|
assert len(traces) == 3
|
|
assert len(traces[0]) == 1
|
|
parent_span = traces[2][0]
|
|
worker_1 = traces[0][0]
|
|
worker_2 = traces[1][0]
|
|
# check spans data and hierarchy
|
|
assert parent_span.name == 'greenlet.main'
|
|
assert worker_1.get_tag('worker_id') == '1'
|
|
assert worker_1.name == 'greenlet.worker'
|
|
assert worker_1.resource == 'greenlet.worker'
|
|
assert worker_1.parent_id == parent_span.span_id
|
|
assert worker_2.get_tag('worker_id') == '2'
|
|
assert worker_2.name == 'greenlet.worker'
|
|
assert worker_2.resource == 'greenlet.worker'
|
|
assert worker_2.parent_id == parent_span.span_id
|
|
|
|
|
|
class TestUtilsGevent(object):
|
|
"""Test the util routines of the opentracer with gevent specific
|
|
configuration.
|
|
"""
|
|
|
|
def test_get_context_provider_for_scope_manager_asyncio(self):
|
|
scope_manager = GeventScopeManager()
|
|
ctx_prov = get_context_provider_for_scope_manager(scope_manager)
|
|
assert isinstance(
|
|
ctx_prov, ddtrace.contrib.gevent.provider.GeventContextProvider
|
|
)
|
|
|
|
def test_tracer_context_provider_config(self):
|
|
tracer = ddtrace.opentracer.Tracer('mysvc', scope_manager=GeventScopeManager())
|
|
assert isinstance(
|
|
tracer._dd_tracer.context_provider,
|
|
ddtrace.contrib.gevent.provider.GeventContextProvider,
|
|
)
|