尽管明确注册了 TimedAspect,@Timed 仍然无法工作 - spring boot 2.1

Rah*_*hul 7 aspectj spring-boot prometheus micrometer

我需要使用测微计@Timed 注释来测量方法度量。因为它不适用于任意方法;我在 spring 配置中明确添加了 @TimedAspect 的配置。已经参考这篇文章以获得精确的配置注意:已经尝试为此添加一个单独的配置类,以及将 TimedAspect bean 作为我现有配置 bean 的一部分

如何使用弹簧靴2和千分尺测量服务方法

然而,不幸的是它不起作用。Bean 已注册,并且从配置类调用在启动时成功通过。调试的时候发现的。但是,@Around 中的代码似乎永远不会执行。不会抛出任何错误;并且我能够在 /metrics 和 /prometheus 端点上查看默认的“系统”指标。

注意:这是在通过执行业务流多次调用“方法”之后。我知道如果根本没有调用该方法,它可能不会出现在指标中

版本:弹簧靴 2.1.1、弹簧 5.3、千分尺 1.1.4、执行器 2.1

尝试了以下帖子的所有内容:

如何使用弹簧靴2和千分尺测量服务方法

https://github.com/izeye/sample-micrometer-spring-boot/tree/timed-annotation

https://github.com/micrometer-metrics/micrometer/issues/361

更新:因此,问题似乎仅在 Timed 位于抽象方法上时才出现,该方法通过另一种方法调用。能够通过一个简单的例子重现它。请参阅@Timed("say_hello_example") 注释。当我点击 prometheus 端点时,它只会被忽略并且不会出现。

代码:抽象类

public abstract class AbstractUtil {
    public abstract void sayhello();

    public void sayhellowithtimed(String passedVar) {
        System.out.println("Passed var =>"+passedVar);
        System.out.println("Calling abstract sayhello....");
        sayhello();

    }
}
Run Code Online (Sandbox Code Playgroud)

实现类

@Component
@Scope("prototype")
public class ExampleUtil extends AbstractUtil  {

    public static final String HELLO = "HELLO";

    @Timed("dirwatcher_handler")
    public void handleDirectoryWatcherChange(WatchEvent event){
        System.out.println("Event kind:" + event.kind() + ". File affected: " + event.context());
    }

    @Timed("say_hello_example")
    @Override
    public void sayhello() {
        System.out.println(HELLO);
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

一个简单的 DirWatcher 实现类...

package com.example;
            
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Scope;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
            
import java.io.IOException;
import java.nio.file.*;
            
@Component
@Scope("prototype")
public class StartDirWatcher implements ApplicationListener<ApplicationStartedEvent> {
            
    @Value("${directory.path:/apps}")
    public String directoryPath;
            
    @Autowired
    private ExampleUtil util;
            
    private void monitorDirectoryForChanges() throws IOException, InterruptedException {
        WatchService watchService = FileSystems.getDefault().newWatchService();
        Path path = Paths.get(directoryPath);
        path.register(
            watchService,
            StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_DELETE,
            StandardWatchEventKinds.ENTRY_MODIFY);
        WatchKey key;
        while ((key = watchService.take()) != null) {
            for (WatchEvent<?> event : key.pollEvents()) {
                util.handleDirectoryWatcherChange(event);
                util.sayhellowithtimed("GOD_OF_SMALL_THINGS_onAPPEvent");
            }
            key.reset();
        }
    }
            
    @Override
    public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
        try {
            monitorDirectoryForChanges();
        } catch (Throwable e) {
            System.err.println("ERROR!! "+e.getMessage());
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Spring Boot 应用程序类

package com.example;

import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@ComponentScan
@Configuration
@SpringBootApplication
public class ExampleStarter{

    @Bean
    MeterRegistryCustomizer<PrometheusMeterRegistry> metricsCommonTags() {
        return registry -> registry.config().commonTags("app.name", "example.app");
    }
    @Bean
    TimedAspect timedAspect(MeterRegistry reg) {
        return new TimedAspect(reg);
    }

    public static void main(String[] args) {
        SpringApplication.run(ExampleStarter.class, args);
    }

}
Run Code Online (Sandbox Code Playgroud)

主要的 pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.metrics.timed.example</groupId>
<artifactId>example-app</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.1.1.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
        <version>2.1.1.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <version>1.1.2</version>
</dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
        <version>2.1.1.RELEASE</version>
    </dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)

mak*_*son 8

我使用 spring boot 2.2.6.RELEASE,这个 MetricConfig 对我有用

@Configuration
public class MetricConfig {

  @Bean
  MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
    return registry -> registry.config().commonTags("application", "my app");
  }

  @Bean
  TimedAspect timedAspect(MeterRegistry registry) {
    return new TimedAspect(registry);
  }

}
Run Code Online (Sandbox Code Playgroud)

在application.yml中

management:
  endpoints:
    web:
      exposure:
        include: ["health", "prometheus"]
  endpoint:
    beans:
      cache:
        time-to-live: 10s
Run Code Online (Sandbox Code Playgroud)

  • 我相信@M。Deinum 的评论有助于回答问题并澄清我面临的问题。它基本上与 AOP 的实现方式以及代理的工作方式有关。下面的链接应该有助于为任何寻求更多细节和澄清原始问题的人提供更清晰的信息 - https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-understanding -aop-代理 (4认同)