Skip to content

Commit

Permalink
Merge remote-tracking branch 'source/master' into feature/trace-get-c…
Browse files Browse the repository at this point in the history
…urrent-span
  • Loading branch information
toumorokoshi committed May 15, 2020
2 parents ec1c120 + 194824b commit 088931d
Show file tree
Hide file tree
Showing 155 changed files with 5,229 additions and 263 deletions.
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
ignore =
E501 # line too long, defer to black
F401 # unused import, defer to pylint
W503 # allow line breaks after binary ops, not after
W503 # allow line breaks before binary ops
W504 # allow line breaks after binary ops
E203 # allow whitespace before ':' (https://github.com/psf/black#slices)
exclude =
.bzr
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: prepare-release
on:
push:
branches:
- 'release/**'

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Get the version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}

- name: Prepare the release
id: update
run: |
./scripts/prepare_release.sh ${{ steps.get_version.outputs.VERSION }}
- name: Create Pull Request
id: create-pr
uses: peter-evans/create-pull-request@v2.7.0
with:
branch: ${{ steps.get_version.outputs.VERSION }}-auto
title: '[pre-release] Update changelogs, version [${{ steps.get_version.outputs.VERSION }}]'
if: ${{ steps.update.outputs.version_updated == 1 }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ _build/
# mypy
.mypy_cache/
target

# Django example

docs/examples/django/db.sqlite3
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pylint==2.4.4
flake8~=3.7
flake8==3.7.9
isort~=4.3
black>=19.3b0,==19.*
mypy==0.740
Expand Down
4 changes: 4 additions & 0 deletions docs-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ sphinx-rtd-theme~=0.4
sphinx-autodoc-typehints~=1.10.2

# Required by ext packages
ddtrace>=0.34.0
aiohttp ~= 3.0
Deprecated>=1.2.6
django>=2.2
PyMySQL~=0.9.3
flask~=1.0
mysql-connector-python~=8.0
Expand All @@ -12,5 +15,6 @@ prometheus_client>=0.5.0,<1.0.0
psycopg2-binary>=2.7.3.1
pymongo~=3.1
redis>=2.6
sqlalchemy>=1.0
thrift>=0.10.0
wrapt >=1.0.0,<2.0.0
8 changes: 8 additions & 0 deletions docs/auto_instrumentation/auto_instrumentation.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
OpenTelemetry Python Autoinstrumentation
========================================

.. automodule:: opentelemetry.auto_instrumentation
:members:
:undoc-members:
:show-inheritance:

Submodules
----------

.. toctree::
:maxdepth: 1

Expand Down
30 changes: 28 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
from os import listdir
from os.path import isdir, join

# configure django to avoid the following exception:
# django.core.exceptions.ImproperlyConfigured: Requested settings, but settings
# are not configured. You must either define the environment variable
# DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
from django.conf import settings

settings.configure()


source_dirs = [
os.path.abspath("../opentelemetry-api/src/"),
os.path.abspath("../opentelemetry-sdk/src/"),
Expand Down Expand Up @@ -68,6 +77,9 @@
"https://opentracing-python.readthedocs.io/en/latest/",
None,
),
"aiohttp": ("https://aiohttp.readthedocs.io/en/stable/", None),
"wrapt": ("https://wrapt.readthedocs.io/en/latest/", None),
"pymongo": ("https://pymongo.readthedocs.io/en/stable/", None),
}

# http://www.sphinx-doc.org/en/master/config.html#confval-nitpicky
Expand All @@ -79,8 +91,22 @@
nitpick_ignore = [
("py:class", "ValueT"),
("py:class", "MetricT"),
("py:class", "typing.Tuple"),
("py:class", "pymongo.monitoring.CommandListener"),
# Even if wrapt is added to intersphinx_mapping, sphinx keeps failing
# with "class reference target not found: ObjectProxy".
("py:class", "ObjectProxy"),
# TODO: Understand why sphinx is not able to find this local class
(
"py:class",
"opentelemetry.trace.propagation.httptextformat.HTTPTextFormat",
),
(
"any",
"opentelemetry.trace.propagation.httptextformat.HTTPTextFormat.extract",
),
(
"any",
"opentelemetry.trace.propagation.httptextformat.HTTPTextFormat.inject",
),
]

# Add any paths that contain templates here, relative to this directory.
Expand Down
189 changes: 189 additions & 0 deletions docs/examples/auto-instrumentation/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
Autoinstrumentation
===================

