【问题标题】:Spring Boot + grpc logging + correlation id?Spring Boot + grpc 日志记录 + 相关 ID?
【发布时间】:2021-03-20 08:26:08
【问题描述】:

我有一个 Spring Boot 应用程序。它是一个标准的 http rest api。我在其中添加了一个 grpc 主机以提供并行 grpc 体验。那部分一切正常。我的要求之一是请求/响应日志记录。

我有一个 ServerInterceptor、一个 SimpleForwardingServerCall 包装器和一个 SimpleForwardingServerCallListener 包装器来捕获我需要记录的所有位置(成功和失败调用)。

我需要从 onMessage 获取请求正文,从 2 个位置获取状态码(一个代表失败,一个代表成功),然后是经过的时间。

这么长的问题,我不确定线程​​模型在 grpc 中是如何工作的,我可以在哪里根据每个请求存储这些信息,所以当我到达没有参数的 onComplete() 时,我可以访问是吗?

我正在做类似的事情:

return new xxxServerCallListener<>(next.startCall(new xxxServerCall<>(call), headers), call);

所以我假设为每个请求创建了一个新的 xxxServerCallListener 和 xxxServerCall,并且我可以在它通过管道移动时将内容存储在其中?那会是最好的存放地点吗?

【问题讨论】:

    标签: spring-boot grpc grpc-java


    【解决方案1】:

    是的,为每个 RPC 构建您自己的 ServerCall.Listener 并将信息存储在那里。

      @Override
      public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
          ServerCall<ReqT, RespT> call,
          final Metadata headers,
          ServerCallHandler<ReqT, RespT> next) {
        // resp could be stored in the call class, but then it would need to be
        // a named class which is more boilerplate. AtomicReference is
        // convenient.
        final AtomicReference<RespT> resp = new AtomicReference<>();
        call = new SimpleForwardingServerCall<ReqT, RespT>(call) {
          @Override public void sendMessage(RespT message) {
            // We assume we're getting immutable protobufs or something similar
            // that doesn't mutate. Otherwise we'd need to copy it here.
            resp.set(message);
            super.sendMessage(message);
          }
        };
        return new SimpleForwardingServerCallListener<ReqT>(next.startCall(call, headers)) {
          private ReqT req;
    
          @Override public void onMessage(ReqT message) {
            this.req = message;
            super.onMessage(message);
          }
    
          @Override public void onCancel() {
            // No point in using 'resp' as the client probably didn't use it.
            // Note that sendMessage() has likely not been called so 'resp' is
            // frequently null. If referencing 'resp' here, synchronizing (like
            // that provided by AtomicReference) is necessary.
            log(req);
            super.onCancel();
          }
    
          @Override public void onComplete() {
            // For properly-behaving callers (those that do not invoke
            // call.sendMessage() after call.close()), this actually doesn't
            // need to be synchronized as call.close() (and thus any
            // sendMessage()) is guaranteed to have been called by this point.
            log(req, resp.get());
            super.onComplete();
          }
        };
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-26
      • 2017-11-01
      • 2016-09-07
      • 2015-08-14
      • 2019-06-18
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      相关资源
      最近更新 更多