@@ -108,7 +108,7 @@ def serve():
108
108
logging.basicConfig()
109
109
serve()
110
110
111
- You can also add the instrumentor manually, rather than using
111
+ You can also add the interceptor manually, rather than using
112
112
:py:class:`~opentelemetry.instrumentation.grpc.GrpcInstrumentorServer`:
113
113
114
114
.. code-block:: python
@@ -118,6 +118,64 @@ def serve():
118
118
server = grpc.server(futures.ThreadPoolExecutor(),
119
119
interceptors = [server_interceptor()])
120
120
121
+ Usage Aio Server
122
+ ------------
123
+ .. code-block:: python
124
+
125
+ import logging
126
+ import asyncio
127
+
128
+ import grpc
129
+
130
+ from opentelemetry import trace
131
+ from opentelemetry.instrumentation.grpc import GrpcAioInstrumentorServer
132
+ from opentelemetry.sdk.trace import TracerProvider
133
+ from opentelemetry.sdk.trace.export import (
134
+ ConsoleSpanExporter,
135
+ SimpleSpanProcessor,
136
+ )
137
+
138
+ try:
139
+ from .gen import helloworld_pb2, helloworld_pb2_grpc
140
+ except ImportError:
141
+ from gen import helloworld_pb2, helloworld_pb2_grpc
142
+
143
+ trace.set_tracer_provider(TracerProvider())
144
+ trace.get_tracer_provider().add_span_processor(
145
+ SimpleSpanProcessor(ConsoleSpanExporter())
146
+ )
147
+
148
+ grpc_server_instrumentor = GrpcAioInstrumentorServer()
149
+ grpc_server_instrumentor.instrument()
150
+
151
+ class Greeter(helloworld_pb2_grpc.GreeterServicer):
152
+ async def SayHello(self, request, context):
153
+ return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name)
154
+
155
+
156
+ async def serve():
157
+
158
+ server = grpc.aio.server()
159
+
160
+ helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
161
+ server.add_insecure_port("[::]:50051")
162
+ await server.start()
163
+ await server.wait_for_termination()
164
+
165
+
166
+ if __name__ == "__main__":
167
+ logging.basicConfig()
168
+ asyncio.run(serve())
169
+
170
+ You can also add the interceptor manually, rather than using
171
+ :py:class:`~opentelemetry.instrumentation.grpc.GrpcAioInstrumentorServer`:
172
+
173
+ .. code-block:: python
174
+
175
+ from opentelemetry.instrumentation.grpc import aio_server_interceptor
176
+
177
+ server = grpc.aio.server(interceptors = [aio_server_interceptor()])
178
+
121
179
"""
122
180
from typing import Collection
123
181
@@ -174,6 +232,44 @@ def _uninstrument(self, **kwargs):
174
232
grpc .server = self ._original_func
175
233
176
234
235
+ class GrpcAioInstrumentorServer (BaseInstrumentor ):
236
+ """
237
+ Globally instrument the grpc.aio server.
238
+
239
+ Usage::
240
+
241
+ grpc_aio_server_instrumentor = GrpcAioInstrumentorServer()
242
+ grpc_aio_server_instrumentor.instrument()
243
+
244
+ """
245
+
246
+ # pylint:disable=attribute-defined-outside-init, redefined-outer-name
247
+
248
+ def instrumentation_dependencies (self ) -> Collection [str ]:
249
+ return _instruments
250
+
251
+ def _instrument (self , ** kwargs ):
252
+ self ._original_func = grpc .aio .server
253
+ tracer_provider = kwargs .get ("tracer_provider" )
254
+
255
+ def server (* args , ** kwargs ):
256
+ if "interceptors" in kwargs :
257
+ # add our interceptor as the first
258
+ kwargs ["interceptors" ].insert (
259
+ 0 , aio_server_interceptor (tracer_provider = tracer_provider )
260
+ )
261
+ else :
262
+ kwargs ["interceptors" ] = [
263
+ aio_server_interceptor (tracer_provider = tracer_provider )
264
+ ]
265
+ return self ._original_func (* args , ** kwargs )
266
+
267
+ grpc .aio .server = server
268
+
269
+ def _uninstrument (self , ** kwargs ):
270
+ grpc .aio .server = self ._original_func
271
+
272
+
177
273
class GrpcInstrumentorClient (BaseInstrumentor ):
178
274
"""
179
275
Globally instrument the grpc client
@@ -255,3 +351,19 @@ def server_interceptor(tracer_provider=None):
255
351
tracer = trace .get_tracer (__name__ , __version__ , tracer_provider )
256
352
257
353
return _server .OpenTelemetryServerInterceptor (tracer )
354
+
355
+
356
+ def aio_server_interceptor (tracer_provider = None ):
357
+ """Create a gRPC aio server interceptor.
358
+
359
+ Args:
360
+ tracer: The tracer to use to create server-side spans.
361
+
362
+ Returns:
363
+ A service-side interceptor object.
364
+ """
365
+ from . import _aio_server
366
+
367
+ tracer = trace .get_tracer (__name__ , __version__ , tracer_provider )
368
+
369
+ return _aio_server .OpenTelemetryAioServerInterceptor (tracer )
0 commit comments