web-dev-qa-db-fra.com

Métriques Codahale: utilisation de l'annotation des métriques @Timed en langage Java pur

J'essaie d'ajouter des métriques à une application Java simple en utilisant des métriques codahale. J'aimerais utiliser l'annotation @Timed, mais il m'est difficile de savoir quel MetricRegistry il utilise ou comment lui dire quel MetricRegistry doit être utilisé. L'application est une application Java 8 standard, construite avec Maven 3, pas de Spring, pas d'Hibernate.

Je ne trouve aucune documentation sur la mise en œuvre de @Timed dans la documentation de dropwizard: https://dropwizard.github.io/metrics/3.1.0/manual/

J'ai ajouté ces dépendances:

<dependency>
  <groupId>io.dropwizard.metrics</groupId>
  <artifactId>metrics-core</artifactId>
  <version>3.1.0</version>
</dependency>
<dependency>
  <groupId>com.codahale.metrics</groupId>
  <artifactId>metrics-annotation</artifactId>
  <version>3.0.2</version>
</dependency>

Lorsque j'utilise un appel programmé avec Timer, je peux obtenir des rapports car je sais quel MetricsRegistry est utilisé:

static final MetricRegistry metrics = new MetricRegistry();
private void update() throws SQLException {
  Timer.Context time = metrics.timer("domainobject.update").time();
  try {
    [...]
  } finally {
    time.stop();
  }
}

