如何基于prom-client为所有REST API实现请求数及失败数追踪?
扩展REST API全量追踪方案
要实现所有API的请求数量、失败数量以及耗时追踪,你可以按以下步骤修改现有代码:
1. 新增请求计数类指标
在现有耗时直方图基础上,添加两个计数器:
- 统计所有请求的总次数
- 统计失败请求(状态码≥400)的次数
2. 统一处理所有路由的指标上报
不管请求匹配到哪个路由,甚至是未匹配的404请求,都要确保指标被正确采集,同时捕获处理过程中的异常,避免指标遗漏。
修改后的完整代码
const http = require('http') const url = require('url') const client = require('prom-client') // 创建指标注册器 const register = new client.Registry() register.setDefaultLabels({ app: 'example-nodejs-app' }) client.collectDefaultMetrics({ register }) // 原有耗时直方图 const httpRequestDurationSeconds = new client.Histogram({ name: 'http_request_duration_seconds', help: 'HTTP请求耗时(秒)', labelNames: ['method', 'route', 'code'], buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10] }) // 新增请求总次数计数器 const httpRequestsTotal = new client.Counter({ name: 'http_requests_total', help: 'HTTP请求总次数', labelNames: ['method', 'route', 'code'] }) // 新增失败请求计数器 const httpRequestsFailedTotal = new client.Counter({ name: 'http_requests_failed_total', help: 'HTTP失败请求次数(状态码≥400)', labelNames: ['method', 'route', 'code'] }) // 注册所有指标 register.registerMetric(httpRequestDurationSeconds) register.registerMetric(httpRequestsTotal) register.registerMetric(httpRequestsFailedTotal) // 路由处理映射表(可根据实际业务扩展) const routeHandlers = { '/order': createOrderHandler, '/products': fetchProducts } // HTTP服务器逻辑 const server = http.createServer(async (req, res) => { const endTimer = httpRequestDurationSeconds.startTimer() const route = url.parse(req.url).pathname let statusCode = 200 try { // 匹配路由处理函数,未匹配则返回404 const handler = routeHandlers[route] if (handler) { await handler(req, res) } else { statusCode = 404 res.writeHead(404, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: 'Route not found' })) } // 从响应对象获取最终状态码(如果handler里修改过) statusCode = res.statusCode || statusCode } catch (error) { // 捕获处理过程中的异常,标记为500错误 statusCode = 500 res.writeHead(500, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: 'Internal server error' })) console.error('Request error:', error) } finally { // 上报所有指标 const labels = { method: req.method, route, code: statusCode } endTimer(labels) httpRequestsTotal.inc(labels) // 统计失败请求 if (statusCode >= 400) { httpRequestsFailedTotal.inc(labels) } } }) // 暴露metrics端点 server.on('request', (req, res) => { if (req.url === '/metrics') { res.setHeader('Content-Type', register.contentType) register.metrics().then(data => res.end(data)) } }) server.listen(8080) // 示例处理函数(保持原有业务逻辑) async function createOrderHandler(req, res) { // 你的订单创建逻辑 res.writeHead(201, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ message: 'Order created' })) } async function fetchProducts(req, res) { // 你的商品查询逻辑 res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ products: [] })) }
关键修改说明
- 路由映射表:用
routeHandlers统一管理路由与处理函数的对应关系,方便后续扩展新API - 异常捕获:用
try/catch/finally确保即使处理函数抛出异常,也能正确上报指标 - 全路由覆盖:未匹配到的路由自动返回404并统计,不会遗漏任何请求
- 失败请求判定:通过状态码≥400来标记失败请求,包含4xx客户端错误和5xx服务端错误
- 指标统一上报:所有指标的上报逻辑放在
finally块中,保证无论请求成功或失败都会执行
内容的提问来源于stack exchange,提问作者Ajay S
相关产品推荐
相关产品推荐

