mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 20:52:57 +08:00
fix: Update falcon instrumentation to follow semantic conventions (#1824)
* fix: Update falcon instrumentation to follow semantic conventions * docs: Update changelog * fix linter errors * Disable falcon.HTTP_200 pylint checck --------- Co-authored-by: Shalev Roda <65566801+shalevr@users.noreply.github.com> Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Update falcon instrumentation to follow semantic conventions
|
||||||
|
([#1824](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1824))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Make Flask request span attributes available for `start_span`.
|
- Make Flask request span attributes available for `start_span`.
|
||||||
|
@ -428,7 +428,6 @@ class _TraceMiddleware:
|
|||||||
|
|
||||||
resource_name = resource.__class__.__name__
|
resource_name = resource.__class__.__name__
|
||||||
span.set_attribute("falcon.resource", resource_name)
|
span.set_attribute("falcon.resource", resource_name)
|
||||||
span.update_name(f"{resource_name}.on_{req.method.lower()}")
|
|
||||||
|
|
||||||
def process_response(
|
def process_response(
|
||||||
self, req, resp, resource, req_succeeded=None
|
self, req, resp, resource, req_succeeded=None
|
||||||
@ -483,6 +482,12 @@ class _TraceMiddleware:
|
|||||||
response_headers = resp.headers
|
response_headers = resp.headers
|
||||||
|
|
||||||
if span.is_recording() and span.kind == trace.SpanKind.SERVER:
|
if span.is_recording() and span.kind == trace.SpanKind.SERVER:
|
||||||
|
# Check if low-cardinality route is available as per semantic-conventions
|
||||||
|
if req.uri_template:
|
||||||
|
span.update_name(f"{req.method} {req.uri_template}")
|
||||||
|
else:
|
||||||
|
span.update_name(f"{req.method}")
|
||||||
|
|
||||||
custom_attributes = (
|
custom_attributes = (
|
||||||
otel_wsgi.collect_custom_response_headers_attributes(
|
otel_wsgi.collect_custom_response_headers_attributes(
|
||||||
response_headers.items()
|
response_headers.items()
|
||||||
|
@ -61,6 +61,13 @@ class CustomResponseHeaderResource:
|
|||||||
resp.set_header("my-secret-header", "my-secret-value")
|
resp.set_header("my-secret-header", "my-secret-value")
|
||||||
|
|
||||||
|
|
||||||
|
class UserResource:
|
||||||
|
def on_get(self, req, resp, user_id):
|
||||||
|
# pylint: disable=no-member
|
||||||
|
resp.status = falcon.HTTP_200
|
||||||
|
resp.body = f"Hello user {user_id}"
|
||||||
|
|
||||||
|
|
||||||
def make_app():
|
def make_app():
|
||||||
_parsed_falcon_version = package_version.parse(falcon.__version__)
|
_parsed_falcon_version = package_version.parse(falcon.__version__)
|
||||||
if _parsed_falcon_version < package_version.parse("3.0.0"):
|
if _parsed_falcon_version < package_version.parse("3.0.0"):
|
||||||
@ -76,4 +83,6 @@ def make_app():
|
|||||||
app.add_route(
|
app.add_route(
|
||||||
"/test_custom_response_headers", CustomResponseHeaderResource()
|
"/test_custom_response_headers", CustomResponseHeaderResource()
|
||||||
)
|
)
|
||||||
|
app.add_route("/user/{user_id}", UserResource())
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
@ -110,7 +110,7 @@ class TestFalconInstrumentation(TestFalconBase, WsgiTestBase):
|
|||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
span = spans[0]
|
span = spans[0]
|
||||||
self.assertEqual(span.name, f"HelloWorldResource.on_{method.lower()}")
|
self.assertEqual(span.name, f"{method} /hello")
|
||||||
self.assertEqual(span.status.status_code, StatusCode.UNSET)
|
self.assertEqual(span.status.status_code, StatusCode.UNSET)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
span.status.description,
|
span.status.description,
|
||||||
@ -145,7 +145,7 @@ class TestFalconInstrumentation(TestFalconBase, WsgiTestBase):
|
|||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
span = spans[0]
|
span = spans[0]
|
||||||
self.assertEqual(span.name, "GET /does-not-exist")
|
self.assertEqual(span.name, "GET")
|
||||||
self.assertEqual(span.status.status_code, StatusCode.UNSET)
|
self.assertEqual(span.status.status_code, StatusCode.UNSET)
|
||||||
self.assertSpanHasAttributes(
|
self.assertSpanHasAttributes(
|
||||||
span,
|
span,
|
||||||
@ -177,7 +177,7 @@ class TestFalconInstrumentation(TestFalconBase, WsgiTestBase):
|
|||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
span = spans[0]
|
span = spans[0]
|
||||||
self.assertEqual(span.name, "ErrorResource.on_get")
|
self.assertEqual(span.name, "GET /error")
|
||||||
self.assertFalse(span.status.is_ok)
|
self.assertFalse(span.status.is_ok)
|
||||||
self.assertEqual(span.status.status_code, StatusCode.ERROR)
|
self.assertEqual(span.status.status_code, StatusCode.ERROR)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -206,6 +206,33 @@ class TestFalconInstrumentation(TestFalconBase, WsgiTestBase):
|
|||||||
span.attributes[SpanAttributes.NET_PEER_IP], "127.0.0.1"
|
span.attributes[SpanAttributes.NET_PEER_IP], "127.0.0.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_url_template(self):
|
||||||
|
self.client().simulate_get("/user/123")
|
||||||
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
|
self.assertEqual(len(spans), 1)
|
||||||
|
span = spans[0]
|
||||||
|
self.assertEqual(span.name, "GET /user/{user_id}")
|
||||||
|
self.assertEqual(span.status.status_code, StatusCode.UNSET)
|
||||||
|
self.assertEqual(
|
||||||
|
span.status.description,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
self.assertSpanHasAttributes(
|
||||||
|
span,
|
||||||
|
{
|
||||||
|
SpanAttributes.HTTP_METHOD: "GET",
|
||||||
|
SpanAttributes.HTTP_SERVER_NAME: "falconframework.org",
|
||||||
|
SpanAttributes.HTTP_SCHEME: "http",
|
||||||
|
SpanAttributes.NET_HOST_PORT: 80,
|
||||||
|
SpanAttributes.HTTP_HOST: "falconframework.org",
|
||||||
|
SpanAttributes.HTTP_TARGET: "/",
|
||||||
|
SpanAttributes.NET_PEER_PORT: "65133",
|
||||||
|
SpanAttributes.HTTP_FLAVOR: "1.1",
|
||||||
|
"falcon.resource": "UserResource",
|
||||||
|
SpanAttributes.HTTP_STATUS_CODE: 200,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def test_uninstrument(self):
|
def test_uninstrument(self):
|
||||||
self.client().simulate_get(path="/hello")
|
self.client().simulate_get(path="/hello")
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
|
Reference in New Issue
Block a user