Prometheus 最初是为监控后端服务而设计的,因此用它来观察 React 应用程序并不常见。本文中,我们将介绍如何使用 Prometheus 在应用程序架构中使用单个监控工具来监控 React 应用程序。
监控Asserts UI
在 Asserts,我们一直在对自己的产品进行处理,并用它来监控我们的后端服务。
经过一番研究,我们发现可以帮助我们发布前端 Prometheus 指标的库已经存在。我们能够配置它们并将它们添加到我们的 react 应用程序中。
使用 prom-react 和发布自定义指标进行检测
prom-react 建立在 promjs 和 react-performance 库之上,并增加了将 React 应用程序包装在 MetricsProvider 中的能力,该 MetricsProvider 默认提供流量和延迟指标,如下所示:
const goldenMetrics: MetricDefinition[] = [
{
type: 'counter',
name: GoldenMetrics.AppLoaded,
description: 'Application loaded counter',
},
{
type: 'counter',
name: GoldenMetrics.AppUnloaded,
description: 'Application unloaded counter',
},
{
type: 'histogram',
name: GoldenMetrics.PageNavigation,
description: 'Total navigation duration between pages in seconds',
},
{
type: 'histogram',
name: GoldenMetrics.PageTimeToComplete,
description: 'Section time to interactive in seconds',
},
{
type: 'histogram',
name: GoldenMetrics.PageTimeToUsable,
description: 'Section time to usable in seconds',
},
{
type: 'histogram',
name: GoldenMetrics.PerformanceTime,
description: 'Application performance load time in seconds',
},
];
我们缺少另一个指标 - 测量ajax请求的持续时间,但prom-react允许我们添加自定义指标。
得到以下指标:
- 应用程序加载和卸载
- 页面之间的导航时间(按每个页面 URI)
- 所有页面的应用程序性能加载时间(以秒为单位)(Load、DomContentLoaded、TimeToFirstByte、TimeToFirstPaint、TimeToFirstContentfulPaint)
- 此外,我们还测量后端 AJAX 响应时间
github上的cabify提供了此用例的文档。
现在,让我们来看看我们在项目中集成 prom-react 时遇到了哪些“反应”问题。
Create-react-app、react-performance 和 .mjs 文件问题
安装 prom-react 后,react 应用程序(使用 CRA 的打字稿模板创建)崩溃并出现以下错误:
Failed to compile.
./node_modules/@shopify/react-performance/build/esm/performance-report.mjs
Can't import the named export 'Header' from non EcmaScript module (only default export is available)
发生这种情况是因为 prom-react 重新导出 react-performance,并且它包含文件。一个已知问题,即 CRA 在使用具有模块导出的包时崩溃。快速解决方案是 react-app-rewired,配置如下:.mjs
.mjs
module.exports = function override(config) {
config.module.rules.push({
test: /\.mjs$/,
include: /node_modules/,
type: "javascript/auto"
});
return config;
}
config-overrides.js 文件
此外,更改脚本package.json
源
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
},
改后
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
},
就是这样!现在它可以毫无问题地编译。
监视 Ajax 请求
prom-react 的想法是拥有一个来自 promjs 的单一注册表并将其提供给所有 React 组件树,因此我们可以使用 hook 来定义阶段 ( 和 ) 更多信息可以在这里找到。我们的目标是测量 Ajax 请求的延迟,在这种情况下,我们需要能够使用相同的注册表从钩子调用方法。当然,我们可以对已经包含一些有关 Ajax 请求延迟的信息的阶段,但它并不精确,因为它还包含渲染时间。出于此类目的以及其他目的(例如,公开 Snackbar 以在 Axios 拦截器中使用通知程序),我们将 npm 库 react-outside-call 与此自定义指标配置一起使用。usePerformanceMark
Stage.Usable
Stage.Complete
.observe
useMetrics
usePerformanceMark
import { MetricDefinition, useMetrics } from '@cabify/prom-react';
import { createCaller } from 'react-outside-call';
export const PROM_UI_REQUEST_SECONDS_COUNT: MetricDefinition = {
type: 'histogram',
name: 'prom_ui_request_seconds_count',
description: 'A metric for UI request latency',
buckets: [0.2, 0.5, 1, 2, 5, 10],
};
export const customPromMetrics: MetricDefinition[] = [
PROM_UI_REQUEST_SECONDS_COUNT,
];
export const callConfig = createCaller({
// eslint-disable-next-line react-hooks/rules-of-hooks
metrics: () => useMetrics(),
});
使用 Axios 拦截器,我们测量请求/响应时间,并通过 观察这个指标。开始时间被放入请求标头中。callConfig
react-outside-call
import axios, { AxiosInstance } from 'axios';
import { callConfig, PROM_UI_REQUEST_SECONDS_COUNT } from './constants';
export const apiHttpService: AxiosInstance = axios.create({});
apiHttpService.interceptors.request.use((req) => {
req.headers = {
'request-startTime': performance.now().toString(),
};
return req;
});
apiHttpService.interceptors.response.use((res) => {
const start = res.config.headers?.['request-startTime'];
const end = performance.now();
callConfig.call.metrics?.observe(
PROM_UI_REQUEST_SECONDS_COUNT.name,
{
uri: res.config.url?.replace(/\?.*/, '') || 'unknown',
method: res.config.method?.toUpperCase() || 'unknown',
statusCode: res.status.toString(),
},
(end - start) / 1000,
);
return res;
});
将指标发布到 Prometheus
Prometheus 旨在抓取目标。库将指标发送到 configured for 。Prometheus 聚合网关可用于收集它们。现在,如果访问聚合网关的终端节点,将看到如下所示的指标列表:metricsAggregatorUrl
MetricsProvider
/metrics
# HELP prom_react_app_loaded Application loaded counter
# TYPE prom_react_app_loaded counter
prom_react_app_loaded{app_name="jarvis",status="failure"} 18
prom_react_app_loaded{app_name="jarvis",owner="asserts",status="success"} 25826
# HELP prom_react_app_unloaded Application unloaded counter
# TYPE prom_react_app_unloaded counter
prom_react_app_unloaded{app_name="jarvis",owner="asserts"} 1877
# HELP prom_react_navigation_duration_seconds Total navigation duration between pages in seconds
# TYPE prom_react_navigation_duration_seconds histogram
prom_react_navigation_duration_seconds_bucket{app_name="jarvis",navigation_type="full_page",owner="asserts",path="/assertions",le="1"} 8876
# HELP prom_react_performance_seconds Application performance load time in seconds
# TYPE prom_react_performance_seconds histogram
prom_react_performance_seconds_bucket{app_name="jarvis",event_type="dcl",owner="asserts",le="1"} 7856
prom_react_performance_seconds_bucket{app_name="jarvis",event_type="load",owner="asserts",le="1"} 7771
prom_react_performance_seconds_bucket{app_name="jarvis",event_type="ttfb",owner="asserts",le="1"} 11321
prom_react_performance_seconds_bucket{app_name="jarvis",event_type="ttfcp",owner="asserts",le="1"} 6562
prom_react_performance_seconds_bucket{app_name="jarvis",event_type="ttfp",owner="asserts",le="1"} 8114
# HELP prom_react_ttc_seconds Section time to interactive in seconds
# TYPE prom_react_ttc_seconds histogram
prom_react_ttc_seconds_bucket{app_name="jarvis",navigation_type="full_page",owner="asserts",path="/",le="1"} 8876
# HELP prom_react_ttu_seconds Section time to usable in seconds
# TYPE prom_react_ttu_seconds histogram
prom_react_ttu_seconds_bucket{app_name="jarvis",navigation_type="full_page",owner="asserts",path="/",le="1"} 8876
# HELP prom_ui_request_seconds_count A metric for UI request latency
# TYPE prom_ui_request_seconds_count histogram
prom_ui_request_seconds_bucket{app_name="jarvis",method="POST",owner="asserts",statusCode="200",uri="/api-server/v1/search/assertions",le="1"} 759
指标在 Prometheus 中后,您可以在 Prometheus UI 中开始运行 PromQL 查询或使用 Grafana Dashboards。
XHR 请求延迟的指标结果示例
可以通过 PromQL 和 Grafana 仪表板获得并与其他后端指标相关联。