Journalisation des performances de printemps
1. Vue d'ensemble
Dans ce didacticiel, nous examinerons quelques options de base proposées par Spring Framework pour la surveillance des performances.
2. PerformanceMonitorInterceptor
Une solution simple pour obtenir des fonctionnalités de surveillance de base pour le temps d'exécution de nos méthodes, nous pouvons utiliser la classePerformanceMonitorInterceptor hors de Spring AOP (Aspect Oriented Programming).
Spring AOP permet de définir des problèmes transversaux dans les applications, c'est-à-dire un code qui intercepte l'exécution d'une ou de plusieurs méthodes, afin d'ajouter des fonctionnalités supplémentaires.
La classePerformanceMonitorInterceptor est un intercepteur qui peut être associé à n'importe quelle méthode personnalisée à exécuter en même temps. Cette classe utilise une instanceStopWatch pour déterminer l'heure de début et de fin de l'exécution de la méthode.
Créons une simple classePerson et une classePersonService avec deux méthodes que nous surveillerons:
public class Person {
private String lastName;
private String firstName;
private LocalDate dateOfBirth;
// standard constructors, getters, setters
}
public class PersonService {
public String getFullName(Person person){
return person.getLastName()+" "+person.getFirstName();
}
public int getAge(Person person){
Period p = Period.between(person.getDateOfBirth(), LocalDate.now());
return p.getYears();
}
}
Pour pouvoir utiliser l'intercepteur de surveillance Spring, nous devons définir un pointcut et un conseiller:
@Configuration
@EnableAspectJAutoProxy
@Aspect
public class AopConfiguration {
@Pointcut(
"execution(public String com.example.performancemonitor.PersonService.getFullName(..))"
)
public void monitor() { }
@Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
return new PerformanceMonitorInterceptor(true);
}
@Bean
public Advisor performanceMonitorAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("com.example.performancemonitor.AopConfiguration.monitor()");
return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor());
}
@Bean
public Person person(){
return new Person("John","Smith", LocalDate.of(1980, Month.JANUARY, 12));
}
@Bean
public PersonService personService(){
return new PersonService();
}
}
Le pointcut contient une expression qui identifie les méthodes que nous voulons être interceptées - dans notre cas, la méthodegetFullName() de la classePersonService.
Après avoir configuré le beanperformanceMonitorInterceptor(), nous devons associer l'intercepteur au pointcut. Ceci est réalisé par un conseiller, comme indiqué dans l'exemple ci-dessus.
Enfin, l'annotation@EnableAspectJAutoProxy activeAspectJ support pour nos beans. En termes simples, AspectJ est une bibliothèque créée pour faciliter l'utilisation de Spring AOP grâce à des annotations pratiques telles que@Pointcut.
Après avoir créé la configuration, nous devonsset the log level of the interceptor class to TRACE, car c'est le niveau auquel il enregistre les messages.
Par exemple, en utilisant Jog4j, nous pouvons y parvenir via le fichierlog4j.properties:
log4j.logger.org.springframework.aop.interceptor.PerformanceMonitorInterceptor=TRACE, stdout
Pour chaque exécution de la méthodegetAge(), nous verrons le messageTRACE dans le journal de la console:
2017-01-08 19:19:25 TRACE
PersonService:66 - StopWatch
'com.example.performancemonitor.PersonService.getFullName':
running time (millis) = 10
3. Intercepteur de surveillance des performances personnalisé
Si nous voulons quemore control over the way the performance monitoring soit fait, nous pouvons implémenter notre propre intercepteur personnalisé.
Pour cela, étendons la classeAbstractMonitoringInterceptor et remplaçons la méthodeinvokeUnderTrace() pour consigner le début, la fin et la durée d'une méthode, ainsi qu'un avertissement si l'exécution de la méthode dure plus de 10 ms:
public class MyPerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {
public MyPerformanceMonitorInterceptor() {
}
public MyPerformanceMonitorInterceptor(boolean useDynamicLogger) {
setUseDynamicLogger(useDynamicLogger);
}
@Override
protected Object invokeUnderTrace(MethodInvocation invocation, Log log)
throws Throwable {
String name = createInvocationTraceName(invocation);
long start = System.currentTimeMillis();
log.info("Method " + name + " execution started at:" + new Date());
try {
return invocation.proceed();
}
finally {
long end = System.currentTimeMillis();
long time = end - start;
log.info("Method "+name+" execution lasted:"+time+" ms");
log.info("Method "+name+" execution ended at:"+new Date());
if (time > 10){
log.warn("Method execution longer than 10 ms!");
}
}
}
}
Les étapes à suivre pour associer l'intercepteur personnalisé à une ou plusieurs méthodes, comme dans la section précédente, doivent être suivies.
Définissons un pointcut pour la méthodegetAge() dePersonService et associons-le à l’intercepteur que nous avons créé:
@Pointcut("execution(public int com.example.performancemonitor.PersonService.getAge(..))")
public void myMonitor() { }
@Bean
public MyPerformanceMonitorInterceptor myPerformanceMonitorInterceptor() {
return new MyPerformanceMonitorInterceptor(true);
}
@Bean
public Advisor myPerformanceMonitorAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("com.example.performancemonitor.AopConfiguration.myMonitor()");
return new DefaultPointcutAdvisor(pointcut, myPerformanceMonitorInterceptor());
}
Définissons le niveau de journalisation surINFO pour l'intercepteur personnalisé:
log4j.logger.com.example.performancemonitor.MyPerformanceMonitorInterceptor=INFO, stdout
L'exécution de la méthode getAge() a produit la sortie suivante:
2017-01-08 19:19:25 INFO PersonService:26 -
Method com.example.performancemonitor.PersonService.getAge
execution started at:Sun Jan 08 19:19:25 EET 2017
2017-01-08 19:19:25 INFO PersonService:33 -
Method com.example.performancemonitor.PersonService.getAge execution lasted:50 ms
2017-01-08 19:19:25 INFO PersonService:34 -
Method com.example.performancemonitor.PersonService.getAge
execution ended at:Sun Jan 08 19:19:25 EET 2017
2017-01-08 19:19:25 WARN PersonService:37 -
Method execution longer than 10 ms!
4. Conclusion
Dans ce tutoriel rapide, nous avons introduit une surveillance simple des performances dans Spring.
Comme toujours, le code source complet de cet article peut être trouvéover on Github.