We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Problem with using domain socket as bind address
**Describe your environment** 
The OT-wsgi library throws error if domain socket is used for the bind address.

**Steps to reproduce**
Here is a test program:

```
import web
from time import sleep
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleSpanProcessor,
)
from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware
from cheroot import wsgi

trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    SimpleSpanProcessor(ConsoleSpanExporter())
)

#tracer = trace.get_tracer(__name__)

urls = (
    '/', 'index'
)
class index:
    def GET(self):
        return "Hello, world!"

if __name__ == "__main__":
  app = web.application(urls, globals())
  func = app.wsgifunc()

  func = OpenTelemetryMiddleware(func)

  server = wsgi.WSGIServer("/tmp/lr.sock", func, server_name="localhost")
  server.start()
```

invocation:
```
(base) kamalh-mbp:~ kamalh$ echo -ne 'GET / HTTP/1.1\r\nHost: test.com\r\n\r\n' | nc -U /tmp/lr.sock
HTTP/1.1 500 Internal Server Error
Content-Length: 0
Content-Type: text/plain
```

Error from the program
```
(base) kamalh-mbp:opentelemetry kamalh$ python3 wsgi-lr.py
Overriding of current TracerProvider is not allowed
ValueError("invalid literal for int() with base 10: ''")
Traceback (most recent call last):
  File "/Users/kamalh/miniconda3/lib/python3.7/site-packages/cheroot/server.py", line 1287, in communicate
    req.respond()
  File "/Users/kamalh/miniconda3/lib/python3.7/site-packages/cheroot/server.py", line 1077, in respond
    self.server.gateway(self).respond()
  File "/Users/kamalh/miniconda3/lib/python3.7/site-packages/cheroot/wsgi.py", line 140, in respond
    response = self.req.server.wsgi_app(self.env, self.start_response)
  File "/Users/kamalh/miniconda3/lib/python3.7/site-packages/opentelemetry/instrumentation/wsgi/__init__.py", line 229, in __call__
    attributes=collect_request_attributes(environ),
  File "/Users/kamalh/miniconda3/lib/python3.7/site-packages/opentelemetry/instrumentation/wsgi/__init__.py", line 122, in collect_request_attributes
    result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})
ValueError: invalid literal for int() with base 10: ''
```

**What is the expected behavior?**
Expect to see the server returning normally as in TCP sockets.

**What is the actual behavior?**
Error message. Please see the paste above.

