如何从不同的方法中提取遥测代码?装饰者模式?面向对象?

How to extract telemetry code from different methods? Decorator pattern? AOP?

我们正在使用 Application Insights 来监控应用程序中的不同服务调用。 Application Insights 的数据由许多不同的方法和 类 提供,但总是在相同的 way/by 相同的代码片段中:

public class MyClassA {

  public void myMethodA() {
    final Instant startTime = Instant.now();

    try {
      callSomeServiceA();
    } catch (final Exception e) {
      sendExceptionDataToAppInsights(e);
      throw e;
    } finally {
      sendDataToAppInsights(MyClass.getName(), myMethodA.getName(), startTime, Instant.now());  
    }
  }

}

public class MyClassB {

  public String myMethodB() {
    final Instant startTime = Instant.now();

    try {
      return callSomeServiceB();
    } catch (final Exception e) {
      sendExceptionDataToAppInsights(e);
      throw e;
    } finally {
      sendDataToAppInsights(MyClass.getName(), myMethodA.getName(), startTime, Instant.now());  
    }
  }

}

我如何才能将那些包装 try catch 片段提取到一个责任点?我看了一下 dacorator 模式,但我猜它不适合,因为方法签名不同。或者是吗?
或者有没有办法用AOP来实现?

Aspect-Oriented Programming 是模块化横切关注点的范例,例如日志记录、监控和错误处理(您的特定情况)。

在 Java 中实现此目的的最流行框架是 AspectJ,它可以通过 spring-boot-starter-aop 依赖项从任何 Spring 项目中使用。

行家

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>${aop-version}</version>
</dependency>

Gradle

implementation `org.springframework.boot:spring-boot-starter-aop:${aop-version}`

实现您所要求的最简单方法是创建一个使用 @Around 的方面(使用 @Aspect)。网上有很多这样的例子。您的执行 (ProceedingJoinPoint:: proceed) 将需要在 try-catch 块内发生,与您在问题中的内容非常相似:

@Around("execution(<aspectj-selector-here>)")
public void anyMethodName(ProceedingJoinPoint pjp) {
    // try-catch blocks here...
}