Tapir+ZIO添加默认错误处理器后Metrics端点404问题求助
问题解决:Tapir+ZIO集成Prometheus指标添加错误处理器后404
问题原因
你在配置defaultHandlers时设置了notFoundWhenRejected = true,这个参数会将所有未匹配端点、或处理过程中触发Reject的请求统一返回404。而Prometheus metrics端点的内部逻辑包含Reject场景(比如Tapir的端点匹配校验),被全局错误处理器拦截后直接返回404,覆盖了正常的metrics数据响应。
解决方案
将metrics端点与业务端点的配置分离:metrics端点使用不带默认错误处理器的ZioHttpServerOptions生成路由,业务端点保留带错误处理器的配置,最后合并两个路由启动服务器。这样既保留了业务请求的错误处理逻辑,又能让metrics端点正常返回数据。
修改后的代码示例
1. 拆分配置项
val metrics = PrometheusMetrics.default[Task]() // 仅用于metrics端点的配置(不含错误处理器) val metricsOnlyOptions: ZioHttpServerOptions[Any] = ZioHttpServerOptions .customiseInterceptors .metricsInterceptor(metrics.metricsInterceptor()) .options // 业务端点使用的配置(带错误处理器) def failureResponse(msg: String): ValuedEndpointOutput[_] = ValuedEndpointOutput(jsonBody[MyFailure], MyFailure(msg)) val businessOptions: ZioHttpServerOptions[Any] = ZioHttpServerOptions .customiseInterceptors .metricsInterceptor(metrics.metricsInterceptor()) // 保留metrics拦截器 .defaultHandlers(failureResponse, notFoundWhenRejected = true) .options
2. 生成路由并合并
// 用专属配置生成metrics路由 val metricsEndpoint = ZioHttpInterpreter(metricsOnlyOptions).toHttp(metrics.metricsEndpoint) // 生成业务路由(示例,替换为你的实际业务端点) val businessEndpoints = List(userEndpoint, orderEndpoint) val businessRoutes = ZioHttpInterpreter(businessOptions).toHttp(businessEndpoints) // 合并路由:metrics路由放在前面优先匹配 val combinedRoutes = metricsEndpoint ++ businessRoutes
3. 启动服务器
ZHttpServer.start(8080, combinedRoutes).provide(ZLayer.succeed(ServerConfig.default))
简化替代方案
如果不想拆分配置,也可以将notFoundWhenRejected改为false,这样未匹配的请求会返回Tapir默认的404响应,metrics端点的正常处理不会被拦截。但此方式会改变业务端点的未匹配请求响应行为,需根据实际需求选择:
val options: ZioHttpServerOptions[Any] = ZioHttpServerOptions .customiseInterceptors .metricsInterceptor(metrics.metricsInterceptor()) .defaultHandlers(failureResponse, notFoundWhenRejected = false) // 修改为false .options
内容的提问来源于stack exchange,提问作者Developus
相关产品推荐
相关产品推荐

