Skip to content

Commit e552f6c

Browse files
Merge branch 'main' into sqlalchemy-db-statement-comment-opt-in
2 parents 0709012 + 95f14cd commit e552f6c

File tree

4 files changed

+27
-14
lines changed

4 files changed

+27
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2323
([#3133](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3133))
2424
- `opentelemetry-instrumentation-falcon` add support version to v4
2525
([#3086](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3086))
26+
- `opentelemetry-instrumentation-wsgi` always record span status code to have it available in metrics
27+
([#3148](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3148))
2628
- add support to Python 3.13
2729
([#3134](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3134))
2830

instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,11 +480,7 @@ def add_response_attributes(
480480
"""Adds HTTP response attributes to span using the arguments
481481
passed to a PEP3333-conforming start_response callable.
482482
"""
483-
if not span.is_recording():
484-
return
485483
status_code_str, _ = start_response_status.split(" ", 1)
486-
487-
status_code = 0
488484
try:
489485
status_code = int(status_code_str)
490486
except ValueError:

instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,19 @@ def test_response_attributes(self):
779779
self.span.set_attribute.assert_has_calls(expected, any_order=True)
780780
self.span.set_attribute.assert_has_calls(expected_new, any_order=True)
781781

782+
def test_response_attributes_noop(self):
783+
mock_span = mock.Mock()
784+
mock_span.is_recording.return_value = False
785+
786+
attrs = {}
787+
otel_wsgi.add_response_attributes(
788+
mock_span, "404 Not Found", {}, duration_attrs=attrs
789+
)
790+
791+
self.assertEqual(mock_span.set_attribute.call_count, 0)
792+
self.assertEqual(mock_span.is_recording.call_count, 2)
793+
self.assertEqual(attrs[SpanAttributes.HTTP_STATUS_CODE], 404)
794+
782795
def test_credential_removal(self):
783796
self.environ["HTTP_HOST"] = "username:password@mock"
784797
self.environ["PATH_INFO"] = "/status/200"

opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
1517
import urllib.parse
1618
from contextlib import contextmanager
1719
from importlib import import_module
1820
from re import escape, sub
19-
from typing import Dict, Iterable, Sequence, Union
21+
from typing import Any, Dict, Generator, Sequence
2022

2123
from wrapt import ObjectProxy
2224

@@ -44,9 +46,9 @@
4446

4547

4648
def extract_attributes_from_object(
47-
obj: any, attributes: Sequence[str], existing: Dict[str, str] = None
49+
obj: Any, attributes: Sequence[str], existing: Dict[str, str] | None = None
4850
) -> Dict[str, str]:
49-
extracted = {}
51+
extracted: dict[str, str] = {}
5052
if existing:
5153
extracted.update(existing)
5254
for attr in attributes:
@@ -81,7 +83,7 @@ def http_status_to_status_code(
8183
return StatusCode.ERROR
8284

8385

84-
def unwrap(obj: Union[object, str], attr: str):
86+
def unwrap(obj: object, attr: str):
8587
"""Given a function that was wrapped by wrapt.wrap_function_wrapper, unwrap it
8688
8789
The object containing the function to unwrap may be passed as dotted module path string.
@@ -152,7 +154,7 @@ def _start_internal_or_server_span(
152154
return span, token
153155

154156

155-
def _url_quote(s) -> str: # pylint: disable=invalid-name
157+
def _url_quote(s: Any) -> str: # pylint: disable=invalid-name
156158
if not isinstance(s, (str, bytes)):
157159
return s
158160
quoted = urllib.parse.quote(s)
@@ -163,13 +165,13 @@ def _url_quote(s) -> str: # pylint: disable=invalid-name
163165
return quoted.replace("%", "%%")
164166

165167

166-
def _get_opentelemetry_values() -> dict:
168+
def _get_opentelemetry_values() -> dict[str, Any]:
167169
"""
168170
Return the OpenTelemetry Trace and Span IDs if Span ID is set in the
169171
OpenTelemetry execution context.
170172
"""
171173
# Insert the W3C TraceContext generated
172-
_headers = {}
174+
_headers: dict[str, Any] = {}
173175
propagator.inject(_headers)
174176
return _headers
175177

@@ -196,7 +198,7 @@ def is_http_instrumentation_enabled() -> bool:
196198

197199

198200
@contextmanager
199-
def _suppress_instrumentation(*keys: str) -> Iterable[None]:
201+
def _suppress_instrumentation(*keys: str) -> Generator[None]:
200202
"""Suppress instrumentation within the context."""
201203
ctx = context.get_current()
202204
for key in keys:
@@ -209,7 +211,7 @@ def _suppress_instrumentation(*keys: str) -> Iterable[None]:
209211

210212

211213
@contextmanager
212-
def suppress_instrumentation() -> Iterable[None]:
214+
def suppress_instrumentation() -> Generator[None]:
213215
"""Suppress instrumentation within the context."""
214216
with _suppress_instrumentation(
215217
_SUPPRESS_INSTRUMENTATION_KEY, _SUPPRESS_INSTRUMENTATION_KEY_PLAIN
@@ -218,7 +220,7 @@ def suppress_instrumentation() -> Iterable[None]:
218220

219221

220222
@contextmanager
221-
def suppress_http_instrumentation() -> Iterable[None]:
223+
def suppress_http_instrumentation() -> Generator[None]:
222224
"""Suppress instrumentation within the context."""
223225
with _suppress_instrumentation(_SUPPRESS_HTTP_INSTRUMENTATION_KEY):
224226
yield

0 commit comments

Comments
 (0)