☰
LoopBack 4 应用接入 Prometheus 监控:基于 @loopback/metrics 的完整实战示例
2026/10/15 17:13:05 网站建设 项目流程
  • 后端
  • 微服务

【免费下载链接】loopback-next

LoopBack makes it easy to build modern API applications that require complex integrations.

项目地址:https://gitcode.com/gh_mirrors/lo/loopback-next
点击查看免费下载

导读

本文基于 LoopBack 4 官方仓库中的@loopback/example-metrics-prometheus示例项目,系统讲解如何为 LoopBack 4 应用接入 Prometheus 指标监控:从启动应用、生成流量,到通过/metrics端点查看 Node.js 进程级指标与 LoopBack 方法调用指标,再到在 Prometheus Web UI 中进行查询与可视化。读完本文,你将掌握@loopback/metrics扩展组件的安装、注册、配置与底层实现原理,并能在自己的 LoopBack 4 应用中复现整套"Pull 模式"监控方案。

示例项目概述

examples/metrics-prometheus是一个用于演示@loopback/metrics扩展与 Prometheus 集成的官方示例。它构建了一个简单的"问候服务":通过 REST 接口批量生成并发调用流量,再由@loopback/metrics组件采集两类指标——Node.js 运行时指标(由 prom-client 提供)与 LoopBack 方法调用指标(由组件内置的拦截器提供),最终暴露为标准 Prometheus 文本格式,供 Prometheus 服务抓取(Pull 模式)。

项目的核心依赖关系可从 examples/metrics-prometheus/package.json 中看到:

  • @loopback/boot、@loopback/core、@loopback/rest:LoopBack 4 应用的基础框架;
  • @loopback/metrics:本示例的核心演示对象,负责指标采集与暴露;
  • @loopback/testlab:开发依赖,用于集成测试。

快速上手:启动应用并生成监控流量

直接启动

在示例目录下执行:

npm start

start脚本会先执行rebuild(即clean+build),再以node .启动应用。应用启动后,终端会输出两类地址信息(见 examples/metrics-prometheus/src/index.ts):

Greeting service is running at http://127.0.0.1:3000/greet/world?count=5. Metrics is running at http://127.0.0.1:3000/metrics

默认监听地址与端口来自index.ts中的配置:

const config = { rest: { port: +(process.env.PORT ?? 3000), host: process.env.HOST ?? '127.0.0.1', openApiSpec: { setServersFromRequest: true, }, }, };

即默认绑定127.0.0.1:3000,可通过环境变量PORT、HOST覆盖。

运行完整演示

npm run demo

demo脚本(package.json 中定义为./bin/demo.sh)会拉起完整的演示环境——包括应用本身与配套的 Prometheus 服务。

生成监控流量

启动后,在浏览器中访问以下地址产生一批并发调用:

http://127.0.0.1:3000/greet/world?count=50

这条请求由GreetingController处理(见 examples/metrics-prometheus/src/controllers/greeting.controller.ts):

@get('/greet/{name}') async greet( @param.path.string('name') name: string, @param.query.number('count') count = 1, ) { const tasks: Promise<string>[] = []; for (let i = 0; i < count; i++) { tasks.push(this.greetingService.greet(name)); } return Promise.all(tasks); }
  • 路径参数name为问候对象;
  • 查询参数count(默认 1)控制并发调用次数,count=50意味着同时发起 50 次服务调用;
  • 所有调用通过Promise.all并行执行,能制造出可观的方法调用流量,便于观察指标变化。

底层GreetingService(见 examples/metrics-prometheus/src/services/greeting.service.ts)为每次调用注入 0~100ms 的随机延迟:

@injectable({tags: {[ContextTags.NAMESPACE]: 'services'}}) export class GreetingService { async greet(name: string) { const ts = new Date().toISOString(); // Delay for a random duration between 0 and 100ms const delayInMs = Math.floor(Math.random() * 100); await sleep(delayInMs); return `[${ts}: ${delayInMs}] Hello, ${name}`; } }

随机延迟使得调用耗时呈现分布特征,让直方图(histogram)与摘要(summary)类指标展示出更有意义的形态。

查看指标端点

生成流量后,访问:

http://127.0.0.1:3000/metrics

即可看到 Prometheus 文本格式的指标输出,内容包括:

