使用 meterRegistry.timer 统计耗时
meterRegistry.timer 如何 统计 平均 最小 耗时
在 Java 中,
meterRegistry.timer 是 Micrometer 库提供的用于计时操作的工具,Micrometer 是一个应用程序指标收集的外观模式库,支持多种监控系统。下面详细介绍如何使用 meterRegistry.timer 来统计平均耗时和最小耗时。1. 添加依赖
首先,你需要在项目中添加 Micrometer 的依赖。如果你使用的是 Maven,可以在
pom.xml 中添加以下依赖:xml
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.11.4</version>
</dependency>
2. 编写示例代码
以下是一个完整的示例代码,展示了如何使用
meterRegistry.timer 来统计平均耗时和最小耗时:java
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import java.util.concurrent.TimeUnit;
public class TimerStatisticsExample {
public static void main(String[] args) {
// 创建一个简单的 MeterRegistry 实例
MeterRegistry meterRegistry = new SimpleMeterRegistry(Clock.SYSTEM);
// 创建一个计时器
Timer timer = meterRegistry.timer("my.timer");
// 模拟多次操作
for (int i = 0; i < 10; i++) {
// 开始计时
Timer.Sample sample = Timer.start(meterRegistry);
try {
// 模拟一些耗时操作
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 结束计时并记录结果
sample.stop(timer);
}
// 获取平均耗时
double meanTime = timer.mean(TimeUnit.MILLISECONDS);
System.out.println("平均耗时: " + meanTime + " 毫秒");
// 获取最小耗时
double minTime = timer.min(TimeUnit.MILLISECONDS);
System.out.println("最小耗时: " + minTime + " 毫秒");
}
}
3. 代码解释
- 创建
MeterRegistry实例:SimpleMeterRegistry是 Micrometer 提供的一个简单的注册表实现,用于存储和管理所有的指标。 - 创建计时器:使用
meterRegistry.timer方法创建一个名为"my.timer"的计时器。 - 模拟耗时操作:使用
Timer.Sample类来记录每次操作的开始时间,操作完成后调用sample.stop(timer)方法来结束计时并将结果记录到计时器中。 - 获取统计信息:
timer.mean(TimeUnit.MILLISECONDS)方法用于获取平均耗时,单位为毫秒。timer.min(TimeUnit.MILLISECONDS)方法用于获取最小耗时,单位为毫秒。
4. 注意事项
timer.min()方法在某些情况下可能返回0,这是因为 Micrometer 的计时器实现可能不会精确记录最小耗时。如果需要更精确的最小耗时统计,你可以手动维护一个最小耗时变量。- 不同的
MeterRegistry实现可能会有不同的统计精度和性能,你可以根据实际需求选择合适的实现。
spring boot 如何 结合 Prometheus 和 Grafana,按照 get请求的入参orgCode 和 prodCode 两个维度 ,统计http的 成功请求数量,失败请求数量,最小耗时,最大耗时,平均耗时,95%耗时,99%耗时,标准差,qps,总请求占比 等指标。
要在 Spring Boot 中结合 Prometheus 和 Grafana,按照
orgCode 和 prodCode 两个维度统计 HTTP 请求的各项指标,可以按照以下步骤进行:1. 添加依赖
在
pom.xml 中添加必要的依赖:xml
<dependencies>
<!-- Spring Boot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micrometer Prometheus Registry -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2. 配置 Spring Boot
在
application.properties 或 application.yml 中添加以下配置:properties
# 开启 Actuator 的 Prometheus 端点
management.endpoints.web.exposure.include=prometheus
# 启用 Micrometer 的 HTTP 请求统计
management.metrics.web.server.request.autotime.enabled=true
3. 自定义拦截器来记录 orgCode 和 prodCode
创建一个拦截器来记录请求的
orgCode 和 prodCode,并将其作为标签添加到指标中:java
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Component
public class RequestTaggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String orgCode = request.getParameter("orgCode");
String prodCode = request.getParameter("prodCode");
Tags tags = Tags.of(
Tag.of("orgCode", orgCode != null ? orgCode : "unknown"),
Tag.of("prodCode", prodCode != null ? prodCode : "unknown")
);
request.setAttribute("requestTags", tags);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 可以在这里做一些后置处理
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 可以在这里做一些完成后的处理
}
}
4. 配置拦截器
创建一个配置类来注册拦截器:
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private RequestTaggingInterceptor requestTaggingInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestTaggingInterceptor);
}
}
5. 自定义 MeterFilter 来添加标签
创建一个
MeterFilter 来将 orgCode 和 prodCode 标签添加到 HTTP 请求指标中:java
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
@Component
public class RequestTaggingMeterFilter implements MeterFilter {
@Override
public Meter.Id map(Meter.Id id) {
if (id.getName().startsWith("http.server.requests")) {
HttpServletRequest request = getCurrentRequest();
if (request != null) {
Optional.ofNullable(request.getAttribute("requestTags"))
.ifPresent(tags -> id = id.withTags((Iterable<io.micrometer.core.instrument.Tag>) tags));
}
}
return id;
}
private HttpServletRequest getCurrentRequest() {
// 这里需要根据实际情况获取当前请求对象
// 可以使用 RequestContextHolder 等方式
return null;
}
}
6. 启动 Prometheus 和 Grafana
- Prometheus:下载并启动 Prometheus,配置
prometheus.yml文件来收集 Spring Boot 应用的指标:
yaml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
- Grafana:下载并启动 Grafana,添加 Prometheus 作为数据源。
7. 在 Grafana 中创建仪表盘
在 Grafana 中创建一个新的仪表盘,并添加以下查询来统计各项指标:
- 成功请求数量:
promql
sum(rate(http_server_requests_seconds_count{status=~"2..", orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
- 失败请求数量:
promql
sum(rate(http_server_requests_seconds_count{status=~"[45]..", orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
- 最小耗时:
promql
min(http_server_requests_seconds_bucket{le="+Inf", orgCode!="unknown", prodCode!="unknown"}) by (orgCode, prodCode)
- 最大耗时:
promql
max(http_server_requests_seconds_bucket{le="+Inf", orgCode!="unknown", prodCode!="unknown"}) by (orgCode, prodCode)
- 平均耗时:
promql
sum(rate(http_server_requests_seconds_sum{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
/
sum(rate(http_server_requests_seconds_count{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
- 95% 耗时:
promql
histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{orgCode!="unknown", prodCode!="unknown"}[5m])) by (le, orgCode, prodCode))
- 99% 耗时:
promql
histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{orgCode!="unknown", prodCode!="unknown"}[5m])) by (le, orgCode, prodCode))
- 标准差:
promql
sqrt(
(sum(rate(http_server_requests_seconds_sum_of_squares{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
/ sum(rate(http_server_requests_seconds_count{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode))
-
(sum(rate(http_server_requests_seconds_sum{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
/ sum(rate(http_server_requests_seconds_count{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)) ^ 2
)
- QPS:
promql
sum(rate(http_server_requests_seconds_count{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
- 总请求占比:
promql
sum(rate(http_server_requests_seconds_count{orgCode!="unknown", prodCode!="unknown"}[5m])) by (orgCode, prodCode)
/
sum(rate(http_server_requests_seconds_count[5m]))
通过以上步骤,你就可以在 Spring Boot 中结合 Prometheus 和 Grafana,按照
orgCode 和 prodCode 两个维度统计 HTTP 请求的各项指标。如果不用 filter实现 而是通过 Controller层 手动插入代码的方式呢?
如果不使用过滤器(Filter),而是在 Controller 层手动插入代码来实现按照
orgCode 和 prodCode 两个维度统计 HTTP 请求的各项指标,可以参考以下步骤和示例代码:1. 添加依赖
确保
pom.xml 中包含必要的依赖,这些依赖和之前使用过滤器时的依赖一致:xml
<dependencies>
<!-- Spring Boot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micrometer Prometheus Registry -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2. 配置 Spring Boot
在
application.properties 或 application.yml 中添加以下配置:properties
# 开启 Actuator 的 Prometheus 端点
management.endpoints.web.exposure.include=prometheus
# 启用 Micrometer 的 HTTP 请求统计
management.metrics.web.server.request.autotime.enabled=true
3. 创建 Controller 并手动统计指标
java
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
public class MyController {
private final MeterRegistry meterRegistry;
@Autowired
public MyController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@GetMapping("/myEndpoint")
public String myEndpoint(@RequestParam(required = false) String orgCode, @RequestParam(required = false) String prodCode) {
orgCode = orgCode != null ? orgCode : "unknown";
prodCode = prodCode != null ? prodCode : "unknown";
// 开始计时
Timer.Sample sample = Timer.start(meterRegistry);
try {
// 模拟一些业务逻辑
Thread.sleep((long) (Math.random() * 100));
// 成功请求计数器
Counter successCounter = meterRegistry.counter("http_requests_success", "orgCode", orgCode, "prodCode", prodCode);
successCounter.increment();
return "Success";
} catch (Exception e) {
// 失败请求计数器
Counter failureCounter = meterRegistry.counter("http_requests_failure", "orgCode", orgCode, "prodCode", prodCode);
failureCounter.increment();
return "Failure";
} finally {
// 结束计时并记录结果
Timer timer = meterRegistry.timer("http_requests_timer", "orgCode", orgCode, "prodCode", prodCode);
sample.stop(timer);
}
}
}
代码解释
- 注入
MeterRegistry:通过构造函数注入MeterRegistry,它是 Micrometer 用于管理和记录指标的核心组件。 - 获取请求参数:从请求中获取
orgCode和prodCode,如果参数为空则设置为"unknown"。 - 开始计时:使用
Timer.Sample开始计时,记录请求处理的开始时间。 - 业务逻辑处理:模拟一些业务逻辑,这里使用
Thread.sleep模拟耗时操作。 - 统计成功和失败请求数量:
- 如果业务逻辑执行成功,使用
Counter增加成功请求的计数。 - 如果业务逻辑抛出异常,使用另一个
Counter增加失败请求的计数。
- 如果业务逻辑执行成功,使用
- 结束计时:在
finally块中结束计时,并将结果记录到Timer中。
4. 启动 Prometheus 和 Grafana
这部分和使用过滤器时的步骤相同,需要下载并启动 Prometheus 和 Grafana,配置 Prometheus 来收集 Spring Boot 应用的指标,并在 Grafana 中添加 Prometheus 作为数据源。
5. 在 Grafana 中创建仪表盘
在 Grafana 中创建一个新的仪表盘,并添加以下查询来统计各项指标:
- 成功请求数量:
promql
sum(rate(http_requests_success_total[5m])) by (orgCode, prodCode)
- 失败请求数量:
promql
sum(rate(http_requests_failure_total[5m])) by (orgCode, prodCode)
- 最小耗时:
promql
min(http_requests_timer_seconds_bucket{le="+Inf"}) by (orgCode, prodCode)
- 最大耗时:
promql
max(http_requests_timer_seconds_bucket{le="+Inf"}) by (orgCode, prodCode)
- 平均耗时:
promql
sum(rate(http_requests_timer_seconds_sum[5m])) by (orgCode, prodCode)
/
sum(rate(http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)
- 95% 耗时:
promql
histogram_quantile(0.95, sum(rate(http_requests_timer_seconds_bucket[5m])) by (le, orgCode, prodCode))
- 99% 耗时:
promql
histogram_quantile(0.99, sum(rate(http_requests_timer_seconds_bucket[5m])) by (le, orgCode, prodCode))
- 标准差:
promql
sqrt(
(sum(rate(http_requests_timer_seconds_sum_of_squares[5m])) by (orgCode, prodCode)
/ sum(rate(http_requests_timer_seconds_count[5m])) by (orgCode, prodCode))
-
(sum(rate(http_requests_timer_seconds_sum[5m])) by (orgCode, prodCode)
/ sum(rate(http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)) ^ 2
)
- QPS:
promql
sum(rate(http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)
- 总请求占比:
promql
sum(rate(http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)
/
sum(rate(http_requests_timer_seconds_count[5m]))
通过以上步骤,你可以在 Controller 层手动插入代码来实现按照
orgCode 和 prodCode 两个维度统计 HTTP 请求的各项指标。这种方式更加灵活,但需要在每个需要统计的 Controller 方法中手动添加统计代码。统一在 http_requests_ 标签前 添加 ent_credit_api_query_
如果你想统一在
http_requests_ 标签前添加 ent_credit_api_query_,可以按照以下步骤进行修改:1. 修改 Controller 代码
java
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
public class MyController {
private final MeterRegistry meterRegistry;
@Autowired
public MyController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@GetMapping("/myEndpoint")
public String myEndpoint(@RequestParam(required = false) String orgCode, @RequestParam(required = false) String prodCode) {
orgCode = orgCode != null ? orgCode : "unknown";
prodCode = prodCode != null ? prodCode : "unknown";
// 开始计时
Timer.Sample sample = Timer.start(meterRegistry);
try {
// 模拟一些业务逻辑
Thread.sleep((long) (Math.random() * 100));
// 成功请求计数器
Counter successCounter = meterRegistry.counter("ent_credit_api_query_http_requests_success", "orgCode", orgCode, "prodCode", prodCode);
successCounter.increment();
return "Success";
} catch (Exception e) {
// 失败请求计数器
Counter failureCounter = meterRegistry.counter("ent_credit_api_query_http_requests_failure", "orgCode", orgCode, "prodCode", prodCode);
failureCounter.increment();
return "Failure";
} finally {
// 结束计时并记录结果
Timer timer = meterRegistry.timer("ent_credit_api_query_http_requests_timer", "orgCode", orgCode, "prodCode", prodCode);
sample.stop(timer);
}
}
}
2. 修改 Grafana 查询语句
- 成功请求数量:
promql
sum(rate(ent_credit_api_query_http_requests_success_total[5m])) by (orgCode, prodCode)
- 失败请求数量:
promql
sum(rate(ent_credit_api_query_http_requests_failure_total[5m])) by (orgCode, prodCode)
- 最小耗时:
promql
min(ent_credit_api_query_http_requests_timer_seconds_bucket{le="+Inf"}) by (orgCode, prodCode)
- 最大耗时:
promql
max(ent_credit_api_query_http_requests_timer_seconds_bucket{le="+Inf"}) by (orgCode, prodCode)
- 平均耗时:
promql
sum(rate(ent_credit_api_query_http_requests_timer_seconds_sum[5m])) by (orgCode, prodCode)
/
sum(rate(ent_credit_api_query_http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)
- 95% 耗时:
promql
histogram_quantile(0.95, sum(rate(ent_credit_api_query_http_requests_timer_seconds_bucket[5m])) by (le, orgCode, prodCode))
- 99% 耗时:
promql
histogram_quantile(0.99, sum(rate(ent_credit_api_query_http_requests_timer_seconds_bucket[5m])) by (le, orgCode, prodCode))
- 标准差:
promql
sqrt(
(sum(rate(ent_credit_api_query_http_requests_timer_seconds_sum_of_squares[5m])) by (orgCode, prodCode)
/ sum(rate(ent_credit_api_query_http_requests_timer_seconds_count[5m])) by (orgCode, prodCode))
-
(sum(rate(ent_credit_api_query_http_requests_timer_seconds_sum[5m])) by (orgCode, prodCode)
/ sum(rate(ent_credit_api_query_http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)) ^ 2
)
- QPS:
promql
sum(rate(ent_credit_api_query_http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)
- 总请求占比:
promql
sum(rate(ent_credit_api_query_http_requests_timer_seconds_count[5m])) by (orgCode, prodCode)
/
sum(rate(ent_credit_api_query_http_requests_timer_seconds_count[5m]))
通过上述修改,就可以统一在
http_requests_ 标签前添加 ent_credit_api_query_,确保指标名称的一致性和可识别性。同时,在 Grafana 中使用修改后的指标名称进行查询,以获取正确的统计数据。修改 Grafana 查询语句 分别按照orgCode和prodCode 两个维度 统计 当天内的 成功请求数量,失败请求数量,最小耗时,最大耗时,平均耗时,95% 耗时,99% 耗时,标准差,QPS,总请求占比
以下是分别按照
orgCode 和 prodCode 两个维度,统计当天内各项指标的 Grafana 查询语句,假设你的指标名称已经按照前面所说统一为 ent_credit_api_query_http_requests_ 开头。1. 按照 orgCode 维度统计
成功请求数量
promql
sum(increase(ent_credit_api_query_http_requests_success_total{job="your_job_name"}[1d])) by (orgCode)
这里的
your_job_name 需要替换为你 Prometheus 配置中定义的实际作业名称。increase 函数用于计算在指定时间范围内(这里是 1 天)指标的增量,sum 函数将结果按 orgCode 分组求和。失败请求数量
promql
sum(increase(ent_credit_api_query_http_requests_failure_total{job="your_job_name"}[1d])) by (orgCode)
最小耗时
promql
min(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name", le="+Inf", __name__=~".*_bucket"}[1d]) by (orgCode)
最大耗时
promql
max(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name", le="+Inf", __name__=~".*_bucket"}[1d]) by (orgCode)
平均耗时
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum{job="your_job_name"}[1d])) by (orgCode)
/
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (orgCode)
95% 耗时
promql
histogram_quantile(0.95, sum(increase(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name"}[1d])) by (le, orgCode))
99% 耗时
promql
histogram_quantile(0.99, sum(increase(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name"}[1d])) by (le, orgCode))
标准差
promql
sqrt(
(sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum_of_squares{job="your_job_name"}[1d])) by (orgCode)
/ sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (orgCode))
-
(sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum{job="your_job_name"}[1d])) by (orgCode)
/ sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (orgCode)) ^ 2
)
QPS(每秒查询率)
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (orgCode)
/
86400
这里
86400 是一天的秒数。总请求占比
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (orgCode)
/
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d]))
2. 按照 prodCode 维度统计
成功请求数量
promql
sum(increase(ent_credit_api_query_http_requests_success_total{job="your_job_name"}[1d])) by (prodCode)
失败请求数量
promql
sum(increase(ent_credit_api_query_http_requests_failure_total{job="your_job_name"}[1d])) by (prodCode)
最小耗时
promql
min(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name", le="+Inf", __name__=~".*_bucket"}[1d]) by (prodCode)
最大耗时
promql
max(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name", le="+Inf", __name__=~".*_bucket"}[1d]) by (prodCode)
平均耗时
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum{job="your_job_name"}[1d])) by (prodCode)
/
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)
95% 耗时
promql
histogram_quantile(0.95, sum(increase(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name"}[1d])) by (le, prodCode))
99% 耗时
promql
histogram_quantile(0.99, sum(increase(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name"}[1d])) by (le, prodCode))
标准差
promql
sqrt(
(sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum_of_squares{job="your_job_name"}[1d])) by (prodCode)
/ sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode))
-
(sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum{job="your_job_name"}[1d])) by (prodCode)
/ sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)) ^ 2
)
QPS(每秒查询率)
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)
/
86400
总请求占比
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)
/
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d]))
这些查询语句利用了 Prometheus 的
increase 函数来计算当天内指标的增量,从而实现按天统计的目的。同时,通过 sum、min、max、histogram_quantile 等函数分别计算不同的统计指标,并按 orgCode 和 prodCode 进行分组。记得将 your_job_name 替换为实际的作业名称。如何在 Grafana 中可视化这些统计结果?
在 Grafana 中可视化前面统计的结果,可以按照以下详细步骤操作:
1. 登录 Grafana 并创建仪表盘
- 登录:打开浏览器,访问 Grafana 的 Web 界面,使用你的用户名和密码登录。
- 创建仪表盘:
- 点击左侧菜单栏中的 “+” 图标,选择 “Dashboard” 来创建一个新的仪表盘。
- 在弹出的对话框中,点击 “Add an empty panel” 添加一个空白面板。
2. 配置数据源
- 确保你已经在 Grafana 中添加了 Prometheus 作为数据源。如果还未添加,可以按以下步骤操作:
- 点击左侧菜单栏中的 “Configuration”(齿轮图标),选择 “Data Sources”。
- 点击 “Add data source”,选择 “Prometheus”。
- 配置 Prometheus 的 URL 等信息,然后点击 “Save & Test” 确保连接成功。
3. 为每个指标添加查询并配置可视化方式
成功请求数量和失败请求数量
- 添加查询:
- 在面板的编辑界面,点击 “Query” 选项卡。
- 选择之前添加的 Prometheus 数据源。
- 分别输入成功请求数量和失败请求数量的查询语句,例如按
orgCode维度统计的成功请求数量:
promql
sum(increase(ent_credit_api_query_http_requests_success_total{job="your_job_name"}[1d])) by (orgCode)
- 失败请求数量查询语句类似,只需将
success改为failure。 - 选择可视化类型:可以选择 “Bar chart”(柱状图)或 “Table”(表格)。
- 柱状图:能直观地比较不同
orgCode或prodCode的成功和失败请求数量。在 “Visualization” 选项卡中选择 “Bar chart”,根据需要调整图表的颜色、标签等样式。 - 表格:适合展示详细的数据。选择 “Table”,可以看到每个
orgCode或prodCode对应的具体请求数量。
- 柱状图:能直观地比较不同
最小耗时、最大耗时和平均耗时
- 添加查询:分别输入相应的查询语句,如按
prodCode维度统计的平均耗时:
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum{job="your_job_name"}[1d])) by (prodCode)
/
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)
- 选择可视化类型:“Line chart”(折线图)或 “Table”。
- 折线图:可以清晰地展示不同
orgCode或prodCode的耗时随时间的变化趋势(如果数据有时间序列)。在 “Visualization” 选项卡中选择 “Line chart”,调整线条颜色、样式等。 - 表格:用于查看具体的耗时数值。
- 折线图:可以清晰地展示不同
95% 耗时和 99% 耗时
- 添加查询:输入对应的查询语句,如按
orgCode维度统计的 95% 耗时:
promql
histogram_quantile(0.95, sum(increase(ent_credit_api_query_http_requests_timer_seconds_bucket{job="your_job_name"}[1d])) by (le, orgCode))
- 选择可视化类型:与最小、最大、平均耗时类似,可以选择 “Line chart” 或 “Table”。
标准差
- 添加查询:输入标准差的查询语句,如按
prodCode维度统计:
promql
sqrt(
(sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum_of_squares{job="your_job_name"}[1d])) by (prodCode)
/ sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode))
-
(sum(increase(ent_credit_api_query_http_requests_timer_seconds_sum{job="your_job_name"}[1d])) by (prodCode)
/ sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)) ^ 2
)
- 选择可视化类型:“Line chart” 或 “Table”。
QPS(每秒查询率)
- 添加查询:输入 QPS 的查询语句,如按
orgCode维度统计:
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (orgCode)
/
86400
- 选择可视化类型:“Line chart” 能较好地展示 QPS 的变化趋势,“Table” 可查看具体数值。
总请求占比
- 添加查询:输入总请求占比的查询语句,如按
prodCode维度统计:
promql
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d])) by (prodCode)
/
sum(increase(ent_credit_api_query_http_requests_timer_seconds_count{job="your_job_name"}[1d]))
- 选择可视化类型:“Pie chart”(饼图)可以直观地展示不同
orgCode或prodCode的总请求占比情况,也可以选择 “Table” 查看具体占比数值。
4. 调整面板样式和布局
- 样式调整:在 “Visualization” 选项卡中,可以调整图表的颜色、字体、轴标签、图例等样式,使图表更加美观和易读。
- 布局调整:在仪表盘界面,可以通过拖动面板来调整它们的位置和大小,还可以添加行和列来组织面板,使整个仪表盘布局更加合理。
5. 保存仪表盘
完成所有配置后,点击面板右上角的 “Save” 按钮保存面板,再点击仪表盘右上角的 “Save dashboard” 保存整个仪表盘。
通过以上步骤,你就可以在 Grafana 中可视化按照
orgCode 和 prodCode 两个维度统计的各项指标。PromQL 求和,ent_credit_api_query_http_requests_success_total + ent_credit_api_query_http_requests_failure_total
在 PromQL 中,要对
ent_credit_api_query_http_requests_success_total 和 ent_credit_api_query_http_requests_failure_total 这两个指标求和,可以使用 sum 函数以及 + 运算符。以下是具体的查询语句示例:promql
sum(ent_credit_api_query_http_requests_success_total + ent_credit_api_query_http_requests_failure_total) by (orgCode, prodCode)
上述查询语句中:
ent_credit_api_query_http_requests_success_total + ent_credit_api_query_http_requests_failure_total表示将成功请求数量指标和失败请求数量指标相加。sum(...) by (orgCode, prodCode)表示对相加后的结果按照orgCode和prodCode这两个标签维度进行分组求和。
如果你不想按照特定标签维度分组,只是单纯地对所有实例的这两个指标求和,可以去掉
by 子句,如下所示:promql
sum(ent_credit_api_query_http_requests_success_total + ent_credit_api_query_http_requests_failure_total)
这样就会得到所有实例的成功请求数量和失败请求数量的总和。
如果 ent_credit_api_query_http_requests_failure_total 或者 ent_credit_api_query_http_requests_success_total 不存在则表示 0
在 PromQL 中,当
ent_credit_api_query_http_requests_failure_total 或者 ent_credit_api_query_http_requests_success_total 不存在时希望将其视为 0 进行求和,可以使用 or 操作符来处理这种情况。按 orgCode 和 prodCode 维度分组求和
promql
sum(
(ent_credit_api_query_http_requests_success_total or vector(0))
+
(ent_credit_api_query_http_requests_failure_total or vector(0))
) by (orgCode, prodCode)
代码解释
or操作符:or操作符用于合并两个向量。如果左边的向量中某个时间序列存在,则使用该时间序列;如果不存在,则使用右边的向量。vector(0):vector(0)用于创建一个值为 0 的单元素向量。当ent_credit_api_query_http_requests_success_total或者ent_credit_api_query_http_requests_failure_total不存在对应的时间序列时,就会用vector(0)来替代,从而保证在计算时缺失的指标按 0 处理。sum(...) by (orgCode, prodCode):对合并和相加后的结果按照orgCode和prodCode这两个标签维度进行分组求和。
不分组直接求和
如果你不需要按照特定标签维度分组,只是单纯地对所有实例的这两个指标求和,可以去掉
by 子句:promql
sum(
(ent_credit_api_query_http_requests_success_total or vector(0))
+
(ent_credit_api_query_http_requests_failure_total or vector(0))
)
这样就能得到所有实例的成功请求数量和失败请求数量的总和,并且在指标不存在时按 0 处理。
如何使用PromQL在Grafana中进行数据过滤?
在 Grafana 中使用 PromQL 进行数据过滤,可以通过对指标的标签(labels)进行筛选、使用逻辑运算符、范围选择器等多种方式来实现。以下是一些常见的数据过滤方法及示例:
1. 通过标签进行过滤
假设你有一个名为
http_requests_total 的指标,它带有 method(请求方法)和 status(响应状态码)等标签,你可以通过指定标签的值来过滤数据。- 过滤特定请求方法的请求数量:
promql
http_requests_total{method="GET"}
这条语句会返回所有
method 标签值为 "GET" 的 http_requests_total 指标数据。- 过滤特定状态码的请求数量:
promql
http_requests_total{status="200"}
这将返回所有
status 标签值为 "200" 的 http_requests_total 指标数据。- 组合多个标签进行过滤:
promql
http_requests_total{method="POST", status="404"}
此语句会返回
method 为 "POST" 且 status 为 "404" 的 http_requests_total 指标数据。2. 使用正则表达式进行标签值过滤
如果想匹配符合某种模式的标签值,可以使用正则表达式。
promql
http_requests_total{method=~"GET|POST", status=~"2.."}
上述语句中,
method=~"GET|POST" 表示 method 标签的值为 "GET" 或者 "POST";status=~"2.." 表示 status 标签的值以 "2" 开头的任意...在 Grafana 中 一般 用什么图形或者表格 展示 上述 最小耗时,最大耗时,平均耗时 等等?
在 Grafana 中,针对最小耗时、最大耗时、平均耗时等不同类型的指标,可以选择合适的图形或表格进行展示,以下是一些常见的选择及适用场景:
1. 表格(Table)
- 适用场景:当你需要精确查看每个分组(如不同的
orgCode和prodCode)对应的具体指标数值时,表格是一个很好的选择。它能清晰地展示每一行数据的详细信息,便于对比和分析。 - 配置示例:在 Grafana 面板中选择 “Table” 可视化类型,将查询到的最小耗时、最大耗时、平均耗时等指标添加到表格中。可以设置表头来明确各列代表的含义,还能对数据进行排序、格式化等操作。
2. 柱状图(Bar Chart)
- 适用场景:适合比较不同分组之间的指标差异。例如,对比不同
orgCode或prodCode的平均耗时,柱状图可以直观地展示出各个分组的指标大小关系,一眼看出哪个分组的耗时较长或较短。 - 配置示例:在面板中选择 “Bar Chart”,将分组字段(如
orgCode或prodCode)设置为 X 轴,最小耗时、最大耗时、平均耗时等指标分别设置为不同的系列(Y 轴)。可以调整柱子的颜色、宽度等样式,使图表更加美观。
3. 折线图(Line Chart)
- 适用场景:如果数据具有时间序列特征,例如你想观察最小耗时、最大耗时、平均耗时随时间的变化趋势,折线图是最佳选择。它能够清晰地展示指标的波动情况和发展趋势。
- 配置示例:在面板中选择 “Line Chart”,将时间字段设置为 X 轴,不同的指标(最小耗时、最大耗时、平均耗时)设置为不同的线条(Y 轴)。可以调整线条的颜色、样式、平滑度等,还能添加数据点标记,方便查看具体数值。
4. 仪表盘(Gauge)
- 适用场景:当你只关注单个指标的当前值,并且希望以一种直观的方式展示该指标是否处于正常范围时,仪表盘很合适。例如,单独展示某个
orgCode和prodCode组合的平均耗时,并设置一个合理的阈值范围,通过仪表盘的指针位置和颜色变化来快速判断指标是否正常。 - 配置示例:在面板中选择 “Gauge”,将需要展示的指标(如平均耗时)设置为值字段。可以设置仪表盘的最小值、最大值、阈值范围等参数,还能调整仪表盘的颜色、样式等。
5. 热力图(Heatmap)
- 适用场景:如果需要同时展示多个分组和多个指标之间的关系,并且想要直观地看到数据的分布和变化趋势,热力图是一个不错的选择。例如,展示不同
orgCode和prodCode组合下的平均耗时,通过颜色深浅来表示耗时的高低。 - 配置示例:在面板中选择 “Heatmap”,将分组字段(如
orgCode和prodCode)分别设置为 X 轴和 Y 轴,平均耗时等指标作为值字段。可以调整颜色映射、数据聚合方式等参数,使热力图更加清晰易懂。
ent_credit_api_query_http_requests_timer_seconds_bucket 不存在
如果
ent_credit_api_query_http_requests_timer_seconds_bucket 指标不存在,可能是由多种原因导致的,下面为你详细分析并给出相应的解决办法。可能的原因及解决办法
1. 代码未正确记录指标
- 原因:在 Spring Boot 应用里,若没有正确配置或者使用 Micrometer 来记录计时指标,就不会生成对应的
_bucket指标。 - 解决办法:
- 要保证在 Controller 代码中正确使用
Timer来记录请求耗时。示例代码如下:
- 要保证在 Controller 代码中正确使用
java
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
public class MyController {
private final MeterRegistry meterRegistry;
@Autowired
public MyController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@GetMapping("/myEndpoint")
public String myEndpoint(@RequestParam(required = false) String orgCode, @RequestParam(required = false) String prodCode) {
orgCode = orgCode != null ? orgCode : "unknown";
prodCode = prodCode != null ? prodCode : "unknown";
Timer timer = meterRegistry.timer("ent_credit_api_query_http_requests_timer", "orgCode", orgCode, "prodCode", prodCode);
Timer.Sample sample = Timer.start(meterRegistry);
try {
// 模拟业务逻辑
Thread.sleep((long) (Math.random() * 100));
return "Success";
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "Failure";
} finally {
sample.stop(timer);
}
}
}
- 确保 Micrometer 配置正确,并且在
application.properties或application.yml中启用了 HTTP 请求计时:
properties
management.metrics.web.server.request.autotime.enabled=true
2. 指标还未生成
- 原因:如果应用刚启动不久,可能还没有足够的请求来生成
_bucket指标。因为_bucket指标是基于直方图的,需要有一定数量的请求数据才能生成。 - 解决办法:
- 发送一些测试请求到应用,等待一段时间,让指标有足够的数据来生成。你可以使用工具(如
curl或 Postman)发送多个请求进行测试。
- 发送一些测试请求到应用,等待一段时间,让指标有足够的数据来生成。你可以使用工具(如
3. Prometheus 配置问题
- 原因:Prometheus 可能没有正确配置来收集应用的指标,或者收集间隔设置过长,导致指标没有及时被采集。
- 解决办法:
- 检查 Prometheus 的
prometheus.yml配置文件,确保正确配置了 Spring Boot 应用的目标地址和采集路径。示例配置如下:
- 检查 Prometheus 的
yaml
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
- 可以适当缩短采集间隔,例如将
scrape_interval设置为 15s:
yaml
global:
scrape_interval: 15s
4. 指标名称拼写错误
- 原因:在 PromQL 查询中,可能存在指标名称拼写错误,导致无法找到对应的指标。
- 解决办法:
- 仔细检查 PromQL 查询语句中的指标名称,确保与实际的指标名称一致。可以通过访问 Prometheus 的 Web 界面(默认地址为
http://localhost:9090),在 “Graph” 标签页中使用自动补全功能来确认指标名称。
- 仔细检查 PromQL 查询语句中的指标名称,确保与实际的指标名称一致。可以通过访问 Prometheus 的 Web 界面(默认地址为
5. 依赖版本不兼容
- 原因:使用的 Micrometer、Spring Boot 或 Prometheus 客户端库的版本不兼容,可能会导致指标记录或采集出现问题。
- 解决办法:
- 确保使用的依赖版本相互兼容。可以参考官方文档或社区论坛来选择合适的版本。例如,对于 Spring Boot 3.x,建议使用 Micrometer 1.11.x 系列的版本。
通过以上步骤,你应该能够解决
ent_credit_api_query_http_requests_timer_seconds_bucket 指标不存在的问题。如果问题仍然存在,建议查看应用的日志文件,以获取更多的错误信息。management.metrics.web.server.request.autotime.enabled=true 提示 Whether to automatically time web server requests. Deprecated: Requests are timed automatically. DO NOT USE THIS PROPERTY AS IT IS COMPLETELY UNSUPPORTED Default value: true
从你给出的提示信息可知,
management.metrics.web.server.request.autotime.enabled 这个配置项已被弃用,因为现在 Spring Boot 会自动对 Web 服务器请求进行计时,所以不需要再使用这个配置项。处理办法
移除配置项
你可以直接从
application.properties 或者 application.yml 里把 management.metrics.web.server.request.autotime.enabled=true 这一行配置删掉。application.properties
如果原本的配置文件是这样的:
properties
# 其他配置...
management.metrics.web.server.request.autotime.enabled=true
那么修改后变为:
properties
# 其他配置...
application.yml
如果原本的配置文件是这样的:
yaml
# 其他配置...
management:
metrics:
web:
server:
request:
autotime:
enabled: true
那么修改后变为:
yaml
# 其他配置...
验证计时功能
移除配置项之后,你可以验证下计时功能是否正常工作。你可以发送一些请求到你的 Spring Boot 应用,然后通过 Prometheus 的 Web 界面(通常是
http://localhost:9090)来查看是否有相关的计时指标(像 ent_credit_api_query_http_requests_timer_seconds_bucket 这类)。示例代码验证
以下是一个简单的示例代码,用来验证计时功能:
java
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
public class TestController {
private final MeterRegistry meterRegistry;
@Autowired
public TestController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@GetMapping("/test")
public String test() {
Timer timer = meterRegistry.timer("ent_credit_api_query_http_requests_timer");
Timer.Sample sample = Timer.start(meterRegistry);
try {
// 模拟一些耗时操作
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
sample.stop(timer);
}
return "Test completed";
}
}
发送请求到
/test 端点,然后查看 Prometheus 里是否有 ent_credit_api_query_http_requests_timer_seconds_bucket 指标。prometheus 实现 springboot 某个http post 请求,按照入参 的 两个维度 name 和 age, 统计 http请求耗时。
要使用 Prometheus 对 Spring Boot 应用中某个 HTTP POST 请求按照入参的两个维度(
name 和 age)统计请求耗时,你可以按照以下步骤进行操作:1. 添加依赖
在
pom.xml 中添加必要的依赖:xml
<dependencies>
<!-- Spring Boot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micrometer Registry Prometheus -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2. 配置 Prometheus 端点
在
application.properties 中添加以下配置,以暴露 Prometheus 指标端点:properties
management.endpoints.web.exposure.include=prometheus
3. 编写控制器和指标统计代码
创建一个控制器类,在其中处理 HTTP POST 请求并使用 Micrometer 统计请求耗时:
java
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
public class MyController {
private final MeterRegistry meterRegistry;
public MyController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@PostMapping("/my-post-endpoint")
public String handlePostRequest(@RequestParam String name, @RequestParam int age) {
// 创建一个带有 name 和 age 标签的计时器
Timer timer = meterRegistry.timer("http.post.request.time", "name", name, "age", String.valueOf(age));
long startTime = System.nanoTime();
// 模拟一些处理逻辑
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
// 记录请求耗时
timer.record(duration, TimeUnit.NANOSECONDS);
return "Request processed successfully";
}
}
4. 启动 Spring Boot 应用
启动 Spring Boot 应用后,你可以通过以下 URL 访问 Prometheus 指标端点:
plaintext
http://localhost:8080/actuator/prometheus
5. 配置 Prometheus 抓取指标
在 Prometheus 的配置文件
prometheus.yml 中添加以下配置,以从 Spring Boot 应用中抓取指标:yaml
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
6. 启动 Prometheus
启动 Prometheus 并访问其 Web 界面(通常是
http://localhost:9090),你可以使用以下 PromQL 查询来查看按照 name 和 age 维度统计的请求耗时:plaintext
http_post_request_time_seconds_sum{name="your_name", age="your_age"} / http_post_request_time_seconds_count{name="your_name", age="your_age"}
通过以上步骤,你就可以使用 Prometheus 对 Spring Boot 应用中某个 HTTP POST 请求按照入参的
name 和 age 两个维度统计请求耗时。上面能 统计 请求次数,和 按照两个维度(name 和 age) 的请求占比吗?
可以在上述代码基础上进一步统计请求次数以及按照
name 和 age 两个维度的请求占比。下面为你详细介绍实现方法:1. 统计请求次数
在控制器中,可以使用
Counter 来统计每个 name 和 age 组合的请求次数。java
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
public class MyController {
private final MeterRegistry meterRegistry;
public MyController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@PostMapping("/my-post-endpoint")
public String handlePostRequest(@RequestParam String name, @RequestParam int age) {
// 创建一个带有 name 和 age 标签的计时器,用于统计请求耗时
Timer timer = meterRegistry.timer("http.post.request.time", "name", name, "age", String.valueOf(age));
// 创建一个带有 name 和 age 标签的计数器,用于统计请求次数
Counter counter = meterRegistry.counter("http.post.request.count", "name", name, "age", String.valueOf(age));
long startTime = System.nanoTime();
// 模拟一些处理逻辑
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
// 记录请求耗时
timer.record(duration, TimeUnit.NANOSECONDS);
// 增加请求计数
counter.increment();
return "Request processed successfully";
}
}
2. 计算请求占比
请求占比可以通过 PromQL 在 Prometheus 中进行计算。具体思路是先计算每个
name 和 age 组合的请求次数,再计算总请求次数,最后用每个组合的请求次数除以总请求次数得到占比。计算每个 name 和 age 组合的请求次数
在 Prometheus 的查询界面,可以使用以下 PromQL 查询每个
name 和 age 组合的请求次数:plaintext
http_post_request_count
计算总请求次数
可以使用
sum 函数对所有 name 和 age 组合的请求次数求和,得到总请求次数:plaintext
sum(http_post_request_count)
计算请求占比
将每个
name 和 age 组合的请求次数除以总请求次数,即可得到请求占比:plaintext
http_post_request_count / sum(http_post_request_count)
3. 注意事项
- 数据准确性:请求占比的计算结果可能会受到 Prometheus 抓取间隔和数据保留策略的影响。为了获得更准确的结果,可以适当调整 Prometheus 的配置。
- 性能影响:使用
Counter和Timer会对应用的性能产生一定的影响,尤其是在高并发场景下。可以根据实际情况进行性能测试和优化。
通过以上步骤,你可以统计请求次数并计算按照
name 和 age 两个维度的请求占比。
摘抄自网络,便于检索查找。

浙公网安备 33010602011771号