Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Commit

Permalink
V2.0.0 (#94)
Browse files Browse the repository at this point in the history
* Implement ScopeManager for in-process propagation (updated) (#64)
* Updating docstrings and tests
* Testbed import (#80)
* Scope managers integration (#83)
  • Loading branch information
carlosalberto authored Jul 10, 2018
1 parent 23a0af1 commit 2f79bf3
Show file tree
Hide file tree
Showing 90 changed files with 4,380 additions and 164 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ install:
- make bootstrap

script:
- make test lint
- make test testbed lint

10 changes: 8 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
History
=======

2.0.0rc2 (2018-04-09)
---------------------

- Implement ScopeManager for in-process propagation.


1.3.0 (2018-01-14)
------------------

Expand All @@ -21,7 +27,7 @@ History
1.2.1 (2016-09-22)
------------------

- Make Span.log(self, **kwargs) smarter
- Make Span.log(self, \**kwargs) smarter


1.2.0 (2016-09-21)
Expand Down Expand Up @@ -109,7 +115,7 @@ History
------------------

- Change inheritance to match api-go: TraceContextSource extends codecs,
Tracer extends TraceContextSource
Tracer extends TraceContextSource
- Create API harness


Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ recursive-include opentracing *
recursive-include example *.py
recursive-include example *.thrift
recursive-include tests *.py
prune testbed
include *
global-exclude *.pyc
graft docs
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pytest := PYTHONDONTWRITEBYTECODE=1 py.test --tb short -rxs \
html_report := --cov-report=html
test_args := --cov-report xml --cov-report term-missing

.PHONY: clean-pyc clean-build docs clean
.PHONY: clean-pyc clean-build docs clean testbed
.DEFAULT_GOAL : help

help:
Expand All @@ -17,6 +17,7 @@ help:
@echo "clean-test - remove test and coverage artifacts"
@echo "lint - check style with flake8"
@echo "test - run tests quickly with the default Python"
@echo "testbed - run testbed scenarios with the default Python"
@echo "coverage - check code coverage quickly with the default Python"
@echo "docs - generate Sphinx HTML documentation, including API docs"
@echo "release - package and upload a release"
Expand Down Expand Up @@ -57,6 +58,9 @@ lint:
test:
$(pytest) $(test_args)

testbed:
PYTHONDONTWRITEBYTECODE=1 python -m testbed

jenkins:
pip install -r requirements.txt
pip install -r requirements-test.txt
Expand Down
108 changes: 93 additions & 15 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
OpenTracing API for Python
==========================

|GitterChat| |BuildStatus| |PyPI|
|GitterChat| |BuildStatus| |PyPI| |ReadTheDocs|

This library is a Python platform API for OpenTracing.

Expand Down Expand Up @@ -34,18 +34,18 @@ The work of instrumentation libraries generally consists of three steps:
Span object in the process. If the request does not contain an active trace,
the service starts a new trace and a new *root* Span.
2. The service needs to store the current Span in some request-local storage,
where it can be retrieved from when a child Span must be created, e.g. in case
of the service making an RPC to another service.
(called ``Span`` *activation*) where it can be retrieved from when a child Span must
be created, e.g. in case of the service making an RPC to another service.
3. When making outbound calls to another service, the current Span must be
retrieved from request-local storage, a child span must be created (e.g., by
using the ``start_child_span()`` helper), and that child span must be embedded
into the outbound request (e.g., using HTTP headers) via OpenTracing's
inject/extract API.

Below are the code examples for steps 1 and 3. Implementation of request-local
storage needed for step 2 is specific to the service and/or frameworks /
instrumentation libraries it is using (TODO: reference to other OSS projects
with examples of instrumentation).
Below are the code examples for the previously mentioned steps. Implementation
of request-local storage needed for step 2 is specific to the service and/or frameworks /
instrumentation libraries it is using, exposed as a ``ScopeManager`` child contained
as ``Tracer.scope_manager``. See details below.

Inbound request
^^^^^^^^^^^^^^^
Expand All @@ -56,12 +56,12 @@ Somewhere in your server's request handler code:
def handle_request(request):
span = before_request(request, opentracing.tracer)
# use span as Context Manager to ensure span.finish() will be called
with span:
# store span in some request-local storage
with RequestContext(span):
# actual business logic
handle_request_for_real(request)
# store span in some request-local storage using Tracer.scope_manager,
# using the returned `Scope` as Context Manager to ensure
# `Span` will be cleared and (in this case) `Span.finish()` be called.
with tracer.scope_manager.activate(span, True) as scope:
# actual business logic
handle_request_for_real(request)
def before_request(request, tracer):
Expand Down Expand Up @@ -137,6 +137,78 @@ Somewhere in your service that's about to make an outgoing call:
return outbound_span
Scope and within-process propagation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For getting/setting the current active ``Span`` in the used request-local storage,
OpenTracing requires that every ``Tracer`` contains a ``ScopeManager`` that grants
access to the active ``Span`` through a ``Scope``. Any ``Span`` may be transferred to
another task or thread, but not ``Scope``.

.. code-block:: python
# Access to the active span is straightforward.
scope = tracer.scope_manager.active()
if scope is not None:
scope.span.set_tag('...', '...')
The common case starts a ``Scope`` that's automatically registered for intra-process
propagation via ``ScopeManager``.

Note that ``start_active_span('...')`` automatically finishes the span on ``Scope.close()``
(``start_active_span('...', finish_on_close=False)`` does not finish it, in contrast).

.. code-block:: python
# Manual activation of the Span.
span = tracer.start_span(operation_name='someWork')
with tracer.scope_manager.activate(span, True) as scope:
# Do things.
# Automatic activation of the Span.
# finish_on_close is a required parameter.
with tracer.start_active_span('someWork', finish_on_close=True) as scope:
# Do things.
# Handling done through a try construct:
span = tracer.start_span(operation_name='someWork')
scope = tracer.scope_manager.activate(span, True)
try:
# Do things.
except Exception as e:
scope.set_tag('error', '...')
finally:
scope.finish()
**If there is a Scope, it will act as the parent to any newly started Span** unless
the programmer passes ``ignore_active_span=True`` at ``start_span()``/``start_active_span()``
time or specified parent context explicitly:

.. code-block:: python
scope = tracer.start_active_span('someWork', ignore_active_span=True)
Each service/framework ought to provide a specific ``ScopeManager`` implementation
that relies on their own request-local storage (thread-local storage, or coroutine-based storage
for asynchronous frameworks, for example).

Scope managers
^^^^^^^^^^^^^^

This project includes a set of ``ScopeManager`` implementations under the ``opentracing.scope_managers`` submodule, which can be imported on demand:

.. code-block:: python
from opentracing.scope_managers import ThreadLocalScopeManager
There exist implementations for ``thread-local`` (the default), ``gevent``, ``Tornado`` and ``asyncio``:

.. code-block:: python
from opentracing.scope_managers.gevent import GeventScopeManager # requires gevent
from opentracing.scope_managers.tornado import TornadoScopeManager # requires Tornado
from opentracing.scope_managers.asyncio import AsyncioScopeManager # requires Python 3.4 or newer.
Development
-----------

Expand All @@ -150,6 +222,11 @@ Tests
make bootstrap
make test
Testbed suite
^^^^^^^^^^^^^

A testbed suite designed to test API changes and experimental features is included under the *testbed* directory. For more information, see the `Testbed README <testbed/README.md>`_.

Instrumentation Tests
---------------------

Expand Down Expand Up @@ -206,5 +283,6 @@ Before new release, add a summary of changes since last version to CHANGELOG.rst
:target: https://travis-ci.org/opentracing/opentracing-python
.. |PyPI| image:: https://badge.fury.io/py/opentracing.svg
:target: https://badge.fury.io/py/opentracing


.. |ReadTheDocs| image:: http://readthedocs.org/projects/opentracing-python/badge/?version=latest
:target: https://opentracing-python.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
27 changes: 27 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Classes
.. autoclass:: opentracing.SpanContext
:members:

.. autoclass:: opentracing.Scope
:members:

.. autoclass:: opentracing.ScopeManager
:members:

.. autoclass:: opentracing.Tracer
:members:

Expand Down Expand Up @@ -39,3 +45,24 @@ Exceptions

.. autoclass:: opentracing.UnsupportedFormatException
:members:

MockTracer
--------------
.. autoclass:: opentracing.mocktracer.MockTracer
:members:

Scope managers
--------------
.. autoclass:: opentracing.scope_managers.ThreadLocalScopeManager
:members:

.. autoclass:: opentracing.scope_managers.gevent.GeventScopeManager
:members:

.. autoclass:: opentracing.scope_managers.tornado.TornadoScopeManager
:members:

.. autofunction:: opentracing.scope_managers.tornado.tracer_stack_context

.. autoclass:: opentracing.scope_managers.asyncio.AsyncioScopeManager
:members:
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_static_path = ['_static']
html_static_path = []
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

intersphinx_mapping = {
Expand Down
2 changes: 2 additions & 0 deletions opentracing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from __future__ import absolute_import
from .span import Span # noqa
from .span import SpanContext # noqa
from .scope import Scope # noqa
from .scope_manager import ScopeManager # noqa
from .tracer import child_of # noqa
from .tracer import follows_from # noqa
from .tracer import Reference # noqa
Expand Down
Loading

0 comments on commit 2f79bf3

Please sign in to comment.