当前位置: 首页 > 知识库问答 >
问题:

Micronaut gRPC服务器endpoint吞咽异常(gRPC的StatusException除外);如何记录它们?

温源
2023-03-14

我正在Kotlin的Micronaut gRPC服务器上工作。默认情况下,如果我的gRPCendpoint抛出异常,它将在没有任何日志记录的情况下被吞噬(即使在调试级别),gRPC只返回一个状态:未知的错误响应,没有任何详细信息。

我希望我所有的gRPCendpoint在ERROR级别记录任何未捕获的异常及其堆栈跟踪。我该怎么做?我可以看到使用Micronaut服务工具(拦截/记录异常)、一些gRPC更改或仅在静态编程语言级别解决此问题,以有效地将相同的除日志重抛逻辑应用于所有endpoint函数。

以下是我尝试过的内容和我找到的其他文档:

作为一种解决方法,我在我的endpoint中添加了一个try-catch日志记录,但我不想在每个endpoint中都使用这个样板文件;我假设有更有效的方法将其添加到拦截器中,但在Micronaut文档中还没有发现。

import mu.KotlinLogging

import javax.inject.Singleton
import javax.sql.DataSource

private val logger = KotlinLogging.logger {}

@Singleton
@Suppress("unused")
class MyEndpoint(val dataSource: DataSource) : MyServiceGrpcKt.MyServiceCoroutineImplBase() {

    override suspend fun search(request: MyRequest): MyResponse {
        try {
            dataSource.getConnection().use { con ->
                con.prepareStatement("SELECT ... some sql ... ").use { stm ->
                    stm.setString(1, request.query)
                    stm.executeQuery().use { rs ->
                        // build RPC response from ResultSet
                      }
                  }
              }
          }
        } catch (e: Throwable) {
            // The question is, how to avoid having to add this try-catch and logger.error
            // call in every Endpoint?
            logger.error(e) { "Error handling $request" }
            throw e
        }

        return MyResponse.newBuilder().setStuff(... from sql ...).build()
    }
}

我查看了Micronaut gRPC服务器文档和gRPC错误处理指南,但没有看到任何提示。Micronaut错误处理文档用于HTTP错误页面,而不是通用拦截器。我还询问了gitter Micronaut社区,但没有回应。

gRPCendpoint类的抽象基在我正在实现的RPC方法上有这个文档:

    /**                                                                                              
     * Returns the response to an RPC for valohealth_monocle.model_search.ModelSearchService.Search. 
     *                                                                                               
     * If this method fails with a [StatusException], the RPC will fail with the corresponding       
     * [io.grpc.Status].  If this method fails with a [java.util.concurrent.CancellationException],  
     * the RPC will fail                                                                             
     * with status `Status.CANCELLED`.  If this method fails for any other reason, the RPC will      
     * fail with `Status.UNKNOWN` with the exception as a cause.                                     
     *                                                                                               
     * @param request The request from the client.                                                   
     */                                                                                              
    open suspend fun search...

该注释表明gRPC将异常转换为UNKNOWN状态是预期的行为。但它没有指出如何启用捕获异常的日志记录。

共有1个答案

孙绍辉
2023-03-14

对于静态编程语言,创建一个像这样的ServerInterceptor。请注意,这与在grpc-java中完成的方式不同。

在Micronaut中,只需将类注释为@javax.inject.Singleton即可安装拦截器。

 类似资料:
  • 我一直在玩CompletableFuture,发现了一件奇怪的事情。 如果在我的thenAccept调用中,断言失败,则不会传播异常。当时我尝试了更丑陋的东西: 不会发生任何事情,不会传播任何异常。我尝试使用诸如handle等方法以及与CompletableFutures中异常相关的其他方法,但失败了-没有一个方法像预期的那样传播异常。 当我调试CompletableFuture时,它会捕获如下异

  • 问题内容: 通常,我会遇到必须吞下/ 块中清理代码所引发的异常以防止原始异常被吞咽的情况。 例如: 假设记录任何异常不是方法块范围内的选项,而是由调用and 方法的代码完成。 吞没和方法抛出的异常是一个好主意吗?如果没有,什么是处理上述情况的更好方法,以免吞下异常? 问题答案: 我不喜欢捕捉和抛出异常。 如果你抓住它,做 一些 与它-即使它只是记录例外。 如果您不能执行任何操作,请不要捕获它-在方

  • 我正在使用quickstart原型构建一个Jersey Moxy服务。我的代码运行良好,我可以得到一些JSON返回。然而,在我开发的过程中,如果我犯了一个错误,比如说请求处理程序有一个不支持的类型,我将得到一个空的500响应,这使得调试变得困难。例如,如果我用@XmlElementRef错误地修饰了一个属性,我将得到如下响应: 服务器将表现得好像什么都没发生一样: 我尝试使用日志配置文件: 这产生

  • 有可能从客户端向服务器抛出异常吗?我们有一个从服务器到客户端的开放流: 当我尝试这样的事情时: 我在客户端的StreamObserver.on错误中获得了异常,但在服务器端没有异常。

  • 这是DevForce论坛帖子的又一个延续。问题是DevForce会默默地吞下EntityManager抛出的任何异常。EntityChanged事件,如果更改是由查询或导入触发的。相关代码如下所示: 正如论坛帖子中提到的,随着时间的推移,这种方法的行为发生了一些变化。现在吞下的东西比我第一次抱怨时少了。但对于我们的应用程序,我们真的需要知道什么时候出了问题。仅仅因为我在执行查询或导入操作时出错,并

  • 我试图了解gRPC中的异常处理机制是如何工作的。 除了try-catch块之外,还有其他方法来处理运行时异常,例如服务器端的IllegalArgumentException吗? 例如,我有一些gRPC流式客户端服务,当传递的参数不满足深层次的一些断言时(在某些库中,例如,com.google.common.base.Preconditions),方法onNext抛出IllegalArgumentE