diff --git a/README.md b/README.md index 991314bdf19..b597d6f6119 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ with tracer.start_span('foo'): print(Context) ``` +See [opentelemetry-example-app](./opentelemetry-example-app/README.rst) for a complete example. + ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py b/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py index fa7741695c8..fac5435ccc8 100644 --- a/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py +++ b/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py @@ -2,9 +2,10 @@ import unittest from unittest import mock -import opentelemetry.ext.http_requests import requests import urllib3 + +import opentelemetry.ext.http_requests from opentelemetry import trace @@ -53,7 +54,7 @@ def tearDown(self): def test_basic(self): url = "https://www.example.org/foo/bar?x=y#top" - _response = requests.get(url=url) + requests.get(url=url) self.assertEqual(1, len(self.send.call_args_list)) self.tracer.start_span.assert_called_with("/foo/bar") self.span_context_manager.__enter__.assert_called_with() @@ -78,7 +79,7 @@ def test_invalid_url(self): exception_type = ValueError with self.assertRaises(exception_type): - _response = requests.post(url=url) + requests.post(url=url) self.assertTrue( self.tracer.start_span.call_args[0][0].startswith( "`_ \ No newline at end of file diff --git a/opentelemetry-example-app/setup.py b/opentelemetry-example-app/setup.py new file mode 100644 index 00000000000..4494d4ad0fa --- /dev/null +++ b/opentelemetry-example-app/setup.py @@ -0,0 +1,53 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import setuptools + +setuptools.setup( + name="opentelemetry-example-app", + version="0.1.dev0", + author="OpenTelemetry Authors", + author_email="cncf-opentelemetry-contributors@lists.cncf.io", + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + ], + description="OpenTelemetry Python API", + include_package_data=True, + long_description=open("README.rst").read(), + install_requires=[ + "typing; python_version<'3.5'", + "opentelemetry-api", + "opentelemetry-sdk", + "opentelemetry-ext-http-requests", + "opentelemetry-ext-wsgi", + "flask", + "requests", + ], + license="Apache-2.0", + package_dir={"": "src"}, + packages=setuptools.find_namespace_packages(where="src"), + url=( + "https://github.com/open-telemetry/opentelemetry-python" + "/tree/master/opentelemetry-example-app" + ), + zip_safe=False, +) diff --git a/opentelemetry-example-app/src/opentelemetry_example_app/__init__.py b/opentelemetry-example-app/src/opentelemetry_example_app/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py b/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py new file mode 100644 index 00000000000..9568f270c98 --- /dev/null +++ b/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py @@ -0,0 +1,69 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +This module serves as an example to integrate with flask, using +the requests library to perform downstream requests +""" +import time + +import flask + +import opentelemetry.ext.http_requests +from opentelemetry import trace +from opentelemetry.ext.wsgi import OpenTelemetryMiddleware +from opentelemetry.sdk.trace import Tracer + + +def configure_opentelemetry(flask_app: flask.Flask): + """Configure a flask application to use OpenTelemetry. + + This activates the specific components: + + * sets tracer to the SDK's Tracer + * enables requests integration on the Tracer + * uses a WSGI middleware to enable configuration + + TODO: + + * processors? + * exporters? + * propagators? + """ + # Start by configuring all objects required to ensure + # a complete end to end workflow. + # the preferred implementation of these objects must be set, + # as the opentelemetry-api defines the interface with a no-op + # implementation. + trace.set_preferred_tracer_implementation(lambda _: Tracer()) + # Integrations are the glue that binds the OpenTelemetry API + # and the frameworks and libraries that are used together, automatically + # creating Spans and propagating context as appropriate. + opentelemetry.ext.http_requests.enable(trace.tracer()) + flask_app.wsgi_app = OpenTelemetryMiddleware(flask_app.wsgi_app) + + +app = flask.Flask(__name__) + + +@app.route("/") +def hello(): + # emit a trace that measures how long the + # sleep takes + with trace.tracer().start_span("sleep"): + time.sleep(0.001) + return "hello" + + +configure_opentelemetry(app) diff --git a/opentelemetry-example-app/tests/__init__.py b/opentelemetry-example-app/tests/__init__.py new file mode 100644 index 00000000000..d853a7bcf65 --- /dev/null +++ b/opentelemetry-example-app/tests/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/opentelemetry-example-app/tests/test_flask_example.py b/opentelemetry-example-app/tests/test_flask_example.py new file mode 100644 index 00000000000..ca2a237a60f --- /dev/null +++ b/opentelemetry-example-app/tests/test_flask_example.py @@ -0,0 +1,14 @@ +import unittest + +import opentelemetry_example_app.flask_example as flask_example + + +class TestFlaskExample(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.app = flask_example.app + + def test_full_path(self): + with self.app.test_client() as client: + response = client.get("/") + assert response.data.decode() == "hello" diff --git a/opentelemetry-sdk/tests/context/propagation/test_b3_format.py b/opentelemetry-sdk/tests/context/propagation/test_b3_format.py index 42ff3410f06..09d3f88f41e 100644 --- a/opentelemetry-sdk/tests/context/propagation/test_b3_format.py +++ b/opentelemetry-sdk/tests/context/propagation/test_b3_format.py @@ -13,9 +13,10 @@ # limitations under the License. import unittest -import opentelemetry.trace as api_trace + import opentelemetry.sdk.context.propagation.b3_format as b3_format import opentelemetry.sdk.trace as trace +import opentelemetry.trace as api_trace FORMAT = b3_format.B3Format() diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index c0a0e65008d..f763293ca27 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from unittest import mock import unittest +from unittest import mock from opentelemetry import trace as trace_api from opentelemetry.sdk import trace diff --git a/tox.ini b/tox.ini index acf1bcb367c..8967adaff77 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,8 @@ skipsdist = True skip_missing_interpreters = True envlist = - py3{4,5,6,7,8}-test-{api,sdk,ext-wsgi,ext-http-requests} - pypy35-test-{api,sdk,ext-wsgi,ext-http-requests} + py3{4,5,6,7,8}-test-{api,sdk,example-app,ext-wsgi,ext-http-requests} + pypy35-test-{api,sdk,example-app,ext-wsgi,ext-http-requests} lint py37-mypy docs @@ -22,6 +22,7 @@ setenv = changedir = test-api: opentelemetry-api/tests test-sdk: opentelemetry-sdk/tests + test-example-app: opentelemetry-example-app/tests test-ext-wsgi: ext/opentelemetry-ext-wsgi/tests test-ext-http-requests: ext/opentelemetry-ext-http-requests/tests @@ -30,6 +31,10 @@ commands_pre = python -m pip install -U pip setuptools wheel test: pip install {toxinidir}/opentelemetry-api test-sdk: pip install {toxinidir}/opentelemetry-sdk + example-app: pip install {toxinidir}/opentelemetry-sdk + example-app: pip install {toxinidir}/ext/opentelemetry-ext-wsgi + example-app: pip install {toxinidir}/ext/opentelemetry-ext-http-requests + example-app: pip install {toxinidir}/opentelemetry-example-app ext: pip install {toxinidir}/opentelemetry-api wsgi: pip install {toxinidir}/ext/opentelemetry-ext-wsgi http-requests: pip install {toxinidir}/ext/opentelemetry-ext-http-requests @@ -53,14 +58,23 @@ commands_pre = pip install -e {toxinidir}/opentelemetry-sdk pip install -e {toxinidir}/ext/opentelemetry-ext-wsgi pip install -e {toxinidir}/ext/opentelemetry-ext-http-requests + pip install -e {toxinidir}/opentelemetry-example-app commands = ; Prefer putting everything in one pylint command to profit from duplication ; warnings. - black --check --diff opentelemetry-api/src/opentelemetry opentelemetry-api/tests/ opentelemetry-sdk/src/opentelemetry opentelemetry-sdk/tests/ ext/opentelemetry-ext-http-requests/src/ ext/opentelemetry-ext-http-requests/tests/ ext/opentelemetry-ext-wsgi/tests/ - pylint opentelemetry-api/src/opentelemetry opentelemetry-api/tests/ opentelemetry-sdk/src/opentelemetry opentelemetry-sdk/tests/ ext/opentelemetry-ext-http-requests/src/ ext/opentelemetry-ext-http-requests/tests/ ext/opentelemetry-ext-wsgi/tests/ - flake8 opentelemetry-api/src/ opentelemetry-api/tests/ opentelemetry-sdk/src/ opentelemetry-sdk/tests/ ext/opentelemetry-ext-wsgi/src/ ext/opentelemetry-ext-wsgi/tests/ ext/opentelemetry-ext-http-requests/src/ - isort --check-only --diff --recursive opentelemetry-api/src opentelemetry-sdk/src ext/opentelemetry-ext-wsgi/src ext/opentelemetry-ext-wsgi/tests ext/opentelemetry-ext-http-requests/src/ + black --check --diff . + pylint opentelemetry-api/src/opentelemetry \ + opentelemetry-api/tests/ \ + opentelemetry-sdk/src/opentelemetry \ + opentelemetry-sdk/tests/ \ + ext/opentelemetry-ext-http-requests/src/ \ + ext/opentelemetry-ext-http-requests/tests/ \ + ext/opentelemetry-ext-wsgi/tests/ \ + opentelemetry-example-app/src/opentelemetry_example_app/ \ + opentelemetry-example-app/tests/ + flake8 . + isort --check-only --diff --recursive . [testenv:docs] deps =