Skip to content

Commit 87033ab

Browse files
authored
Merge branch 'main' into proper-buckets-http-stable-django
2 parents 803618b + f9d9f19 commit 87033ab

File tree

5 files changed

+200
-58
lines changed

5 files changed

+200
-58
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012))
1818
- `opentelemetry-instrumentation-django`: proper bucket boundaries in stable semconv http duration
1919
([#3524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3524))
20+
- `opentelemetry-instrumentation-grpc`: support non-list interceptors
21+
([#3520](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3520))
2022

2123
### Breaking changes
2224

instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
ElasticsearchInstrumentor,
3232
)
3333
from opentelemetry.instrumentation.elasticsearch.utils import sanitize_body
34-
from opentelemetry.semconv.trace import SpanAttributes
34+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
35+
DB_STATEMENT,
36+
DB_SYSTEM,
37+
)
3538
from opentelemetry.test.test_base import TestBase
3639
from opentelemetry.trace import StatusCode
3740

@@ -76,15 +79,15 @@ def get_elasticsearch_client(*args, **kwargs):
7679
)
7780
class TestElasticsearchIntegration(TestBase):
7881
search_attributes = {
79-
SpanAttributes.DB_SYSTEM: "elasticsearch",
82+
DB_SYSTEM: "elasticsearch",
8083
"elasticsearch.url": "/test-index/_search",
8184
"elasticsearch.method": helpers.dsl_search_method,
8285
"elasticsearch.target": "test-index",
83-
SpanAttributes.DB_STATEMENT: str({"query": {"bool": {"filter": "?"}}}),
86+
DB_STATEMENT: str({"query": {"bool": {"filter": "?"}}}),
8487
}
8588

8689
create_attributes = {
87-
SpanAttributes.DB_SYSTEM: "elasticsearch",
90+
DB_SYSTEM: "elasticsearch",
8891
"elasticsearch.url": "/test-index",
8992
"elasticsearch.method": "HEAD",
9093
}
@@ -361,13 +364,13 @@ def test_dsl_create(self, request_mock):
361364
)
362365

363366
attributes = {
364-
SpanAttributes.DB_SYSTEM: "elasticsearch",
367+
DB_SYSTEM: "elasticsearch",
365368
"elasticsearch.url": "/test-index",
366369
"elasticsearch.method": "PUT",
367370
}
368371
self.assertSpanHasAttributes(span2, attributes)
369372
self.assertEqual(
370-
literal_eval(span2.attributes[SpanAttributes.DB_STATEMENT]),
373+
literal_eval(span2.attributes[DB_STATEMENT]),
371374
helpers.dsl_create_statement,
372375
)
373376

