Skip to content

Commit 4014879

Browse files
srikanthccvaabmass
authored andcommitted
Remove http.status_text from span attributes (open-telemetry#406)
Update instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py Update .github/workflows/test.yml Co-authored-by: Aaron Abbott <[email protected]>
1 parent 1ee8924 commit 4014879

File tree

21 files changed

+112
-57
lines changed

21 files changed

+112
-57
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,6 @@ jobs:
9898
uses: actions/cache@v2
9999
with:
100100
path: .tox
101-
key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }}
101+
key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }}
102102
- name: run tox
103103
run: tox -e ${{ matrix.tox-environment }}

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
([#299](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/299))
2222
- `opentelemetry-instrumenation-django` now supports request and response hooks.
2323
([#407](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/407))
24+
- `opentelemetry-instrumentation-falcon` FalconInstrumentor now supports request/response hooks.
25+
([#415](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/415))
26+
27+
### Removed
28+
- Remove `http.status_text` from span attributes
29+
([#406](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/406))
2430

2531
## [0.19b0](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.19b0) - 2021-03-26
2632

docs-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ boto~=2.0
2525
botocore~=1.0
2626
celery>=4.0
2727
flask~=1.0
28+
falcon~=2.0
2829
grpcio~=1.27
2930
mysql-connector-python~=8.0
3031
pymongo~=3.1
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
OpenTelemetry Falcon Instrumentation
2+
====================================
3+
4+
.. automodule:: opentelemetry.instrumentation.falcon
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

-3
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,6 @@ async def on_request_end(
198198
trace_config_ctx.span.set_attribute(
199199
"http.status_code", params.response.status
200200
)
201-
trace_config_ctx.span.set_attribute(
202-
"http.status_text", params.response.reason
203-
)
204201
_end_trace(trace_config_ctx)
205202

206203
async def on_request_exception(

instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py

-4
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ def test_status_codes(self):
134134
host, port
135135
),
136136
"http.status_code": int(status_code),
137-
"http.status_text": status_code.phrase,
138137
},
139138
)
140139
]
@@ -191,7 +190,6 @@ def test_span_name_option(self):
191190
host, port, path
192191
),
193192
"http.status_code": int(HTTPStatus.OK),
194-
"http.status_text": HTTPStatus.OK.phrase,
195193
},
196194
)
197195
]
@@ -222,7 +220,6 @@ def strip_query_params(url: yarl.URL) -> str:
222220
host, port
223221
),
224222
"http.status_code": int(HTTPStatus.OK),
225-
"http.status_text": HTTPStatus.OK.phrase,
226223
},
227224
)
228225
]
@@ -361,7 +358,6 @@ def test_instrument(self):
361358
span.attributes["http.url"],
362359
)
363360
self.assertEqual(200, span.attributes["http.status_code"])
364-
self.assertEqual("OK", span.attributes["http.status_text"])
365361

366362
def test_instrument_with_existing_trace_config(self):
367363
trace_config = aiohttp.TraceConfig()

instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py

-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ def test_templated_route_get(self):
121121
)
122122
self.assertEqual(span.attributes["http.scheme"], "http")
123123
self.assertEqual(span.attributes["http.status_code"], 200)
124-
self.assertEqual(span.attributes["http.status_text"], "OK")
125124

126125
def test_traced_get(self):
127126
Client().get("/traced/")
@@ -143,7 +142,6 @@ def test_traced_get(self):
143142
self.assertEqual(span.attributes["http.route"], "^traced/")
144143
self.assertEqual(span.attributes["http.scheme"], "http")
145144
self.assertEqual(span.attributes["http.status_code"], 200)
146-
self.assertEqual(span.attributes["http.status_text"], "OK")
147145

148146
def test_not_recording(self):
149147
mock_tracer = Mock()
@@ -178,7 +176,6 @@ def test_traced_post(self):
178176
self.assertEqual(span.attributes["http.route"], "^traced/")
179177
self.assertEqual(span.attributes["http.scheme"], "http")
180178
self.assertEqual(span.attributes["http.status_code"], 200)
181-
self.assertEqual(span.attributes["http.status_text"], "OK")
182179

183180
def test_error(self):
184181
with self.assertRaises(ValueError):

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

