File: README.md

package info (click to toggle)
python-opentracing 2.4.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 816 kB
  • sloc: python: 3,489; makefile: 98
file content (41 lines) | stat: -rw-r--r-- 1,987 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Multiple callbacks example.

This example shows a `Span` created for a top-level operation, covering a set of asynchronous operations (representing callbacks), and have this `Span` finished when **all** of them have been executed.

`Client.send()` is used to create a new asynchronous operation (callback), and in turn every operation both restores the active `Span`, and creates a child `Span` (useful for measuring the performance of each callback).

Implementation details:
- For `threading`, a thread-safe counter is put in each `Span` to keep track of the pending callbacks, and call `Span.finish()` when the count becomes 0.
- For `gevent`, `tornado`, `asyncio` and `contextvars` the children coroutines representing the subtasks are simply yielded over, so no counter is needed.
- For `tornado`, the invoked coroutines do not set any active `Span` as doing so messes the used `StackContext`. So yielding over **multiple** coroutines is not supported.
- For `contextvars`, parent context is propagated to the children coroutines implicitly, manual context activation has been avoided. 

`threading` implementation:
```python
    def task(self, interval, parent_span):
        logger.info('Starting task')

        try:
            scope = self.tracer.scope_manager.activate(parent_span, False)
            with self.tracer.start_active_span('task'):
                time.sleep(interval)
        finally:
            scope.close()
            if parent_span._ref_count.decr() == 0:
                parent_span.finish()
```

`asyncio` implementation:
```python
    async def task(self, interval, parent_span):
        logger.info('Starting task')

        with self.tracer.scope_manager.activate(parent_span, False):
            with self.tracer.start_active_span('task'):
                await asyncio.sleep(interval)

    # Invoke and yield over the corotuines.
    with self.tracer.start_active_span('parent'):
	tasks = self.submit_callbacks()
	await asyncio.gather(*tasks)
```