Overview
--------

This example shows how to use auto-instrumentation in OpenTelemetry.
This example is also based on a previous example for OpenTracing that
can be found
`here <https://github.com/yurishkuro/opentracing-tutorial/tree/master/python>`__.

The source files of these examples are available :scm_web:`here <docs/examples/auto-instrumentation/>`.

This example uses 2 scripts whose main difference is they being
instrumented manually or not:

1. ``server_instrumented.py`` which has been instrumented manually
2. ``server_uninstrumented.py`` which has not been instrumented manually

The former will be run without the automatic instrumentation agent and
the latter with the automatic instrumentation agent. They should produce
the same result, showing that the automatic instrumentation agent does
the equivalent of what manual instrumentation does.

In order to understand this better, here is the relevant part of both
scripts:

Manually instrumented server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``server_instrumented.py``

.. code:: python
@app.route("/server_request")
def server_request():
with tracer.start_as_current_span(
"server_request",
parent=propagators.extract(
lambda dict_, key: dict_.get(key, []), request.headers
)["current-span"],
):
print(request.args.get("param"))
return "served"
Publisher not instrumented manually
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``server_uninstrumented.py``

.. code:: python
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
Preparation
-----------

This example will be executed in a separate virtual environment:

.. code:: sh
$ mkdir auto_instrumentation
$ virtualenv auto_instrumentation
$ source auto_instrumentation/bin/activate
Installation
------------

.. code:: sh
$ pip install opentelemetry-sdk
$ pip install opentelemetry-auto-instrumentation
$ pip install opentelemetry-ext-flask
$ pip install requests
Execution
---------

Execution of the manually instrumented server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is done in 2 separate consoles, one to run each of the scripts that
make up this example:

.. code:: sh
$ source auto_instrumentation/bin/activate
$ python server_instrumented.py
.. code:: sh
$ source auto_instrumentation/bin/activate
$ python client.py testing
The execution of ``server_instrumented.py`` should return an output
similar to:

.. code:: sh
{
"name": "server_request",
"context": {
"trace_id": "0xfa002aad260b5f7110db674a9ddfcd23",
"span_id": "0x8b8bbaf3ca9c5131",
"trace_state": "{}"
},
"kind": "SpanKind.SERVER",
"parent_id": null,
"start_time": "2020-04-30T17:28:57.886397Z",
"end_time": "2020-04-30T17:28:57.886490Z",
"status": {
"canonical_code": "OK"
},
"attributes": {
"component": "http",
"http.method": "GET",
"http.server_name": "127.0.0.1",
"http.scheme": "http",
"host.port": 8082,
"http.host": "localhost:8082",
"http.target": "/server_request?param=testing",
"net.peer.ip": "127.0.0.1",
"net.peer.port": 52872,
"http.flavor": "1.1"
},
"events": [],
"links": []
}
Execution of an automatically instrumented server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now, kill the execution of ``server_instrumented.py`` with ``ctrl + c``
and run this instead:

.. code:: sh
$ opentelemetry-auto-instrumentation python server_uninstrumented.py
In the console where you previously executed ``client.py``, run again
this again:

.. code:: sh
$ python client.py testing
The execution of ``server_uninstrumented.py`` should return an output
similar to:

.. code:: sh
{
"name": "server_request",
"context": {
"trace_id": "0x9f528e0b76189f539d9c21b1a7a2fc24",
"span_id": "0xd79760685cd4c269",
"trace_state": "{}"
},
"kind": "SpanKind.SERVER",
"parent_id": "0xb4fb7eee22ef78e4",
"start_time": "2020-04-30T17:10:02.400604Z",
"end_time": "2020-04-30T17:10:02.401858Z",
"status": {
"canonical_code": "OK"
},
"attributes": {
"component": "http",
"http.method": "GET",
"http.server_name": "127.0.0.1",
"http.scheme": "http",
"host.port": 8082,
"http.host": "localhost:8082",
"http.target": "/server_request?param=testing",
"net.peer.ip": "127.0.0.1",
"net.peer.port": 48240,
"http.flavor": "1.1",
"http.route": "/server_request",
"http.status_text": "OK",
"http.status_code": 200
},
"events": [],
"links": []
}
Both outputs are equivalent since the automatic instrumentation does
what the manual instrumentation does too.
Loading

0 comments on commit 088931d

Please sign in to comment.