-
Notifications
You must be signed in to change notification settings - Fork 631
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement WSGI middleware integration. (#84)
- Loading branch information
Showing
8 changed files
with
452 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
OpenTelemetry WSGI Middleware | ||
============================= | ||
|
||
This library provides a WSGI middleware that can be used on any WSGI framework | ||
(such as Django / Flask) to track requests timing through OpenTelemetry. | ||
|
||
|
||
Usage (Flask) | ||
------------- | ||
|
||
.. code-block:: python | ||
from flask import Flask | ||
from opentelemetry.ext.wsgi import OpenTelemetryMiddleware | ||
app = Flask(__name__) | ||
app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) | ||
@app.route("/") | ||
def hello(): | ||
return "Hello!" | ||
if __name__ == "__main__": | ||
app.run(debug=True) | ||
Usage (Django) | ||
-------------- | ||
|
||
Modify the application's ``wsgi.py`` file as shown below. | ||
|
||
.. code-block:: python | ||
import os | ||
from opentelemetry.ext.wsgi import OpenTelemetryMiddleware | ||
from django.core.wsgi import get_wsgi_application | ||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings') | ||
application = get_wsgi_application() | ||
application = OpenTelemetryMiddleware(application) | ||
References | ||
---------- | ||
|
||
* `OpenTelemetry Project <https://opentelemetry.io/>`_ | ||
* `WSGI <https://www.python.org/dev/peps/pep-3333>`_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# 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. | ||
# | ||
[metadata] | ||
name = opentelemetry-ext-wsgi | ||
description = WSGI Middleware for OpenTelemetry | ||
long_description = file: README.rst | ||
long_description_content_type = text/x-rst | ||
author = OpenTelemetry Authors | ||
author_email = cncf-opentelemetry-contributors@lists.cncf.io | ||
url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-ext-wsgi | ||
platforms = any | ||
license = Apache-2.0 | ||
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 | ||
|
||
[options] | ||
python_requires = >=3.4 | ||
package_dir= | ||
=src | ||
packages=find: | ||
install_requires = | ||
opentelemetry-api | ||
|
||
[options.packages.find] | ||
where = src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# 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 os | ||
import setuptools | ||
|
||
BASE_DIR = os.path.dirname(__file__) | ||
VERSION_FILENAME = os.path.join( | ||
BASE_DIR, | ||
"src", | ||
"opentelemetry", | ||
"ext", | ||
"wsgi", | ||
"version.py", | ||
) | ||
PACKAGE_INFO = {} | ||
with open(VERSION_FILENAME) as f: | ||
exec(f.read(), PACKAGE_INFO) | ||
|
||
setuptools.setup(version=PACKAGE_INFO["__version__"]) |
105 changes: 105 additions & 0 deletions
105
ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# 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. | ||
|
||
""" | ||
The opentelemetry-ext-wsgi package provides a WSGI middleware that can be used | ||
on any WSGI framework (such as Django / Flask) to track requests timing through | ||
OpenTelemetry. | ||
""" | ||
|
||
import functools | ||
import wsgiref.util as wsgiref_util | ||
|
||
from opentelemetry import trace | ||
from opentelemetry.ext.wsgi.version import __version__ # noqa | ||
|
||
|
||
class OpenTelemetryMiddleware: | ||
"""The WSGI application middleware. | ||
This class is used to create and annotate spans for requests to a WSGI | ||
application. | ||
Args: | ||
wsgi: The WSGI application callable. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
wsgi, | ||
propagators=None, | ||
): | ||
self.wsgi = wsgi | ||
|
||
# TODO: implement context propagation | ||
self.propagators = propagators | ||
|
||
@staticmethod | ||
def _add_request_attributes(span, environ): | ||
span.set_attribute("component", "http") | ||
span.set_attribute("http.method", environ["REQUEST_METHOD"]) | ||
|
||
host = environ.get("HTTP_HOST") or environ["SERVER_NAME"] | ||
span.set_attribute("http.host", host) | ||
|
||
url = ( | ||
environ.get("REQUEST_URI") or | ||
environ.get("RAW_URI") or | ||
wsgiref_util.request_uri(environ, include_query=False) | ||
) | ||
span.set_attribute("http.url", url) | ||
|
||
@staticmethod | ||
def _add_response_attributes(span, status): | ||
status_code, status_text = status.split(" ", 1) | ||
span.set_attribute("http.status_text", status_text) | ||
|
||
try: | ||
status_code = int(status_code) | ||
except ValueError: | ||
pass | ||
else: | ||
span.set_attribute("http.status_code", status_code) | ||
|
||
@classmethod | ||
def _create_start_response(cls, span, start_response): | ||
@functools.wraps(start_response) | ||
def _start_response(status, response_headers, *args, **kwargs): | ||
cls._add_response_attributes(span, status) | ||
return start_response(status, response_headers, *args, **kwargs) | ||
|
||
return _start_response | ||
|
||
def __call__(self, environ, start_response): | ||
"""The WSGI application | ||
Args: | ||
environ: A WSGI environment. | ||
start_response: The WSGI start_response callable. | ||
""" | ||
|
||
tracer = trace.tracer() | ||
path_info = environ["PATH_INFO"] or "/" | ||
|
||
with tracer.start_span(path_info) as span: | ||
self._add_request_attributes(span, environ) | ||
start_response = self._create_start_response(span, start_response) | ||
|
||
iterable = self.wsgi(environ, start_response) | ||
try: | ||
for yielded in iterable: | ||
yield yielded | ||
finally: | ||
if hasattr(iterable, 'close'): | ||
iterable.close() |
15 changes: 15 additions & 0 deletions
15
ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/version.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# 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. | ||
|
||
__version__ = "0.1.dev0" |
Empty file.
Oops, something went wrong.