@@ -408,13 +411,13 @@ def test_dsl_index(self, request_mock):
408411
span = spans[0]
409412
self.assertEqual(span.name, helpers.dsl_index_span_name)
410413
attributes = {
411-
SpanAttributes.DB_SYSTEM: "elasticsearch",
414+
DB_SYSTEM: "elasticsearch",
412415
"elasticsearch.url": helpers.dsl_index_url,
413416
"elasticsearch.method": "PUT",
414417
}
415418
self.assertSpanHasAttributes(span, attributes)
416419
self.assertEqual(
417-
literal_eval(span.attributes[SpanAttributes.DB_STATEMENT]),
420+
literal_eval(span.attributes[DB_STATEMENT]),
418421
{
419422
"body": "A few words here, a few words there",
420423
"title": "About searching",

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ def _instrument(self, **kwargs):
334334
tracer_provider = kwargs.get("tracer_provider")
335335

336336
def server(*args, **kwargs):
337-
if "interceptors" in kwargs:
337+
if "interceptors" in kwargs and kwargs["interceptors"]:
338+
kwargs["interceptors"] = list(kwargs["interceptors"])
338339
# add our interceptor as the first
339340
kwargs["interceptors"].insert(
340341
0,
@@ -348,6 +349,7 @@ def server(*args, **kwargs):
348349
tracer_provider=tracer_provider, filter_=self._filter
349350
)
350351
]
352+
351353
return self._original_func(*args, **kwargs)
352354

353355
grpc.server = server
@@ -386,7 +388,8 @@ def _instrument(self, **kwargs):
386388
tracer_provider = kwargs.get("tracer_provider")
387389

388390
def server(*args, **kwargs):
389-
if "interceptors" in kwargs:
391+
if "interceptors" in kwargs and kwargs["interceptors"]:
392+
kwargs["interceptors"] = list(kwargs["interceptors"])
390393
# add our interceptor as the first
391394
kwargs["interceptors"].insert(
392395
0,
@@ -516,6 +519,7 @@ def instrumentation_dependencies(self) -> Collection[str]:
516519

517520
def _add_interceptors(self, tracer_provider, kwargs):
518521
if "interceptors" in kwargs and kwargs["interceptors"]:
522+
kwargs["interceptors"] = list(kwargs["interceptors"])
519523
kwargs["interceptors"] = (
520524
aio_client_interceptors(
521525
tracer_provider=tracer_provider,

instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_server_interceptor.py

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,9 @@ async def ServerStreamingMethod(self, request, context):
5858

5959

6060
async def run_with_test_server(
61-
runnable, servicer=Servicer(), add_interceptor=True
61+
runnable, servicer=Servicer(), interceptors=None
6262
):
63-
if add_interceptor:
64-
interceptors = [aio_server_interceptor()]
65-
server = grpc.aio.server(interceptors=interceptors)
66-
else:
67-
server = grpc.aio.server()
63+
server = grpc.aio.server(interceptors=interceptors)
6864

6965
add_GRPCTestServerServicer_to_server(servicer, server)
7066

@@ -95,7 +91,7 @@ async def request(channel):
9591
msg = request.SerializeToString()
9692
return await channel.unary_unary(rpc_call)(msg)
9793

98-
await run_with_test_server(request, add_interceptor=False)
94+
await run_with_test_server(request)
9995

10096
spans_list = self.memory_exporter.get_finished_spans()
10197
self.assertEqual(len(spans_list), 1)
@@ -140,7 +136,7 @@ async def request(channel):
140136
msg = request.SerializeToString()
141137
return await channel.unary_unary(rpc_call)(msg)
142138

143-
await run_with_test_server(request, add_interceptor=False)
139+
await run_with_test_server(request)
144140

145141
spans_list = self.memory_exporter.get_finished_spans()
146142
self.assertEqual(len(spans_list), 0)
@@ -154,7 +150,9 @@ async def request(channel):
154150
msg = request.SerializeToString()
155151
return await channel.unary_unary(rpc_call)(msg)
156152

157-
await run_with_test_server(request)
153+
await run_with_test_server(
154+
request, interceptors=[aio_server_interceptor()]
155+
)
158156

159157
spans_list = self.memory_exporter.get_finished_spans()
160158
self.assertEqual(len(spans_list), 1)
@@ -206,7 +204,11 @@ async def request(channel):
206204
msg = request.SerializeToString()
207205
return await channel.unary_unary(rpc_call)(msg)
208206

209-
await run_with_test_server(request, servicer=TwoSpanServicer())
207+
await run_with_test_server(
208+
request,
209+
servicer=TwoSpanServicer(),
210+
interceptors=[aio_server_interceptor()],
211+
)
210212

211213
spans_list = self.memory_exporter.get_finished_spans()
212214
self.assertEqual(len(spans_list), 2)
@@ -253,7 +255,9 @@ async def request(channel):
253255
async for response in channel.unary_stream(rpc_call)(msg):
254256
print(response)
255257

256-
await run_with_test_server(request)
258+
await run_with_test_server(
259+
request, interceptors=[aio_server_interceptor()]
260+
)
257261

258262
spans_list = self.memory_exporter.get_finished_spans()
259263
self.assertEqual(len(spans_list), 1)
@@ -307,7 +311,11 @@ async def request(channel):
307311
async for response in channel.unary_stream(rpc_call)(msg):
308312
print(response)
309313

310-
await run_with_test_server(request, servicer=TwoSpanServicer())
314+
await run_with_test_server(
315+
request,
316+
servicer=TwoSpanServicer(),
317+
interceptors=[aio_server_interceptor()],
318+
)
311319

312320
spans_list = self.memory_exporter.get_finished_spans()
313321
self.assertEqual(len(spans_list), 2)
@@ -367,7 +375,11 @@ async def request(channel):
367375
lifetime_servicer = SpanLifetimeServicer()
368376
active_span_before_call = trace.get_current_span()
369377

370-
await run_with_test_server(request, servicer=lifetime_servicer)
378+
await run_with_test_server(
379+
request,
380+
servicer=lifetime_servicer,
381+
interceptors=[aio_server_interceptor()],
382+
)
371383

372384
active_span_in_handler = lifetime_servicer.span
373385
active_span_after_call = trace.get_current_span()
@@ -390,7 +402,9 @@ async def sequential_requests(channel):
390402
await request(channel)
391403
await request(channel)
392404

393-
await run_with_test_server(sequential_requests)
405+
await run_with_test_server(
406+
sequential_requests, interceptors=[aio_server_interceptor()]
407+
)
394408

395409
spans_list = self.memory_exporter.get_finished_spans()
396410
self.assertEqual(len(spans_list), 2)
@@ -450,7 +464,9 @@ async def concurrent_requests(channel):
450464
await asyncio.gather(request(channel), request(channel))
451465

452466
await run_with_test_server(
453-
concurrent_requests, servicer=LatchedServicer()
467+
concurrent_requests,
468+
servicer=LatchedServicer(),
469+
interceptors=[aio_server_interceptor()],
454470
)
455471

456472
spans_list = self.memory_exporter.get_finished_spans()
@@ -504,7 +520,11 @@ async def request(channel):
504520
self.assertEqual(cm.exception.code(), grpc.StatusCode.INTERNAL)
505521
self.assertEqual(cm.exception.details(), failure_message)
506522

507-
await run_with_test_server(request, servicer=AbortServicer())
523+
await run_with_test_server(
524+
request,
525+
servicer=AbortServicer(),
526+
interceptors=[aio_server_interceptor()],
527+
)
508528

509529
spans_list = self.memory_exporter.get_finished_spans()
510530
self.assertEqual(len(spans_list), 1)
@@ -569,7 +589,11 @@ async def request(channel):
569589
)
570590
self.assertEqual(cm.exception.details(), failure_message)
571591

572-
await run_with_test_server(request, servicer=AbortServicer())
592+
await run_with_test_server(
593+
request,
594+
servicer=AbortServicer(),
595+
interceptors=[aio_server_interceptor()],
596+
)
573597

574598
spans_list = self.memory_exporter.get_finished_spans()
575599
self.assertEqual(len(spans_list), 1)
@@ -602,6 +626,60 @@ async def request(channel):
602626
},
603627
)
604628

629+
async def test_non_list_interceptors(self):
630+
"""Check that we handle non-list interceptors correctly."""
631+
632+
grpc_server_instrumentor = GrpcAioInstrumentorServer()
633+
grpc_server_instrumentor.instrument()
634+
635+
try:
636+
rpc_call = "/GRPCTestServer/SimpleMethod"
637+
638+
async def request(channel):
639+
request = Request(client_id=1, request_data="test")
640+
msg = request.SerializeToString()
641+
return await channel.unary_unary(rpc_call)(msg)
642+
643+
class MockInterceptor(grpc.aio.ServerInterceptor):
644+
async def intercept_service(
645+
self, continuation, handler_call_details
646+
):
647+
return await continuation(handler_call_details)
648+
649+
await run_with_test_server(
650+
request, interceptors=(MockInterceptor(),)
651+
)
652+
653+
finally:
654+
grpc_server_instrumentor.uninstrument()
655+
656+
spans_list = self.memory_exporter.get_finished_spans()
657+
self.assertEqual(len(spans_list), 1)
658+
span = spans_list[0]
659+
660+
self.assertEqual(span.name, rpc_call)
661+
self.assertIs(span.kind, trace.SpanKind.SERVER)
662+
663+
# Check version and name in span's instrumentation info
664+
self.assertEqualSpanInstrumentationScope(
665+
span, opentelemetry.instrumentation.grpc
666+
)
667+
668+
# Check attributes
669+
self.assertSpanHasAttributes(
670+
span,
671+
{
672+
SpanAttributes.NET_PEER_IP: "[::1]",
673+
SpanAttributes.NET_PEER_NAME: "localhost",
674+
SpanAttributes.RPC_METHOD: "SimpleMethod",
675+
SpanAttributes.RPC_SERVICE: "GRPCTestServer",
676+
SpanAttributes.RPC_SYSTEM: "grpc",
677+
SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[
678+
0
679+
],
680+
},
681+
)
682+
605683

606684
def get_latch(num):
607685
"""Get a countdown latch function for use in n threads."""

0 commit comments

Comments
 (0)