  1. Node.js 进程指标:CPU 时间(process_cpu_user_seconds_total等)、内存占用(process_resident_memory_bytes)、事件循环延迟(nodejs_eventloop_lag_seconds)、活动句柄/请求数、V8 堆大小等;
  2. LoopBack 方法调用指标:以loopback_invocation_为前缀的四类指标(详见下文"拦截器采集的四类指标")。

指标端点的底层实现

/metrics端点由@loopback/metrics组件动态注册的MetricsController提供。见 extensions/metrics/src/controllers/metrics.controller.ts:

@injectable({scope: BindingScope.SINGLETON}) class MetricsController { @get(basePath, spec) async report(@inject(RestBindings.Http.RESPONSE) res: Response) { // Set the content type from the register res.contentType(register.contentType); const data = await register.metrics(); res.send(data); return res; } }

关键点:

  • 端点路径basePath默认/metrics,可通过配置修改;
  • 响应内容类型与数据均取自 prom-client 的全局注册表register;
  • 端点默认在 OpenAPI 规格中隐藏(x-visibility: undocumented),因此不会出现在 API Explorer 中,除非显式开启openApiSpec: true。

端点安全性说明

由于指标可能泄露内部信息,默认将端点从 OpenAPI 规格中隐藏。实际部署时建议通过防火墙、反向代理鉴权等方式进一步保护该端点,或将其迁移到独立的内网端口。

在 Prometheus Web UI 中查看指标

打开:

http://localhost:9090

即可访问示例项目配套启动的 Prometheus Web UI。在其中可以:

