OpenTelemetry gRPC Instrumentation

Module contents

Usage Client

import logging

import grpc

from opentelemetry import trace
from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient, client_interceptor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleExportSpanProcessor,
)

from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter

try:
    from .gen import helloworld_pb2, helloworld_pb2_grpc
except ImportError:
    from gen import helloworld_pb2, helloworld_pb2_grpc

trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    SimpleExportSpanProcessor(ConsoleSpanExporter())
)

# Set meter provider to opentelemetry-sdk's MeterProvider
metrics.set_meter_provider(MeterProvider())

# Optional - export GRPC specific metrics (latency, bytes in/out, errors) by passing an exporter
instrumentor = GrpcInstrumentorClient(exporter=ConsoleMetricsExporter(), interval=10)
instrumentor.instrument()

def run():
    with grpc.insecure_channel("localhost:50051") as channel:

        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name="YOU"))

    print("Greeter client received: " + response.message)


if __name__ == "__main__":
    logging.basicConfig()
    run()

Usage Server

import logging
from concurrent import futures

import grpc

from opentelemetry import trace
from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleExportSpanProcessor,
)

try:
    from .gen import helloworld_pb2, helloworld_pb2_grpc
except ImportError:
    from gen import helloworld_pb2, helloworld_pb2_grpc

trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    SimpleExportSpanProcessor(ConsoleSpanExporter())
)

grpc_server_instrumentor = GrpcInstrumentorServer()
grpc_server_instrumentor.instrument()

class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name)


def serve():

    server = grpc.server(futures.ThreadPoolExecutor())

    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port("[::]:50051")
    server.start()
    server.wait_for_termination()


if __name__ == "__main__":
    logging.basicConfig()
    serve()

You can also add the instrumentor manually, rather than using GrpcInstrumentorServer:

from opentelemetry.instrumentation.grpc import server_interceptor

server = grpc.server(futures.ThreadPoolExecutor(),
                     interceptors = [server_interceptor()])
class opentelemetry.instrumentation.grpc.GrpcInstrumentorServer[source]

Bases: opentelemetry.instrumentation.instrumentor.BaseInstrumentor

Globally instrument the grpc server.

Usage:

grpc_server_instrumentor = GrpcInstrumentorServer()
grpc_server_instrumentor.instrument()
class opentelemetry.instrumentation.grpc.GrpcInstrumentorClient[source]

Bases: opentelemetry.instrumentation.instrumentor.BaseInstrumentor

wrapper_fn(exporter, interval, original_func, instance, args, kwargs)[source]
opentelemetry.instrumentation.grpc.client_interceptor(tracer_provider=None, exporter=None, interval=30)[source]

Create a gRPC client channel interceptor.

Parameters
  • tracer – The tracer to use to create client-side spans.

  • exporter – The exporter that will receive client metrics

  • interval – Time between every export call

Returns

An invocation-side interceptor object.

opentelemetry.instrumentation.grpc.server_interceptor(tracer_provider=None)[source]

Create a gRPC server interceptor.

Parameters

tracer – The tracer to use to create server-side spans.

Returns

A service-side interceptor object.