Mais lorsque j'utilise l'annotation @Timed, beaucoup plus élégante, je ne sais pas quel registre est utilisé, et je ne peux donc pas créer de reporter, ce qui signifie que je ne peux pas obtenir les métriques rapportées (je ne suis même pas sûr n'importe quoi):

@Timed(name = "domainobject.update")
private void update() throws SQLException {
    [...]
}

Veuillez indiquer comment faire en sorte que @Timed et les autres annotations Metrics fonctionnent dans une application Java normale.

Informations complémentaires: La raison pour laquelle je trouve cela étrange, c’est que j’ai ajouté le framework Lombok et les annotations @ Slf4j qui fonctionnent. J'ai ajouté Lombok en tant que dépendance dans le fichier pav.xml:

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.14.8</version>
</dependency>

Et je peux utiliser l'annotation de classe @ Sl4fj pour ajouter un enregistreur à la classe sans encombrer les variables membres:

@Slf4j
public class App {
  public void logsome(){
    log.info("Hello there");
  }
}

Donc, si cela est possible en ajoutant simplement une dépendance, je pense qu'il me manque une dépendance ou une configuration pour obtenir le travail d'annotation codahale @Timed, comme décrit ci-dessus.

(Soit dit en passant, consultez Lombok, cela vous facilitera la vie: http://projectlombok.org/ )

33
Rolf

En résumé, vous ne pouvez pas utiliser @Timed sans une sorte d'AOP (que ce soit Spring AOP ou AspectJ).

Il y a une semaine ou deux, j'ai également décidé d'ajouter des mesures à notre projet et de choisir AspectJ pour cette tâche (principalement parce que je l'utilisais auparavant dans un but similaire et parce qu'il permet le tissage à la compilation, tandis que Spring n'autorise que l'exécution par le biais de serveurs proxy .

Vous devriez pouvoir trouver toutes les informations et instructions nécessaires ici: https://github.com/astefanutti/metrics-aspectj .

En ce qui concerne Lombok, je suppose qu’ils utilisent un processeur d’annotations javac intégré:

Un autre point de discorde est la mise en œuvre du code prenant en charge l'intégration IDE ainsi que du processeur d'annotation javac. Ces deux éléments du projet Lombok utilisent des API non publiques pour mener à bien leurs activités de sorcellerie. Cela signifie que le projet Lombok risque d’être rompu avec les versions ultérieures de IDE ou du JDK.

16
Andrew Logvinov

Utiliser @Timed ne nécessite pas réellement l'utilisation de AOP, comme cela avait déjà été dit dans la réponse de choix, si vous êtes à l'intérieur d'un conteneur et utilisez l'une des bibliothèques d'instrumentation de Dropwizard. Voir le module Jersey 2.x, par exemple, dont vous pouvez voir qu'il utilise la réflexion (comme les autres que j'ai examinés), si vous lisez le source .

Vous pouvez consulter tous ces modules dans dans la documentation Dropwizard sous les puces "Instrumenting ____" correspondantes.

Je comprends que le PO ne fonctionnait pas explicitement dans un tel conteneur, mais je voulais offrir cette information, car beaucoup d’entre nous qui recherchent cette réponse travaillent peut-être sur un service Web moderne pouvant enregistrer de telles ressources dans son environnement d’exécution.

11
Michael Zalimeni

Utilisez MetricRegistry intégré, accessible à partir du paramètre bootstrap de la méthode initialize de votre classe d'application.

@Override
public void initialize(final Bootstrap<Configuration> bootstrap) {
    final JmxReporter reporter = JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build();
    reporter.start();
}
5
joev

AOP est excessif et ne convient pas pour l'utilisation de @timed, en général Parlant.

Le registre de métriques par défaut écrit des métriques @timed sur un ConcurrentHashMap et ne joint aucun écouteur significatif.

DropWizard Bootstrap constructeur:

/**
 * Creates a new {@link Bootstrap} for the given application.
 * @param application a Dropwizard {@link Application}
 */
public Bootstrap(Application<T> application) {
    this.application = application;
    this.objectMapper = Jackson.newObjectMapper();
    this.bundles = Lists.newArrayList();
    this.configuredBundles = Lists.newArrayList();
    this.commands = Lists.newArrayList();
    this.validatorFactory = Validators.newValidatorFactory();


    // returns new ConcurrentHashMap<String, Metric>(); 
    this.metricRegistry = new MetricRegistry(); 


    this.configurationSourceProvider = new FileConfigurationSourceProvider();
    this.classLoader = Thread.currentThread().getContextClassLoader();
    this.configurationFactoryFactory = new DefaultConfigurationFactoryFactory<T>();
}

Vous devez donc créer/démarrer/enregistrer le registre de mesures approprié dans afin de voir les résultats.

Ici j'utilise JMX:

@Override
public void initialize(Bootstrap<PayloadStorageConfiguration> bootstrap) {
    JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build().start();
}

C'est tout ce que vous devez faire.

Voici un exemple de sortie (exécutez jconsole sur votre application/serveur Java pour afficher les résultats JMX):

 enter image description here

3
Robert Christian

Comme l’a dit l’autre réponse, vous devez disposer de quelque chose dans l’application pour écouter vos classes instanciées et les vérifier pour l’annotation @Timed.

Si vous utilisez Guice, vous pouvez utiliser: https://github.com/palominolabs/metrics-guice

3
woxwoxwoxwox

Dans les versions plus récentes de Dropwizard (j'utilise la version 0.9.2), vous pouvez accéder à la variable MetricRegistry par défaut via l'environnement d'installation io.dropwizard.setup.Environment. Cette variable par défaut MetricRegistry est déjà associée à une variable InstrumentedResourceMethodApplicationListener qui écoute toutes les métriques de vos ressources.

Si vous avez enregistré une ressource avec la variable JerseyEnvironment sous, 

environment.jersey().register(resource);

vous devez simplement annoter votre méthode de ressource (ou classe) avec @Timed, @Metered ou @ExceptionMetered pour enregistrer les métriques respectives.

@POST
@Timed
public String show() {
    return "yay";
}

Vous pouvez assigner une Reporter (comme un Slf4jReporter ou JmxReporter) à la valeur par défaut MetricRegistry comme sous

Slf4jReporter.forRegistry(environment.metrics()).build();

Pour vérifier rapidement si vos métriques ont bien été enregistrées, vous pouvez appeler GET l'URL http://localhost:8081/metrics ou l'URL métrique Admin correspondante dans votre environnement de test.

Certaines autres versions nécessitent que vous enregistriez explicitement une InstrumentedResourceMethodApplicationListener comme indiqué dans ce document

1
Faraz

Vous pouvez également utiliser stagemonitor-core pour cela. Voir la documentation ici et ici . L'avantage est que stagemonitor (qui est libre et open source btw) ne dépend d'aucun AOP basé sur un conteneur, comme les intercepteurs Spring AOP ou EJB. Il utilise une manipulation de code binaire via une pièce jointe à l'exécution, ce qui signifie que vous n'avez même pas besoin d'ajouter un indicateur -javaagent au démarrage de votre application. Une simple dépendance suffit.

Si vous souhaitez mesurer le temps d'exécution dans une application Web ou dans une application EJB distante, vous n'avez même pas besoin d'annoter manuellement votre code. De plus, stagemonitor propose des tableaux de bord préconfigurés Grafana et Kibana.

Disclaimer: Je suis l'un des développeurs de Stimonitor

0
Felix

cet exemple simple/droit au point https://karollotkowski.wordpress.com/2015/10/19/api-endpoint-in-one-minute-with-dropwizard/ vient de le montrer l'annotation

 enter image description here

0
gli00001