Skip to content

Commit 993de40

Browse files
committed
Add falcon version 1.4.1 support to opentelemetry-instrumentation-falcon
1 parent abd01fb commit 993de40

File tree

5 files changed

+48
-14
lines changed

5 files changed

+48
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.10.0-0.29b0...HEAD)
99

10+
- `opentelemetry-instrumentation-falcon` Add support for falcon==1.4.1
11+
([#1000])(https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1000)
1012
- `opentelemetry-instrumentation-flask` Fix non-recording span bug
1113
([#999])(https://github.com/open-telemetry/opentelemetry-python-contrib/pull/999)
1214
- `opentelemetry-instrumentation-tornado` Fix non-recording span bug

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

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def response_hook(span, req, resp):
9191
"""
9292

9393
from logging import getLogger
94+
from packaging import version as package_version
9495
from sys import exc_info
9596
from typing import Collection
9697

@@ -126,12 +127,19 @@ def response_hook(span, req, resp):
126127

127128
_response_propagation_setter = FuncSetter(falcon.Response.append_header)
128129

129-
if hasattr(falcon, "App"):
130+
_parsed_falcon_version = package_version.parse(falcon.__version__)
131+
if _parsed_falcon_version >= package_version.parse('3.0.0'):
130132
# Falcon 3
131133
_instrument_app = "App"
132-
else:
134+
_falcon_version = 3
135+
elif _parsed_falcon_version >= package_version.parse('2.0.0'):
133136
# Falcon 2
134137
_instrument_app = "API"
138+
_falcon_version = 2
139+
else:
140+
# Falcon 1
141+
_instrument_app = "API"
142+
_falcon_version = 1
135143

136144

137145
class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
@@ -163,13 +171,31 @@ def __init__(self, *args, **kwargs):
163171
super().__init__(*args, **kwargs)
164172

165173
def _handle_exception(
166-
self, req, resp, ex, params
174+
self, arg1, arg2, arg3, arg4
167175
): # pylint: disable=C0103
168176
# Falcon 3 does not execute middleware within the context of the exception
169177
# so we capture the exception here and save it into the env dict
178+
179+
# Translation layer for handling the changed arg position of "ex" in Falcon > 2 vs
180+
# Falcon < 2
181+
if _falcon_version == 1:
182+
ex = arg1
183+
req = arg2
184+
resp = arg3
185+
params = arg4
186+
else:
187+
req = arg1
188+
resp = arg2
189+
ex = arg3
190+
params = arg4
191+
170192
_, exc, _ = exc_info()
171193
req.env[_ENVIRON_EXC] = exc
172-
return super()._handle_exception(req, resp, ex, params)
194+
195+
if _falcon_version == 1:
196+
return super()._handle_exception(ex, req, resp, params)
197+
else:
198+
return super()._handle_exception(req, resp, ex, params)
173199

174200
def __call__(self, env, start_response):
175201
# pylint: disable=E1101

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
# limitations under the License.
1414

1515

16-
_instruments = ("falcon >= 2.0.0, < 4.0.0",)
16+
_instruments = ("falcon >= 1.4.1, < 4.0.0",)

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from packaging import version as package_version
12
import falcon
23

34
# pylint:disable=R0201,W0613,E0602
@@ -34,12 +35,17 @@ def on_get(self, req, resp):
3435

3536

3637
def make_app():
37-
if hasattr(falcon, "App"):
38+
_parsed_falcon_version = package_version.parse(falcon.__version__)
39+
if _parsed_falcon_version >= package_version.parse('3.0.0'):
3840
# Falcon 3
3941
app = falcon.App()
40-
else:
42+
elif _parsed_falcon_version >= package_version.parse('2.0.0'):
4143
# Falcon 2
4244
app = falcon.API()
45+
else:
46+
# Falcon 1
47+
app = falcon.API()
48+
4349
app.add_route("/hello", HelloWorldResource())
4450
app.add_route("/ping", HelloWorldResource())
4551
app.add_route("/error", ErrorResource())

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_head(self):
8181

8282
def _test_method(self, method):
8383
self.client().simulate_request(
84-
method=method, path="/hello", remote_addr="127.0.0.1"
84+
method=method, path="/hello"
8585
)
8686
spans = self.memory_exporter.get_finished_spans()
8787
self.assertEqual(len(spans), 1)
@@ -111,7 +111,7 @@ def _test_method(self, method):
111111
self.memory_exporter.clear()
112112

113113
def test_404(self):
114-
self.client().simulate_get("/does-not-exist", remote_addr="127.0.0.1")
114+
self.client().simulate_get("/does-not-exist")
115115
spans = self.memory_exporter.get_finished_spans()
116116
self.assertEqual(len(spans), 1)
117117
span = spans[0]
@@ -135,7 +135,7 @@ def test_404(self):
135135

136136
def test_500(self):
137137
try:
138-
self.client().simulate_get("/error", remote_addr="127.0.0.1")
138+
self.client().simulate_get("/error")
139139
except NameError:
140140
pass
141141
spans = self.memory_exporter.get_finished_spans()
@@ -187,7 +187,7 @@ def test_exclude_lists(self):
187187
self.assertEqual(len(span_list), 1)
188188

189189
def test_traced_request_attributes(self):
190-
self.client().simulate_get(path="/hello?q=abc")
190+
self.client().simulate_get(path="/hello", query_string="q=abc")
191191
span = self.memory_exporter.get_finished_spans()[0]
192192
self.assertIn("query_string", span.attributes)
193193
self.assertEqual(span.attributes["query_string"], "q=abc")
@@ -197,7 +197,7 @@ def test_trace_response(self):
197197
orig = get_global_response_propagator()
198198
set_global_response_propagator(TraceResponsePropagator())
199199

200-
response = self.client().simulate_get(path="/hello?q=abc")
200+
response = self.client().simulate_get(path="/hello", query_string="q=abc")
201201
self.assertTraceResponseHeaderMatchesSpan(
202202
response.headers, self.memory_exporter.get_finished_spans()[0]
203203
)
@@ -211,7 +211,7 @@ def test_traced_not_recording(self):
211211
mock_tracer.start_span.return_value = mock_span
212212
with patch("opentelemetry.trace.get_tracer") as tracer:
213213
tracer.return_value = mock_tracer
214-
self.client().simulate_get(path="/hello?q=abc")
214+
self.client().simulate_get(path="/hello", query_string="q=abc")
215215
self.assertFalse(mock_span.is_recording())
216216
self.assertTrue(mock_span.is_recording.called)
217217
self.assertFalse(mock_span.set_attribute.called)
@@ -257,7 +257,7 @@ def response_hook(self, span, req, resp):
257257
span.update_name("set from hook")
258258

259259
def test_hooks(self):
260-
self.client().simulate_get(path="/hello?q=abc")
260+
self.client().simulate_get(path="/hello", query_string="q=abc")
261261
span = self.memory_exporter.get_finished_spans()[0]
262262

263263
self.assertEqual(span.name, "set from hook")

0 commit comments

Comments
 (0)