Efficient, concise API performance measurement

2019-08-24 01:40发布

I'd like to centralize API performance measurement logic -- is there an elegant, efficient solution?

Suppose we have this API:

public interface MyApi {
    void zero();
    Long one(String a);
    String two(Long a, Long b);
}

And I'd like to measure the performance of an implementation of this API using a simple measurement wrapper:

public class MyApiImpl implements MyApi{
    // ...
    public Long one(String a) {
        Long start = System.nanoTime();
        try {
          return oneImpl(a);
        } finally {
           Measure.record(System.nanoTime()-start, "one", a);
        }
    }
    // ...
}

but instead of repeating this measurement wrapper logic across each API implementation I'd like to centralize it, e.g., an efficient annotation would be an elegant solution:

public class MyApiImpl implements MyApi{
    // ...

    @Measure
    public Long one(String a) {
        // ...
    }

    // ...
}

The APIs with Measure are in Linux development, staging, and production environments and are enabled 24x7x365. Anyone willing to share good solutions?

Note: I'm specifically not looking for "packaged software solution" that "solves" this problem, regardless of whether it's commercial or open-source. The question is how do you solve the gathering of data efficiently and elegantly at the call-site, i.e., what are the programmatic solutions, e.g., an efficient annotation.

1条回答
时光不老,我们不散
2楼-- · 2019-08-24 02:24

I have done something similar using aspect and Dropwizard metrics. Start with creating an aspect for Timed annotation,

@Aspect
@Component
public class TimedAspect {

    private MetricRegistry registry;

    @Autowired
    public TimedAspect(MetricRegistry registry) {
        this.registry = registry;
    }

    @Around("@annotation(annotation) || @within(annotation)")
    public Object generateMetric(
            final ProceedingJoinPoint pointcut,
            final Timed annotation) throws Throwable {
        Timed anno = getAnnotation(pointcut, annotation);
        String metricName = ...;
        final Timer timer = registry.timer(metricName);
        final Timer.Context context = timer.time();

        try {
            return pointcut.proceed();
        } finally {
            context.stop();
        }
    }

    ...

}

Now you can use @Timed annotation anywhere in your class,

public class MyApiImpl implements MyApi {
    // ...

    @Timed
    public Long one(String a) {
        // ...
    }

    // ...
}

I have a working example here.

查看更多
登录 后发表回答