**Additional context**
Add any other context about the problem here.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py`
Content:
```
1 # Copyright The OpenTelemetry Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """
15 This library provides a WSGI middleware that can be used on any WSGI framework
16 (such as Django / Flask) to track requests timing through OpenTelemetry.
17 
18 Usage (Flask)
19 -------------
20 
21 .. code-block:: python
22 
23     from flask import Flask
24     from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware
25 
26     app = Flask(__name__)
27     app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)
28 
29     @app.route("/")
30     def hello():
31         return "Hello!"
32 
33     if __name__ == "__main__":
34         app.run(debug=True)
35 
36 
37 Usage (Django)
38 --------------
39 
40 Modify the application's ``wsgi.py`` file as shown below.
41 
42 .. code-block:: python
43 
44     import os
45     from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware
46     from django.core.wsgi import get_wsgi_application
47 
48     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
49 
50     application = get_wsgi_application()
51     application = OpenTelemetryMiddleware(application)
52 
53 API
54 ---
55 """
56 
57 import functools
58 import typing
59 import wsgiref.util as wsgiref_util
60 
61 from opentelemetry import context, trace
62 from opentelemetry.instrumentation.utils import http_status_to_status_code
63 from opentelemetry.instrumentation.wsgi.version import __version__
64 from opentelemetry.propagate import extract
65 from opentelemetry.propagators.textmap import Getter
66 from opentelemetry.semconv.trace import SpanAttributes
67 from opentelemetry.trace.status import Status, StatusCode
68 
69 _HTTP_VERSION_PREFIX = "HTTP/"
70 _CARRIER_KEY_PREFIX = "HTTP_"
71 _CARRIER_KEY_PREFIX_LEN = len(_CARRIER_KEY_PREFIX)
72 
73 
74 class WSGIGetter(Getter):
75     def get(
76         self, carrier: dict, key: str
77     ) -> typing.Optional[typing.List[str]]:
78         """Getter implementation to retrieve a HTTP header value from the
79              PEP3333-conforming WSGI environ
80 
81         Args:
82              carrier: WSGI environ object
83              key: header name in environ object
84          Returns:
85              A list with a single string with the header value if it exists,
86              else None.
87         """
88         environ_key = "HTTP_" + key.upper().replace("-", "_")
89         value = carrier.get(environ_key)
90         if value is not None:
91             return [value]
92         return None
93 
94     def keys(self, carrier):
95         return [
96             key[_CARRIER_KEY_PREFIX_LEN:].lower().replace("_", "-")
97             for key in carrier
98             if key.startswith(_CARRIER_KEY_PREFIX)
99         ]
100 
101 
102 wsgi_getter = WSGIGetter()
103 
104 
105 def setifnotnone(dic, key, value):
106     if value is not None:
107         dic[key] = value
108 
109 
110 def collect_request_attributes(environ):
111     """Collects HTTP request attributes from the PEP3333-conforming
112     WSGI environ and returns a dictionary to be used as span creation attributes."""
113 
114     result = {
115         SpanAttributes.HTTP_METHOD: environ.get("REQUEST_METHOD"),
116         SpanAttributes.HTTP_SERVER_NAME: environ.get("SERVER_NAME"),
117         SpanAttributes.HTTP_SCHEME: environ.get("wsgi.url_scheme"),
118     }
119 
120     host_port = environ.get("SERVER_PORT")
121     if host_port is not None:
122         result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})
123 
124     setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get("HTTP_HOST"))
125     target = environ.get("RAW_URI")
126     if target is None:  # Note: `"" or None is None`
127         target = environ.get("REQUEST_URI")
128     if target is not None:
129         result[SpanAttributes.HTTP_TARGET] = target
130     else:
131         result[SpanAttributes.HTTP_URL] = wsgiref_util.request_uri(environ)
132 
133     remote_addr = environ.get("REMOTE_ADDR")
134     if remote_addr:
135         result[SpanAttributes.NET_PEER_IP] = remote_addr
136     remote_host = environ.get("REMOTE_HOST")
137     if remote_host and remote_host != remote_addr:
138         result[SpanAttributes.NET_PEER_NAME] = remote_host
139 
140     user_agent = environ.get("HTTP_USER_AGENT")
141     if user_agent is not None and len(user_agent) > 0:
142         result[SpanAttributes.HTTP_USER_AGENT] = user_agent
143 
144     setifnotnone(
145         result, SpanAttributes.NET_PEER_PORT, environ.get("REMOTE_PORT")
146     )
147     flavor = environ.get("SERVER_PROTOCOL", "")
148     if flavor.upper().startswith(_HTTP_VERSION_PREFIX):
149         flavor = flavor[len(_HTTP_VERSION_PREFIX) :]
150     if flavor:
151         result[SpanAttributes.HTTP_FLAVOR] = flavor
152 
153     return result
154 
155 
156 def add_response_attributes(
157     span, start_response_status, response_headers
158 ):  # pylint: disable=unused-argument
159     """Adds HTTP response attributes to span using the arguments
160     passed to a PEP3333-conforming start_response callable."""
161     if not span.is_recording():
162         return
163     status_code, _ = start_response_status.split(" ", 1)
164 
165     try:
166         status_code = int(status_code)
167     except ValueError:
168         span.set_status(
169             Status(
170                 StatusCode.ERROR,
171                 "Non-integer HTTP status: " + repr(status_code),
172             )
173         )
174     else:
175         span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code)
176         span.set_status(Status(http_status_to_status_code(status_code)))
177 
178 
179 def get_default_span_name(environ):
180     """Default implementation for name_callback, returns HTTP {METHOD_NAME}."""
181     return "HTTP {}".format(environ.get("REQUEST_METHOD", "")).strip()
182 
183 
184 class OpenTelemetryMiddleware:
185     """The WSGI application middleware.
186 
187     This class is a PEP 3333 conforming WSGI middleware that starts and
188     annotates spans for any requests it is invoked with.
189 
190     Args:
191         wsgi: The WSGI application callable to forward requests to.
192         request_hook: Optional callback which is called with the server span and WSGI
193                       environ object for every incoming request.
194         response_hook: Optional callback which is called with the server span,
195                        WSGI environ, status_code and response_headers for every
196                        incoming request.
197         tracer_provider: Optional tracer provider to use. If omitted the current
198                          globally configured one is used.
199     """
200 
201     def __init__(
202         self, wsgi, request_hook=None, response_hook=None, tracer_provider=None
203     ):
204         self.wsgi = wsgi
205         self.tracer = trace.get_tracer(__name__, __version__, tracer_provider)
206         self.request_hook = request_hook
207         self.response_hook = response_hook
208 
209     @staticmethod
210     def _create_start_response(span, start_response, response_hook):
211         @functools.wraps(start_response)
212         def _start_response(status, response_headers, *args, **kwargs):
213             add_response_attributes(span, status, response_headers)
214             if response_hook:
215                 response_hook(status, response_headers)
216             return start_response(status, response_headers, *args, **kwargs)
217 
218         return _start_response
219 
220     def __call__(self, environ, start_response):
221         """The WSGI application
222 
223         Args:
224             environ: A WSGI environment.
225             start_response: The WSGI start_response callable.
226         """
227 
228         token = context.attach(extract(environ, getter=wsgi_getter))
229 
230         span = self.tracer.start_span(
231             get_default_span_name(environ),
232             kind=trace.SpanKind.SERVER,
233             attributes=collect_request_attributes(environ),
234         )
235 
236         if self.request_hook:
237             self.request_hook(span, environ)
238 
239         response_hook = self.response_hook
240         if response_hook:
241             response_hook = functools.partial(response_hook, span, environ)
242 
243         try:
244             with trace.use_span(span):
245                 start_response = self._create_start_response(
246                     span, start_response, response_hook
247                 )
248                 iterable = self.wsgi(environ, start_response)
249                 return _end_span_after_iterating(
250                     iterable, span, self.tracer, token
251                 )
252         except Exception as ex:
253             if span.is_recording():
254                 span.set_status(Status(StatusCode.ERROR, str(ex)))
255             span.end()
256             context.detach(token)
257             raise
258 
259 
260 # Put this in a subfunction to not delay the call to the wrapped
261 # WSGI application (instrumentation should change the application
262 # behavior as little as possible).
263 def _end_span_after_iterating(iterable, span, tracer, token):
264     try:
265         with trace.use_span(span):
266             for yielded in iterable:
267                 yield yielded
268     finally:
269         close = getattr(iterable, "close", None)
270         if close:
271             close()
272         span.end()
273         context.detach(token)
274 
275 
276 # TODO: inherit from opentelemetry.instrumentation.propagators.Setter
277 
278 
279 class ResponsePropagationSetter:
280     def set(self, carrier, key, value):  # pylint: disable=no-self-use
281         carrier.append((key, value))
282 
283 
284 default_response_propagation_setter = ResponsePropagationSetter()
285
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py
--- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py
@@ -118,7 +118,7 @@
     }
 
     host_port = environ.get("SERVER_PORT")
-    if host_port is not None:
+    if host_port is not None and not host_port == "":
         result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})
 
     setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get("HTTP_HOST"))

{"golden_diff": "diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py\n--- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py\n+++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py\n@@ -118,7 +118,7 @@\n     }\n \n     host_port = environ.get(\"SERVER_PORT\")\n-    if host_port is not None:\n+    if host_port is not None and not host_port == \"\":\n         result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})\n \n     setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get(\"HTTP_HOST\"))\n", "issue": "Problem with using domain socket as bind address\n**Describe your environment** \r\nThe OT-wsgi library throws error if domain socket is used for the bind address.\r\n\r\n**Steps to reproduce**\r\nHere is a test program:\r\n\r\n```\r\nimport web\r\nfrom time import sleep\r\nfrom opentelemetry import trace\r\nfrom opentelemetry.sdk.trace import TracerProvider\r\nfrom opentelemetry.sdk.trace.export import (\r\n    ConsoleSpanExporter,\r\n    SimpleSpanProcessor,\r\n)\r\nfrom opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware\r\nfrom cheroot import wsgi\r\n\r\ntrace.set_tracer_provider(TracerProvider())\r\ntrace.get_tracer_provider().add_span_processor(\r\n    SimpleSpanProcessor(ConsoleSpanExporter())\r\n)\r\n\r\n#tracer = trace.get_tracer(__name__)\r\n\r\nurls = (\r\n    '/', 'index'\r\n)\r\nclass index:\r\n    def GET(self):\r\n        return \"Hello, world!\"\r\n\r\nif __name__ == \"__main__\":\r\n  app = web.application(urls, globals())\r\n  func = app.wsgifunc()\r\n\r\n  func = OpenTelemetryMiddleware(func)\r\n\r\n  server = wsgi.WSGIServer(\"/tmp/lr.sock\", func, server_name=\"localhost\")\r\n  server.start()\r\n```\r\n\r\ninvocation:\r\n```\r\n(base) kamalh-mbp:~ kamalh$ echo -ne 'GET / HTTP/1.1\\r\\nHost: test.com\\r\\n\\r\\n' | nc -U /tmp/lr.sock\r\nHTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\nContent-Type: text/plain\r\n```\r\n\r\nError from the program\r\n```\r\n(base) kamalh-mbp:opentelemetry kamalh$ python3 wsgi-lr.py\r\nOverriding of current TracerProvider is not allowed\r\nValueError(\"invalid literal for int() with base 10: ''\")\r\nTraceback (most recent call last):\r\n  File \"/Users/kamalh/miniconda3/lib/python3.7/site-packages/cheroot/server.py\", line 1287, in communicate\r\n    req.respond()\r\n  File \"/Users/kamalh/miniconda3/lib/python3.7/site-packages/cheroot/server.py\", line 1077, in respond\r\n    self.server.gateway(self).respond()\r\n  File \"/Users/kamalh/miniconda3/lib/python3.7/site-packages/cheroot/wsgi.py\", line 140, in respond\r\n    response = self.req.server.wsgi_app(self.env, self.start_response)\r\n  File \"/Users/kamalh/miniconda3/lib/python3.7/site-packages/opentelemetry/instrumentation/wsgi/__init__.py\", line 229, in __call__\r\n    attributes=collect_request_attributes(environ),\r\n  File \"/Users/kamalh/miniconda3/lib/python3.7/site-packages/opentelemetry/instrumentation/wsgi/__init__.py\", line 122, in collect_request_attributes\r\n    result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})\r\nValueError: invalid literal for int() with base 10: ''\r\n```\r\n\r\n**What is the expected behavior?**\r\nExpect to see the server returning normally as in TCP sockets.\r\n\r\n**What is the actual behavior?**\r\nError message. Please see the paste above.\r\n\r\n**Additional context**\r\nAdd any other context about the problem here.\r\n\n", "before_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis library provides a WSGI middleware that can be used on any WSGI framework\n(such as Django / Flask) to track requests timing through OpenTelemetry.\n\nUsage (Flask)\n-------------\n\n.. code-block:: python\n\n    from flask import Flask\n    from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware\n\n    app = Flask(__name__)\n    app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)\n\n    @app.route(\"/\")\n    def hello():\n        return \"Hello!\"\n\n    if __name__ == \"__main__\":\n        app.run(debug=True)\n\n\nUsage (Django)\n--------------\n\nModify the application's ``wsgi.py`` file as shown below.\n\n.. code-block:: python\n\n    import os\n    from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware\n    from django.core.wsgi import get_wsgi_application\n\n    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')\n\n    application = get_wsgi_application()\n    application = OpenTelemetryMiddleware(application)\n\nAPI\n---\n\"\"\"\n\nimport functools\nimport typing\nimport wsgiref.util as wsgiref_util\n\nfrom opentelemetry import context, trace\nfrom opentelemetry.instrumentation.utils import http_status_to_status_code\nfrom opentelemetry.instrumentation.wsgi.version import __version__\nfrom opentelemetry.propagate import extract\nfrom opentelemetry.propagators.textmap import Getter\nfrom opentelemetry.semconv.trace import SpanAttributes\nfrom opentelemetry.trace.status import Status, StatusCode\n\n_HTTP_VERSION_PREFIX = \"HTTP/\"\n_CARRIER_KEY_PREFIX = \"HTTP_\"\n_CARRIER_KEY_PREFIX_LEN = len(_CARRIER_KEY_PREFIX)\n\n\nclass WSGIGetter(Getter):\n    def get(\n        self, carrier: dict, key: str\n    ) -> typing.Optional[typing.List[str]]:\n        \"\"\"Getter implementation to retrieve a HTTP header value from the\n             PEP3333-conforming WSGI environ\n\n        Args:\n             carrier: WSGI environ object\n             key: header name in environ object\n         Returns:\n             A list with a single string with the header value if it exists,\n             else None.\n        \"\"\"\n        environ_key = \"HTTP_\" + key.upper().replace(\"-\", \"_\")\n        value = carrier.get(environ_key)\n        if value is not None:\n            return [value]\n        return None\n\n    def keys(self, carrier):\n        return [\n            key[_CARRIER_KEY_PREFIX_LEN:].lower().replace(\"_\", \"-\")\n            for key in carrier\n            if key.startswith(_CARRIER_KEY_PREFIX)\n        ]\n\n\nwsgi_getter = WSGIGetter()\n\n\ndef setifnotnone(dic, key, value):\n    if value is not None:\n        dic[key] = value\n\n\ndef collect_request_attributes(environ):\n    \"\"\"Collects HTTP request attributes from the PEP3333-conforming\n    WSGI environ and returns a dictionary to be used as span creation attributes.\"\"\"\n\n    result = {\n        SpanAttributes.HTTP_METHOD: environ.get(\"REQUEST_METHOD\"),\n        SpanAttributes.HTTP_SERVER_NAME: environ.get(\"SERVER_NAME\"),\n        SpanAttributes.HTTP_SCHEME: environ.get(\"wsgi.url_scheme\"),\n    }\n\n    host_port = environ.get(\"SERVER_PORT\")\n    if host_port is not None:\n        result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})\n\n    setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get(\"HTTP_HOST\"))\n    target = environ.get(\"RAW_URI\")\n    if target is None:  # Note: `\"\" or None is None`\n        target = environ.get(\"REQUEST_URI\")\n    if target is not None:\n        result[SpanAttributes.HTTP_TARGET] = target\n    else:\n        result[SpanAttributes.HTTP_URL] = wsgiref_util.request_uri(environ)\n\n    remote_addr = environ.get(\"REMOTE_ADDR\")\n    if remote_addr:\n        result[SpanAttributes.NET_PEER_IP] = remote_addr\n    remote_host = environ.get(\"REMOTE_HOST\")\n    if remote_host and remote_host != remote_addr:\n        result[SpanAttributes.NET_PEER_NAME] = remote_host\n\n    user_agent = environ.get(\"HTTP_USER_AGENT\")\n    if user_agent is not None and len(user_agent) > 0:\n        result[SpanAttributes.HTTP_USER_AGENT] = user_agent\n\n    setifnotnone(\n        result, SpanAttributes.NET_PEER_PORT, environ.get(\"REMOTE_PORT\")\n    )\n    flavor = environ.get(\"SERVER_PROTOCOL\", \"\")\n    if flavor.upper().startswith(_HTTP_VERSION_PREFIX):\n        flavor = flavor[len(_HTTP_VERSION_PREFIX) :]\n    if flavor:\n        result[SpanAttributes.HTTP_FLAVOR] = flavor\n\n    return result\n\n\ndef add_response_attributes(\n    span, start_response_status, response_headers\n):  # pylint: disable=unused-argument\n    \"\"\"Adds HTTP response attributes to span using the arguments\n    passed to a PEP3333-conforming start_response callable.\"\"\"\n    if not span.is_recording():\n        return\n    status_code, _ = start_response_status.split(\" \", 1)\n\n    try:\n        status_code = int(status_code)\n    except ValueError:\n        span.set_status(\n            Status(\n                StatusCode.ERROR,\n                \"Non-integer HTTP status: \" + repr(status_code),\n            )\n        )\n    else:\n        span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code)\n        span.set_status(Status(http_status_to_status_code(status_code)))\n\n\ndef get_default_span_name(environ):\n    \"\"\"Default implementation for name_callback, returns HTTP {METHOD_NAME}.\"\"\"\n    return \"HTTP {}\".format(environ.get(\"REQUEST_METHOD\", \"\")).strip()\n\n\nclass OpenTelemetryMiddleware:\n    \"\"\"The WSGI application middleware.\n\n    This class is a PEP 3333 conforming WSGI middleware that starts and\n    annotates spans for any requests it is invoked with.\n\n    Args:\n        wsgi: The WSGI application callable to forward requests to.\n        request_hook: Optional callback which is called with the server span and WSGI\n                      environ object for every incoming request.\n        response_hook: Optional callback which is called with the server span,\n                       WSGI environ, status_code and response_headers for every\n                       incoming request.\n        tracer_provider: Optional tracer provider to use. If omitted the current\n                         globally configured one is used.\n    \"\"\"\n\n    def __init__(\n        self, wsgi, request_hook=None, response_hook=None, tracer_provider=None\n    ):\n        self.wsgi = wsgi\n        self.tracer = trace.get_tracer(__name__, __version__, tracer_provider)\n        self.request_hook = request_hook\n        self.response_hook = response_hook\n\n    @staticmethod\n    def _create_start_response(span, start_response, response_hook):\n        @functools.wraps(start_response)\n        def _start_response(status, response_headers, *args, **kwargs):\n            add_response_attributes(span, status, response_headers)\n            if response_hook:\n                response_hook(status, response_headers)\n            return start_response(status, response_headers, *args, **kwargs)\n\n        return _start_response\n\n    def __call__(self, environ, start_response):\n        \"\"\"The WSGI application\n\n        Args:\n            environ: A WSGI environment.\n            start_response: The WSGI start_response callable.\n        \"\"\"\n\n        token = context.attach(extract(environ, getter=wsgi_getter))\n\n        span = self.tracer.start_span(\n            get_default_span_name(environ),\n            kind=trace.SpanKind.SERVER,\n            attributes=collect_request_attributes(environ),\n        )\n\n        if self.request_hook:\n            self.request_hook(span, environ)\n\n        response_hook = self.response_hook\n        if response_hook:\n            response_hook = functools.partial(response_hook, span, environ)\n\n        try:\n            with trace.use_span(span):\n                start_response = self._create_start_response(\n                    span, start_response, response_hook\n                )\n                iterable = self.wsgi(environ, start_response)\n                return _end_span_after_iterating(\n                    iterable, span, self.tracer, token\n                )\n        except Exception as ex:\n            if span.is_recording():\n                span.set_status(Status(StatusCode.ERROR, str(ex)))\n            span.end()\n            context.detach(token)\n            raise\n\n\n# Put this in a subfunction to not delay the call to the wrapped\n# WSGI application (instrumentation should change the application\n# behavior as little as possible).\ndef _end_span_after_iterating(iterable, span, tracer, token):\n    try:\n        with trace.use_span(span):\n            for yielded in iterable:\n                yield yielded\n    finally:\n        close = getattr(iterable, \"close\", None)\n        if close:\n            close()\n        span.end()\n        context.detach(token)\n\n\n# TODO: inherit from opentelemetry.instrumentation.propagators.Setter\n\n\nclass ResponsePropagationSetter:\n    def set(self, carrier, key, value):  # pylint: disable=no-self-use\n        carrier.append((key, value))\n\n\ndefault_response_propagation_setter = ResponsePropagationSetter()\n", "path": "instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py"}], "after_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis library provides a WSGI middleware that can be used on any WSGI framework\n(such as Django / Flask) to track requests timing through OpenTelemetry.\n\nUsage (Flask)\n-------------\n\n.. code-block:: python\n\n    from flask import Flask\n    from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware\n\n    app = Flask(__name__)\n    app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)\n\n    @app.route(\"/\")\n    def hello():\n        return \"Hello!\"\n\n    if __name__ == \"__main__\":\n        app.run(debug=True)\n\n\nUsage (Django)\n--------------\n\nModify the application's ``wsgi.py`` file as shown below.\n\n.. code-block:: python\n\n    import os\n    from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware\n    from django.core.wsgi import get_wsgi_application\n\n    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')\n\n    application = get_wsgi_application()\n    application = OpenTelemetryMiddleware(application)\n\nAPI\n---\n\"\"\"\n\nimport functools\nimport typing\nimport wsgiref.util as wsgiref_util\n\nfrom opentelemetry import context, trace\nfrom opentelemetry.instrumentation.utils import http_status_to_status_code\nfrom opentelemetry.instrumentation.wsgi.version import __version__\nfrom opentelemetry.propagate import extract\nfrom opentelemetry.propagators.textmap import Getter\nfrom opentelemetry.semconv.trace import SpanAttributes\nfrom opentelemetry.trace.status import Status, StatusCode\n\n_HTTP_VERSION_PREFIX = \"HTTP/\"\n_CARRIER_KEY_PREFIX = \"HTTP_\"\n_CARRIER_KEY_PREFIX_LEN = len(_CARRIER_KEY_PREFIX)\n\n\nclass WSGIGetter(Getter):\n    def get(\n        self, carrier: dict, key: str\n    ) -> typing.Optional[typing.List[str]]:\n        \"\"\"Getter implementation to retrieve a HTTP header value from the\n             PEP3333-conforming WSGI environ\n\n        Args:\n             carrier: WSGI environ object\n             key: header name in environ object\n         Returns:\n             A list with a single string with the header value if it exists,\n             else None.\n        \"\"\"\n        environ_key = \"HTTP_\" + key.upper().replace(\"-\", \"_\")\n        value = carrier.get(environ_key)\n        if value is not None:\n            return [value]\n        return None\n\n    def keys(self, carrier):\n        return [\n            key[_CARRIER_KEY_PREFIX_LEN:].lower().replace(\"_\", \"-\")\n            for key in carrier\n            if key.startswith(_CARRIER_KEY_PREFIX)\n        ]\n\n\nwsgi_getter = WSGIGetter()\n\n\ndef setifnotnone(dic, key, value):\n    if value is not None:\n        dic[key] = value\n\n\ndef collect_request_attributes(environ):\n    \"\"\"Collects HTTP request attributes from the PEP3333-conforming\n    WSGI environ and returns a dictionary to be used as span creation attributes.\"\"\"\n\n    result = {\n        SpanAttributes.HTTP_METHOD: environ.get(\"REQUEST_METHOD\"),\n        SpanAttributes.HTTP_SERVER_NAME: environ.get(\"SERVER_NAME\"),\n        SpanAttributes.HTTP_SCHEME: environ.get(\"wsgi.url_scheme\"),\n    }\n\n    host_port = environ.get(\"SERVER_PORT\")\n    if host_port is not None and not host_port == \"\":\n        result.update({SpanAttributes.NET_HOST_PORT: int(host_port)})\n\n    setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get(\"HTTP_HOST\"))\n    target = environ.get(\"RAW_URI\")\n    if target is None:  # Note: `\"\" or None is None`\n        target = environ.get(\"REQUEST_URI\")\n    if target is not None:\n        result[SpanAttributes.HTTP_TARGET] = target\n    else:\n        result[SpanAttributes.HTTP_URL] = wsgiref_util.request_uri(environ)\n\n    remote_addr = environ.get(\"REMOTE_ADDR\")\n    if remote_addr:\n        result[SpanAttributes.NET_PEER_IP] = remote_addr\n    remote_host = environ.get(\"REMOTE_HOST\")\n    if remote_host and remote_host != remote_addr:\n        result[SpanAttributes.NET_PEER_NAME] = remote_host\n\n    user_agent = environ.get(\"HTTP_USER_AGENT\")\n    if user_agent is not None and len(user_agent) > 0:\n        result[SpanAttributes.HTTP_USER_AGENT] = user_agent\n\n    setifnotnone(\n        result, SpanAttributes.NET_PEER_PORT, environ.get(\"REMOTE_PORT\")\n    )\n    flavor = environ.get(\"SERVER_PROTOCOL\", \"\")\n    if flavor.upper().startswith(_HTTP_VERSION_PREFIX):\n        flavor = flavor[len(_HTTP_VERSION_PREFIX) :]\n    if flavor:\n        result[SpanAttributes.HTTP_FLAVOR] = flavor\n\n    return result\n\n\ndef add_response_attributes(\n    span, start_response_status, response_headers\n):  # pylint: disable=unused-argument\n    \"\"\"Adds HTTP response attributes to span using the arguments\n    passed to a PEP3333-conforming start_response callable.\"\"\"\n    if not span.is_recording():\n        return\n    status_code, _ = start_response_status.split(\" \", 1)\n\n    try:\n        status_code = int(status_code)\n    except ValueError:\n        span.set_status(\n            Status(\n                StatusCode.ERROR,\n                \"Non-integer HTTP status: \" + repr(status_code),\n            )\n        )\n    else:\n        span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code)\n        span.set_status(Status(http_status_to_status_code(status_code)))\n\n\ndef get_default_span_name(environ):\n    \"\"\"Default implementation for name_callback, returns HTTP {METHOD_NAME}.\"\"\"\n    return \"HTTP {}\".format(environ.get(\"REQUEST_METHOD\", \"\")).strip()\n\n\nclass OpenTelemetryMiddleware:\n    \"\"\"The WSGI application middleware.\n\n    This class is a PEP 3333 conforming WSGI middleware that starts and\n    annotates spans for any requests it is invoked with.\n\n    Args:\n        wsgi: The WSGI application callable to forward requests to.\n        request_hook: Optional callback which is called with the server span and WSGI\n                      environ object for every incoming request.\n        response_hook: Optional callback which is called with the server span,\n                       WSGI environ, status_code and response_headers for every\n                       incoming request.\n        tracer_provider: Optional tracer provider to use. If omitted the current\n                         globally configured one is used.\n    \"\"\"\n\n    def __init__(\n        self, wsgi, request_hook=None, response_hook=None, tracer_provider=None\n    ):\n        self.wsgi = wsgi\n        self.tracer = trace.get_tracer(__name__, __version__, tracer_provider)\n        self.request_hook = request_hook\n        self.response_hook = response_hook\n\n    @staticmethod\n    def _create_start_response(span, start_response, response_hook):\n        @functools.wraps(start_response)\n        def _start_response(status, response_headers, *args, **kwargs):\n            add_response_attributes(span, status, response_headers)\n            if response_hook:\n                response_hook(status, response_headers)\n            return start_response(status, response_headers, *args, **kwargs)\n\n        return _start_response\n\n    def __call__(self, environ, start_response):\n        \"\"\"The WSGI application\n\n        Args:\n            environ: A WSGI environment.\n            start_response: The WSGI start_response callable.\n        \"\"\"\n\n        token = context.attach(extract(environ, getter=wsgi_getter))\n\n        span = self.tracer.start_span(\n            get_default_span_name(environ),\n            kind=trace.SpanKind.SERVER,\n            attributes=collect_request_attributes(environ),\n        )\n\n        if self.request_hook:\n            self.request_hook(span, environ)\n\n        response_hook = self.response_hook\n        if response_hook:\n            response_hook = functools.partial(response_hook, span, environ)\n\n        try:\n            with trace.use_span(span):\n                start_response = self._create_start_response(\n                    span, start_response, response_hook\n                )\n                iterable = self.wsgi(environ, start_response)\n                return _end_span_after_iterating(\n                    iterable, span, self.tracer, token\n                )\n        except Exception as ex:\n            if span.is_recording():\n                span.set_status(Status(StatusCode.ERROR, str(ex)))\n            span.end()\n            context.detach(token)\n            raise\n\n\n# Put this in a subfunction to not delay the call to the wrapped\n# WSGI application (instrumentation should change the application\n# behavior as little as possible).\ndef _end_span_after_iterating(iterable, span, tracer, token):\n    try:\n        with trace.use_span(span):\n            for yielded in iterable:\n                yield yielded\n    finally:\n        close = getattr(iterable, \"close\", None)\n        if close:\n            close()\n        span.end()\n        context.detach(token)\n\n\n# TODO: inherit from opentelemetry.instrumentation.propagators.Setter\n\n\nclass ResponsePropagationSetter:\n    def set(self, carrier, key, value):  # pylint: disable=no-self-use\n        carrier.append((key, value))\n\n\ndefault_response_propagation_setter = ResponsePropagationSetter()\n", "path": "instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py"}]}