  • 使用 PromQL 查询指标,例如loopback_invocation_total、nodejs_eventloop_lag_seconds;
  • 按标签(如method、path、statusCode)过滤指标;
  • 将查询结果渲染为图表,观察调用量与延迟随时间的变化。

下面的截图来自本示例项目,展示了 Prometheus Web UI 中查询 LoopBack 方法调用指标并绘制出随时间变化的曲线(图片位于 examples/metrics-prometheus/prometheus-demo.png):

@loopback/metrics 组件:安装与注册

安装

npm install --save @loopback/metrics

该包依赖prom-client(见 extensions/metrics/package.json),并声明@loopback/core、@loopback/rest为 peerDependencies。当前版本以0.x.y发布,属于**实验性(Experimental)**扩展,API 在未来版本中可能有破坏性变更,生产环境接入需关注版本演进。

在应用中注册

示例应用的注册方式极为简洁(见 examples/metrics-prometheus/src/application.ts):

import {BootMixin} from '@loopback/boot'; import {ApplicationConfig} from '@loopback/core'; import {MetricsComponent} from '@loopback/metrics'; import {RestApplication} from '@loopback/rest'; export class GreetingApplication extends BootMixin(RestApplication) { constructor(config: ApplicationConfig = {}) { super(config); this.projectRoot = __dirname; this.component(MetricsComponent); } }

只需要在自定义Application的构造函数中调用this.component(MetricsComponent)一行代码,即可获得完整的指标能力。

组件内部装配了什么

从 extensions/metrics/src/metrics.component.ts 的源码可以看到,注册组件后会按配置条件化地装配以下构件:

if (options.defaultMetrics && !options.defaultMetrics.disabled) { this.application.lifeCycleObserver(MetricsObserver); } if (options.pushGateway && !options.pushGateway.disabled) { this.application.lifeCycleObserver(MetricsPushObserver); } this.application.add(createBindingFromClass(MetricsInterceptor)); if (options.endpoint && !options.endpoint.disabled) { this.application.controller(metricsControllerFactory(options)); } if (options.defaultLabels) { register.setDefaultLabels(options.defaultLabels); }

即:

构件作用启用条件
MetricsObserver生命周期观察者,启动时调用 prom-client 的collectDefaultMetrics采集 Node.js 默认指标defaultMetrics未禁用(默认启用)
MetricsPushObserver按固定周期把指标推送到 Pushgateway(Push 模式)配置了pushGateway且未禁用
MetricsInterceptor全局拦截器,为 LoopBack 方法调用采集指标始终注册
MetricsController暴露/metrics拉取端点endpoint未禁用(默认启用)
默认标签通过register.setDefaultLabels为所有指标附加静态标签配置了defaultLabels

默认配置项

DEFAULT_METRICS_OPTIONS定义于 extensions/metrics/src/types.ts:

export const DEFAULT_METRICS_OPTIONS: MetricsOptions = { endpoint: { basePath: '/metrics', }, defaultMetrics: {}, openApiSpec: false, };

组件构造时会将用户配置与默认配置合并:{...DEFAULT_METRICS_OPTIONS, ...metricsConfig},因此未配置的选项自动取默认值。

深入配置 MetricsOptions

MetricsOptions的完整结构(见 extensions/metrics/src/types.ts):

export interface MetricsOptions { endpoint?: { disabled?: boolean; basePath?: string; }; defaultMetrics?: { disabled?: boolean; } & DefaultMetricsCollectorConfiguration; // prom-client 的默认指标采集配置 defaultLabels?: { [labelName: string]: string; }; pushGateway?: { disabled?: boolean; url: string; interval?: number; // 推送周期,默认 5000ms jobName?: string; // 任务名,默认 'loopback' groupingKey?: {[key: string]: string}; replaceAll?: boolean; // true 使用 push(覆盖),false 使用 pushAdd(追加) }; openApiSpec?: boolean; }

配置示例

在注册组件之前调用this.configure(MetricsBindings.COMPONENT).to({...})即可自定义配置:

import {MetricsBindings} from '@loopback/metrics'; this.configure(MetricsBindings.COMPONENT).to({ endpoint: { basePath: '/metrics', }, defaultMetrics: { timeout: 5000, }, defaultLabels: { service: 'api', version: '1.0.0', }, });

重要:this.configure()必须在this.component()之前调用才能生效。

常用配置项说明

配置项默认值说明
endpoint.basePath/metrics指标暴露路径,可改为如/internal/metrics
endpoint.disabledfalse设为true时不注册指标控制器,/metrics返回 404
defaultMetrics.disabledfalse设为true时停止 Node.js 默认指标采集
defaultMetrics.prefix无为默认指标统一添加前缀(如myapp_)
defaultLabels无为所有指标附加静态标签(如服务名、版本号)
openApiSpecfalse设为true后指标端点出现在 OpenAPI 规格中,可在 API Explorer 中看到
pushGateway未启用配置url后启用 Push 模式

以上配置行为均有对应的验收测试佐证(见 extensions/metrics/src/tests/acceptance/metrics.acceptance.ts):例如basePath改为/internal/metrics后原/metrics返回 404;endpoint.disabled时控制器不注册;defaultMetrics.disabled时不再输出process_cpu_user_seconds_total;defaultLabels会同时出现在默认指标与方法调用指标中。

拦截器采集的四类 LoopBack 方法调用指标

MetricsInterceptor(见 extensions/metrics/src/interceptors/metrics.interceptor.ts)是@loopback/metrics的核心,以全局拦截器(asGlobalInterceptor('metrics'))注册,作用于所有方法调用,输出四类指标:

指标名类型含义
loopback_invocation_duration_secondsGauge当前方法调用的实时耗时(秒)
loopback_invocation_duration_histogramHistogram调用耗时的直方图分布(分桶统计)
loopback_invocation_totalCounter方法调用累计次数
loopback_invocation_duration_summarySummary调用耗时的分位数摘要(quantile)

四类指标共用一组标签:

type LabelNames = 'targetName' | 'method' | 'path' | 'statusCode';
  • targetName:被调用方法的全名,例如GreetingController.prototype.greet;
  • method:HTTP 方法(大写),如GET、POST;
  • path:路径模板(pattern)而非实际路径——这是刻意设计:若使用含动态参数的原始路径,每个不同的 ID 值都会产生新的时间序列,导致指标基数爆炸。见源码注释:
    // make sure to use path pattern instead of raw path // this is important since paths can contain unbounded sets of values // such as IDs which would create a new time series for each unique value return source.value.path;
  • statusCode:响应状态码,拦截器在响应写回前执行,因此需要特殊推导:200 且无返回体的计为 204;异常时从错误对象读取statusCode(ENTITY_NOT_FOUND记为 404,其余无状态码时记 500)。

需要注意:该拦截器只覆盖方法调用本身,不包括在此之前执行的 Sequence 动作与中间件耗时。若需要更完整的链路指标,应在其他位置自行埋点。

理解 Pull 与 Push 两种采集模式

Prometheus 支持两种指标采集模式,@loopback/metrics同时支持:

  • Pull(拉取)模式:Prometheus 定期向被监控系统暴露的 HTTP 指标端点发起抓取。这是常规模式,本示例默认采用,对应/metrics端点;
  • Push(推送)模式:被监控系统主动把指标推送到 Prometheus Pushgateway,通常用于短暂存活的一次性任务(如批处理、CI 作业)。@loopback/metrics通过MetricsPushObserver支持该模式。

Push 模式配置示例

this.configure(MetricsBindings.COMPONENT).to({ pushGateway: { url: 'http://127.0.0.1:9091', // Pushgateway 地址 interval: 5000, // 每 5 秒推送一次 jobName: 'my_job', groupingKey: {env: 'test'}, replaceAll: false, // false 使用 pushAdd 追加;true 使用 push 覆盖 }, });

其实现见 extensions/metrics/src/observers/metrics.push.observer.ts:start()时创建Pushgateway实例,用setInterval按interval(默认 5000ms)周期推送;replaceAll为true时调用gateway.push()(整体覆盖),否则调用gateway.pushAdd()(追加合并);jobName默认'loopback'。

推送行为在 extensions/metrics/src/tests/acceptance/metrics-push.acceptance.ts 中有完整测试覆盖,包括自定义jobName、groupingKey与replaceAll三种组合。

测试与验证

运行示例测试

npm test

示例项目包含一条集成测试(见 examples/metrics-prometheus/src/tests/integration/greeting-service.integration.ts),验证两个核心行为:

  1. 访问/greet/Raymond返回 200 且响应体为数组,元素匹配Hello, Raymond;
  2. 访问/metrics返回 200 且文本中包含loopback_invocation_duration_seconds的 TYPE 声明。

@loopback/metrics 的验收测试

@loopback/metrics扩展自身的验收测试(extensions/metrics/src/tests/acceptance/metrics.acceptance.ts)则覆盖了更细粒度的行为,可作为理解组件能力的参考:

  • 默认配置下/metrics返回含# TYPE、# HELP的文本;
  • 指标端点默认不出现在 OpenAPI 规格中,开启openApiSpec后出现在规格中;
  • 不同 HTTP 方法(GET/POST/PUT/PATCH/DELETE)都会产出带method标签的指标;
  • 不同状态码(200/204/302/400/404/500)正确映射到statusCode标签;
  • 动态路径使用路径模板:请求/path/1产出path="/path/{param}";
  • 纯拦截代理调用(非 REST 路由)只有targetName标签,没有method/path/statusCode。

总结:把监控接入自己的 LoopBack 4 应用

把本示例的能力迁移到自己的项目,只需四步:

  1. 安装:npm install --save @loopback/metrics;
  2. 注册:在应用构造函数中调用this.component(MetricsComponent)(先configure再component可定制行为);
  3. 配置:按需设置endpoint、defaultMetrics、defaultLabels、pushGateway等选项;
  4. 抓取:在 Prometheus 的scrape_configs中配置 target 指向应用的/metrics地址,即可开始采集。

在此基础上,还可以参考MetricsOptions的类型定义,使用 prom-client 的 API 在业务代码中自定义 Counter、Gauge、Histogram 等业务指标,形成"Node.js 运行时 + LoopBack 框架 + 业务自定义"三层完整的可观测性体系。

  • 后端
  • 微服务

【免费下载链接】loopback-next

LoopBack makes it easy to build modern API applications that require complex integrations.

项目地址:https://gitcode.com/gh_mirrors/lo/loopback-next
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询