+69-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,36 @@
2121
* The ``falcon.resource`` Span attribute is set so the matched resource.
2222
* Error from Falcon resources are properly caught and recorded.
2323
24+
Configuration
25+
-------------
26+
27+
Exclude lists
28+
*************
29+
To exclude certain URLs from being tracked, set the environment variable ``OTEL_PYTHON_FALCON_EXCLUDED_URLS`` with comma delimited regexes representing which URLs to exclude.
30+
31+
For example,
32+
33+
::
34+
35+
export OTEL_PYTHON_FALCON_EXCLUDED_URLS="client/.*/info,healthcheck"
36+
37+
will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
38+
39+
Request attributes
40+
********************
41+
To extract certain attributes from Falcon's request object and use them as span attributes, set the environment variable ``OTEL_PYTHON_FALCON_TRACED_REQUEST_ATTRS`` to a comma
42+
delimited list of request attribute names.
43+
44+
For example,
45+
46+
::
47+
48+
export OTEL_PYTHON_FALCON_TRACED_REQUEST_ATTRS='query_string,uri_template'
49+
50+
will extract query_string and uri_template attributes from every traced request and add them as span attritbues.
51+
52+
Falcon Request object reference: https://falcon.readthedocs.io/en/stable/api/request_and_response.html#id1
53+
2454
Usage
2555
-----
2656
@@ -39,10 +69,27 @@ def on_get(self, req, resp):
3969
4070
app.add_route('/hello', HelloWorldResource())
4171
72+
73+
Request and Response hooks
74+
***************************
75+
The instrumentation supports specifying request and response hooks. These are functions that get called back by the instrumentation right after a Span is created for a request
76+
and right before the span is finished while processing a response. The hooks can be configured as follows:
77+
78+
::
79+
80+
def request_hook(span, req):
81+
pass
82+
83+
def response_hook(span, req, resp):
84+
pass
85+
86+
FalconInstrumentation().instrument(request_hook=request_hook, response_hook=response_hook)
87+
4288
API
4389
---
4490
"""
4591

92+
from functools import partial
4693
from logging import getLogger
4794
from sys import exc_info
4895

@@ -83,21 +130,25 @@ class FalconInstrumentor(BaseInstrumentor):
83130

84131
def _instrument(self, **kwargs):
85132
self._original_falcon_api = falcon.API
86-
falcon.API = _InstrumentedFalconAPI
133+
falcon.API = partial(_InstrumentedFalconAPI, **kwargs)
87134

88135
def _uninstrument(self, **kwargs):
89136
falcon.API = self._original_falcon_api
90137

91138

92139
class _InstrumentedFalconAPI(falcon.API):
93140
def __init__(self, *args, **kwargs):
141+
# inject trace middleware
94142
middlewares = kwargs.pop("middleware", [])
95143
if not isinstance(middlewares, (list, tuple)):
96144
middlewares = [middlewares]
97145

98146
self._tracer = trace.get_tracer(__name__, __version__)
99147
trace_middleware = _TraceMiddleware(
100-
self._tracer, kwargs.get("traced_request_attributes")
148+
self._tracer,
149+
kwargs.pop("traced_request_attributes", None),
150+
kwargs.pop("request_hook", None),
151+
kwargs.pop("response_hook", None),
101152
)
102153
middlewares.insert(0, trace_middleware)
103154
kwargs["middleware"] = middlewares
@@ -148,12 +199,23 @@ def _start_response(status, response_headers, *args, **kwargs):
148199
class _TraceMiddleware:
149200
# pylint:disable=R0201,W0613
150201

151-
def __init__(self, tracer=None, traced_request_attrs=None):
202+
def __init__(
203+
self,
204+
tracer=None,
205+
traced_request_attrs=None,
206+
request_hook=None,
207+
response_hook=None,
208+
):
152209
self.tracer = tracer
153210
self._traced_request_attrs = _traced_request_attrs
211+
self._request_hook = request_hook
212+
self._response_hook = response_hook
154213

155214
def process_request(self, req, resp):
156215
span = req.env.get(_ENVIRON_SPAN_KEY)
216+
if span and self._request_hook:
217+
self._request_hook(span, req)
218+
157219
if not span or not span.is_recording():
158220
return
159221

@@ -178,6 +240,7 @@ def process_response(
178240
self, req, resp, resource, req_succeeded=None
179241
): # pylint:disable=R0201
180242
span = req.env.get(_ENVIRON_SPAN_KEY)
243+
181244
if not span or not span.is_recording():
182245
return
183246

@@ -209,3 +272,6 @@ def process_response(
209272
description=reason,
210273
)
211274
)
275+
276+
if self._response_hook:
277+
self._response_hook(span, req, resp)

instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@
2424
from .app import make_app
2525

2626

27-
class TestFalconInstrumentation(TestBase):
27+
class TestFalconBase(TestBase):
2828
def setUp(self):
2929
super().setUp()
30-
FalconInstrumentor().instrument()
30+
FalconInstrumentor().instrument(
31+
request_hook=getattr(self, "request_hook", None),
32+
response_hook=getattr(self, "response_hook", None),
33+
)
3134
self.app = make_app()
3235
# pylint: disable=protected-access
3336
self.env_patch = patch.dict(
@@ -64,6 +67,8 @@ def tearDown(self):
6467
self.exclude_patch.stop()
6568
self.traced_patch.stop()
6669

70+
71+
class TestFalconInstrumentation(TestFalconBase):
6772
def test_get(self):
6873
self._test_method("GET")
6974

@@ -104,7 +109,6 @@ def _test_method(self, method):
104109
"net.peer.port": "65133",
105110
"http.flavor": "1.1",
106111
"falcon.resource": "HelloWorldResource",
107-
"http.status_text": "Created",
108112
"http.status_code": 201,
109113
},
110114
)
@@ -129,7 +133,6 @@ def test_404(self):
129133
"net.peer.ip": "127.0.0.1",
130134
"net.peer.port": "65133",
131135
"http.flavor": "1.1",
132-
"http.status_text": "Not Found",
133136
"http.status_code": 404,
134137
},
135138
)
@@ -206,3 +209,22 @@ def test_traced_not_recording(self):
206209
self.assertTrue(mock_span.is_recording.called)
207210
self.assertFalse(mock_span.set_attribute.called)
208211
self.assertFalse(mock_span.set_status.called)
212+
213+
214+
class TestFalconInstrumentationHooks(TestFalconBase):
215+
# pylint: disable=no-self-use
216+
def request_hook(self, span, req):
217+
span.set_attribute("request_hook_attr", "value from hook")
218+
219+
def response_hook(self, span, req, resp):
220+
span.update_name("set from hook")
221+
222+
def test_hooks(self):
223+
self.client().simulate_get(path="/hello?q=abc")
224+
span = self.memory_exporter.get_finished_spans()[0]
225+
226+
self.assertEqual(span.name, "set from hook")
227+
self.assertIn("request_hook_attr", span.attributes)
228+
self.assertEqual(
229+
span.attributes["request_hook_attr"], "value from hook"
230+
)

instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py

-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ def expected_attributes(override_attributes):
3535
"http.host": "localhost",
3636
"http.target": "/",
3737
"http.flavor": "1.1",
38-
"http.status_text": "OK",
3938
"http.status_code": 200,
4039
}
4140
for key, val in override_attributes.items():
@@ -138,7 +137,6 @@ def test_404(self):
138137
{
139138
"http.method": "POST",
140139
"http.target": "/bye",
141-
"http.status_text": "NOT FOUND",
142140
"http.status_code": 404,
143141
}
144142
)
@@ -157,7 +155,6 @@ def test_internal_error(self):
157155
{
158156
"http.target": "/hello/500",
159157
"http.route": "/hello/<int:helloid>",
160-
"http.status_text": "INTERNAL SERVER ERROR",
161158
"http.status_code": 500,
162159
}
163160
)

instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py

-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ def expected_attributes(override_attributes):
3535
"http.host": "localhost",
3636
"http.target": "/",
3737
"http.flavor": "1.1",
38-
"http.status_text": "OK",
3938
"http.status_code": 200,
4039
}
4140
for key, val in override_attributes.items():
@@ -118,7 +117,6 @@ def test_404(self):
118117
{
119118
"http.method": "POST",
120119
"http.target": "/bye",
121-
"http.status_text": "Not Found",
122120
"http.status_code": 404,
123121
}
124122
)
@@ -137,7 +135,6 @@ def test_internal_error(self):
137135
{
138136
"http.target": "/hello/500",
139137
"http.route": "/hello/{helloid}",
140-
"http.status_text": "Internal Server Error",
141138
"http.status_code": 500,
142139
}
143140
)

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

-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ def _instrumented_requests_call(
150150
if isinstance(result, Response):
151151
if span.is_recording():
152152
span.set_attribute("http.status_code", result.status_code)
153-
span.set_attribute("http.status_text", result.reason)
154153
span.set_status(
155154
Status(http_status_to_status_code(result.status_code))
156155
)

instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py

-4
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ def test_basic(self):
8282
"http.method": "GET",
8383
"http.url": self.URL,
8484
"http.status_code": 200,
85-
"http.status_text": "OK",
8685
},
8786
)
8887

@@ -127,7 +126,6 @@ def test_not_foundbasic(self):
127126
span = self.assert_span()
128127

129128
self.assertEqual(span.attributes.get("http.status_code"), 404)
130-
self.assertEqual(span.attributes.get("http.status_text"), "Not Found")
131129

132130
self.assertIs(
133131
span.status.status_code, trace.StatusCode.ERROR,
@@ -235,7 +233,6 @@ def span_callback(span, result: requests.Response):
235233
"http.method": "GET",
236234
"http.url": self.URL,
237235
"http.status_code": 200,
238-
"http.status_text": "OK",
239236
"http.response.body": "Hello!",
240237
},
241238
)
@@ -304,7 +301,6 @@ def test_requests_exception_with_response(self, *_, **__):
304301
"http.method": "GET",
305302
"http.url": self.URL,
306303
"http.status_code": 500,
307-
"http.status_text": "Internal Server Error",
308304
},
309305
)
310306
self.assertEqual(span.status.status_code, StatusCode.ERROR)

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

-2
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ def _finish_span(tracer, handler, error=None):
238238
return
239239

240240
if ctx.span.is_recording():
241-
if reason:
242-
ctx.span.set_attribute("http.status_text", reason)
243241
ctx.span.set_attribute("http.status_code", status_code)
244242
ctx.span.set_status(
245243
Status(

0 commit comments

Comments
 (0)