请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

python使用opentelemetry来实现grpc链路追踪

实现了 opentelemetry 来进行链路追踪
但是server端有一点不优雅的代码 希望 帮忙解答或解决一哈

先上 Client段代码

import time

import grpc
from proto import helloworld_pb2, helloworld_pb2_grpc
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleSpanProcessor,
)


# 1. 这个问题能改吗?
# 2. 其他语言有没有这个问题 其他语言 go语言 python 不服气
if __name__ == '__main__':
    resource = Resource(attributes={
        SERVICE_NAME: "mxshop-grpc"
    })

    jaeger_exporter = JaegerExporter(
        agent_host_name="192.168.16.196",
        agent_port=6831,
    )

    provider = TracerProvider(resource=resource)
    # 这是 导出器 设置为 Jaeger  也可设置为 控制台 zipkin 等  需要看官网给的例子
    processor = BatchSpanProcessor(jaeger_exporter)
    provider.add_span_processor(processor)
    # 这是 设置 grpc 相关代码
    proto_simple = SimpleSpanProcessor(ConsoleSpanExporter())
    provider.add_span_processor(proto_simple)
    # 设置全局默认跟踪程序提供程序
    trace.set_tracer_provider(provider)
    # 这里的代码封装了 tracer = trace.get_tracer(__name__)  所以不需要我们手动开启链路追踪
    instrumentor = GrpcInstrumentorClient().instrument()

    with grpc.insecure_channel("localhost:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        hello_request = helloworld_pb2.HelloRequest()
        hello_request.name = "bobby"
        hello_request.id.extend([1, 2])
        hello_request.id.append(3)
        rsp: helloworld_pb2.HelloReply = stub.SayHello(hello_request)

        print(rsp.message)

    time.sleep(2)

Server端 代码

import time
from concurrent import futures
from random import randint

import grpc
import logging
from proto import helloworld_pb2, helloworld_pb2_grpc
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry import trace
from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleSpanProcessor,
)

resource = Resource(attributes={
    SERVICE_NAME: "mxshop-srv"
})

jaeger_exporter = JaegerExporter(
    agent_host_name="192.168.16.196",
    agent_port=6831,
)

provider = TracerProvider(resource=resource)
# 这是 导出器 设置为 Jaeger  也可设置为 控制台 zipkin 等  需要看官网给的例子
processor = BatchSpanProcessor(jaeger_exporter)
provider.add_span_processor(processor)
# 这是 设置 grpc 相关代码
proto_simple = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(proto_simple)
# 这是另一种注入方式
# trace.get_tracer_provider().add_span_processor(
#     SimpleSpanProcessor(ConsoleSpanExporter())
# )
# 设置全局默认跟踪程序提供程序
trace.set_tracer_provider(provider)
# 这里有点问题  但是我不清楚怎么修改 因为需要 深层次 去 调用 tracer 来创建 子链路 所以我这声明了一个 tracer 理论上 他应该是有什么方法可以给我们来调用的
tracer = trace.get_tracer(__name__)
# 这里的代码封装了 tracer = trace.get_tracer(__name__)  所以不需要我们手动开启链路追踪
grpc_server_instrumentor = GrpcInstrumentorServer().instrument()

class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        # 如何在这里找到父的span
        with tracer.start_span('execute') as execute_span:
            time.sleep(randint(1, 9) * 0.1)
        return helloworld_pb2.HelloReply(message=f"您好, {request.name}, id {request.id}")


if __name__ == '__main__':
    # 1. 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 2. 注册逻辑到server中
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 3. 启动server
    server.add_insecure_port("[::]:50051")
    server.start()
    server.wait_for_termination()

这里的问题在于 从 opentelemetry 的风格来看 他是不希望我们来手动生成 tracer 的
但是 子链路 又需要父链路 才能生成
要不然又是全新的链路

所以我在 server上 自己又去声明了一遍 tracer = trace.get_tracer(name)
这很不优雅 但是不知道调用什么方法 来实现 子链路

请问 这如何解决呢


重新看了一下代码 是我傻了

# 设置全局默认跟踪程序提供程序
trace.set_tracer_provider(provider)

这里将 trace 设置了全局变量

然后 子链路调用 只要如下 调用即可

tracer = trace.get_tracer(__name__)
with tracer.start_span('execute') as execute_span:
    # 你的代码逻辑

如果可以的话 bobby老师登个QQ 有些问题问一下?

正在回答

1回答

trace.get_tracer(__name__) 没问题的, 因为就是获取全局的tracer,实际中也是经常这样使用

0 回复 有任何疑惑可以回复我~
  • 提问者 城中城 #1
    现在又一个问题
    我启动 服务     之前不是有一个 
    consul 会不停发送 健康检查
    导致 链路追踪下  会存在大量这些数据
    如何解决这类问题
    回复 有任何疑惑可以回复我~ 2022-08-02 16:42:50
  • 提问者 城中城 #2
    第二个问题  
    就是  在python下 控制台会不停发送 打印数据   
    如何屏蔽掉
    回复 有任何疑惑可以回复我~ 2022-08-02 16:44:08
  • bobby 回复 提问者 城中城 #3
    在middleware中过滤掉这个url
    回复 有任何疑惑可以回复我~ 2022-08-03 13:08:23
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信