![[17.0.0.3 and later]](../ng_v17003plus.gif)
API d'instrumentation de MicroProfile metrics
Vous pouvez utiliser l'API MicroProfile metrics pour ajouter des métriques à vos applications. L'API MicroProfile metrics est similaire à l'API Dropwizard metrics.
Architecture de MicroProfile metrics
- Base
- Le registre de base est utilisé pour les métriques du serveur conformément aux besoins spécifiés par la spécification de MicroProfile metrics.
- Fournisseur
- Le registre fournisseur est utilisé pour les métriques qui sont ajoutées par le fournisseur du produit, dans ce cas Liberty.
- Application
- Le registre d'application est utilisé pour les métriques qui sont ajoutées par vos applications. Le registre d'application par défaut est MetricRegistry.
Les fonctions mpMetrics-1.0 et mpMetrics-1.1 incluent également un noeud final /metrics, qui fournit l'interface HTTP pour l'interaction avec les navigateurs et les outils de contrôle.
Vérification des valeurs des métriques
Les métriques MicroProfile fournissent un noeud final /metrics auquel vous pouvez accéder via HTTP. Une fois que le serveur Liberty est démarré avec la configuration adéquate, vous pouvez afficher vos métriques à partir de n'importe quel navigateur.
https://localhost:9443/metrics
En général, les équipes des opérations configurent les outils pour contrôler et enregistrer les valeurs des métriques dans le temps.
Ajout de métriques à vos applications
- Directement à l'aide de MetricRegistry. Si vous utilisez cette méthode, votre code d'application crée explicitement les métriques et les enregistre.
- En utilisant CDI pour injecter des métriques. Si vous utilisez cette méthode, les métriques sont implicitement créées par CDI et enregistrées dans l'application MetricRegistry.
- En utilisant les annotations de métriques. Si vous utilisez cette méthode, les métriques sont implicitement créées par CDI et enregistrées dans l'application MetricRegistry.
Administration directe de MetricRegistry
MetricRegistry stocke toutes les métriques et leurs métadonnées respectives. Les métriques et les métadonnées peuvent être enregistrées et extraites à l'aide des méthodes fournies. Par défaut, toutes les métriques relatives aux applications sont ajoutées à une seule instance MetricRegistry étendue aux applications.
@Inject
MetricRegistry registry;
Enregistrement des métriques
La classe MetricRegistry possède des méthodes qui permettent d'extraire ou de créer des compteurs, des mètres, des histogrammes et des temporisateurs.
Metadata counterMetadata = new Metadata(…);
…
// Create or retrieve the metric by Metadata.getName()
Counter counterMetric = registry.counter(counterMetadata);
Timer timerMetric = registry.timer(timerMetadata);
Histogram histogramMetric = registry.histogram(histogramMetadata);
Meter meterMetric = registry.meter(meterMetadata);
// Register a gauge metric by Metadata.getName()
registry.register("gaugeMetric", gaugeMetric, gaugeMetadata);
Description des métriques avec des métadonnées
Les métadonnées sont un ensemble de données qui décrivent et résument les informations sur les métriques et facilitent la recherche et l'utilisation des différents types de métriques. Les métadonnées peuvent être suffisamment précises pour définir des informations au niveau des attributs.
Les métadonnées de métriques sont composées des attributs suivants :
- Unit
- Ensemble fixe d'unités de chaîne.
- Type
- Jauge, compteur, mètre, histogramme ou temporisateur.
- Description
- Description lisible par l'homme de la métrique.
- DisplayName
- Nom lisible par l'homme de la métrique à des fins d'affichage, si le nom de la métrique n'est pas lisible par l'homme, par exemple, lorsque le nom est un UUID.
- Tags
- Liste de paires clé-valeur (key=value), séparées par des virgules.
Reusable
A partir de la version 1.1 de MicroProfile Metrics, reusable est un booléen qui indique que le nom de métrique peut être réutilisé. Par exemple, si vous souhaitez réutiliser une seule métrique lorsque vous annotez plusieurs méthodes.
export MP_METRICS_TAGS=app=shop,node=2932
Vous pouvez également utiliser MicroProfile config pour configurer MP_METRICS_TAGS. Pour en savoir plus sur la configuration de MP_METRICS_TAGS, voir Emplacements des valeurs de configuration valides dans l'environnement d'exécution Liberty.
Compteurs
Les compteurs sont des métriques qui sont utilisées pour calculer une valeur à la hausse ou à la baisse. La valeur initiale du compteur est définie sur 0 et peut être incrémentée avec inc() ou inc(long n) et décrémentée avec dec() ou dec(long n).
Vous pouvez utiliser un compteur pour compter le nombre total de demandes reçues ou le nombre total de sessions HTTP actives simultanément.
Metadata statsHitsCounterMetadata = new Metadata(
"statsHits", // name
"Stats Hits", // display name
"Number of hits on the /stats endpoint", // description
MetricType.COUNTER, // type
MetricUnits.NONE); // units
Counter statsHitsCounter = registry.counter(statsHitsCounterMetadata);
@GET
@Path("/donations")
public String getTotalDonations() {
statsHitsCounter.inc();
return "$" + donationManager.getTotalDonations();
}
curl -k -u user:password https://localhost:9443/metrics/application/statsHits
# TYPE application:stats_hits counter
# HELP application:stats_hits Number of hits on the /stats endpoint
application:stats_hits 213
curl -k -u user:password -H “Accept: application/json” https://localhost:9443/metrics/application/statsHits
{"statsHits":213}
Jauges
Les jauges représentent des métriques qui sont échantillonnées pour obtenir leur valeur.
Une jauge est une interface qui a besoin d'être implémentée par le développeur. Comme l'implémentation d'une jauge n'est pas définie, elles doivent être enregistrées manuellement dans MetricRegistry à l'aide de la méthode .register() de MetricRegistry. Vérifiez que register() n'est utilisé qu'une fois par métrique. Vous ne pouvez pas enregistrer deux métriques sous le même nom. Vous utilisez une jauge pour mesurer la température de l'unité centrale ou pour mesurer le pourcentage d'utilisation du disque.
Gauge<Double> progressGauge = new Gauge<Double>() {
public Double getValue() {
return (double) getTotalDonations()
/ (double) getGoal() * 100.0;
}
};
// Gauge
Metadata progressMetadata = new Metadata(
"progress", // name
"Donation Progress", // display name
"The percentage of the goal achieved so far", // description
MetricType.GAUGE, // type
MetricUnits.PERCENT); // units
registry.register(progressMetadata.getName(), progressGauge, progressMetadata);
curl -k -u user:password https://localhost:9443/metrics/application/progress
# TYPE application:progress_percent gauge
# HELP application:progress_percent The percentage of the goal achieved so far
application:progress_percent 4.472
curl -k -u user:password -H "Accept: application/json" https://localhost:9443/metrics/application/progress
{"progress":4.472}
Mètres
Les mètres sont utilisés pour contrôler le débit.
- Débit moyen.
- Débit moyen mobile pondéré exponentiellement de une/cinq/quinze minutes.
- Calcul du nombre de mesures.
Vous pouvez utiliser un mètre pour calculer le taux de transactions qui sont traitées par une application.
Metadata getProgressMeterMetadata = new Metadata(
"getProgressMeter", // name
"getProgress Call Rate", // display name
"The rate of getProgress calls", // description
MetricType.METERED, // type
MetricUnits.SECONDS); // units
Meter getProgressMeter = registry.meter(getProgressMeterMetadata);
public Double getProgress() {
getProgressMeter.mark();
return (double) getTotalDonations()/(double) getGoal() * 100.0;
}
curl -k -u user:password https://localhost:9443/metrics/application/getProgressMeter1
# TYPE application:get_progress_meter_total counter
# HELP application:get_progress_meter_total The rate of getProgress calls
application:get_progress_meter_total 78
# TYPE application:get_progress_meter_rate_per_second gauge
application:get_progress_meter_rate_per_second 0.6584919803150174
# TYPE application:get_progress_meter_one_min_rate_per_second gauge
application:get_progress_meter_one_min_rate_per_second 0.5851884005757912
# TYPE application:get_progress_meter_five_min_rate_per_second gauge
application:get_progress_meter_five_min_rate_per_second 1.4218610926179416
# TYPE application:get_progress_meter_fifteen_min_rate_per_second gauge
application:get_progress_meter_fifteen_min_rate_per_second 1.6627979138032118
curl -k -u user:password -H "Accept: application/json" https://localhost:9443/metrics/application/getProgressMeter
{
"getProgressMeter": {
"count": 78,
"fifteenMinRate": 1.6627979138032118,
"fiveMinRate": 1.4218610926179416,
"meanRate": 0.6584919803150174,
"oneMinRate": 0.5851884005757912
}
}
Histogrammes
Les histogrammes sont utilisés pour stocker la distribution des valeurs.
Pour enregistrer une valeur dans l'histogramme, vous devez appeler histogram.update(long value) avec la valeur que vous souhaitez enregistrer. L'état en cours (ou instantané) de l'histogramme peut être extrait avec getSnapshot(). Les histogrammes dans MicroProfile Metrics prennent uniquement en charge les nombres entiers ou les valeurs longues.
- Valeurs max/min/moy
- La valeur au 50ème, 75ème, 95ème, 98ème, 99ème, 99,9ème percentile
- Un calcul du nombre de valeurs
Exemples d'histogrammes : Distribution des tailles de charges utiles extraites ou, pour une enquête d'intégration, distribution des revenus des ménages.
Metadata donationDistributionMetadata = new Metadata(
"donationDistribution", // name
"Donation Distribution", // display name
"The distribution of the donation amounts ", // description
MetricType.HISTOGRAM, // type
“dollars”); // units
Histogram donationDistribution = registry.histogram(donationDistributionMetadata);
public void addDonation(Long amount) {
totalDonations += amount;
donations.add(amount);
donationDistribution.update(amount);
}
curl -k -u user:password https://localhost:9443/metrics/application/com.example.samples.donationapp.DonationManager.donationDistribution
# TYPE application:com_example_samples_donationapp_donation_manager_donation_distribution_mean_dollars gauge
application:com_example_samples_donationapp_donation_manager_donation_distribution_mean_dollars 19.300015535407777
# TYPE application:com_example_samples_donationapp_donation_manager_donation_distribution_max_dollars gauge
application:com_example_samples_donationapp_donation_manager_donation_distribution_max_dollars 102.0
# TYPE application:com_example_samples_donationapp_donation_manager_donation_distribution_min_dollars gauge
application:com_example_samples_donationapp_donation_manager_donation_distribution_min_dollars 3.0
# TYPE application:com_example_samples_donationapp_donation_manager_donation_distribution_stddev_dollars gauge
application:com_example_samples_donationapp_donation_manager_donation_distribution_stddev_dollars 26.35464238355834
# TYPE application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars summary
# HELP application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars The distribution of the donation amounts
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars_count 203
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars{quantile="0.5"} 5.0
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars{quantile="0.75"} 24.0
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars{quantile="0.95"} 83.0
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars{quantile="0.98"} 93.0
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars{quantile="0.99"} 101.0
application:com_example_samples_donationapp_donation_manager_donation_distribution_dollars{quantile="0.999"} 102.0
curl -k -u user:password -H "Accept: application/json" https://localhost:9443/metrics/application/com.example.samples.donationapp.DonationManager.donationDistribution
{
"com.example.samples.donationapp.DonationManager.donationDistribution": {
"count": 203,
"max": 102,
"mean": 19.300015535407777,
"min": 3,
"p50": 5.0,
"p75": 24.0,
"p95": 83.0,
"p98": 93.0,
"p99": 101.0,
"p999": 102.0,
"stddev": 26.35464238355834
}
}
Temporisateurs
Les temporisateurs sont utilisés pour ajouter des durées de minutage, en nanosecondes, et pour fournir des statistiques sur la durée et le débit.
Pour temporiser une portion du code, vous pouvez appeler timer.time(), qui renvoie un objet timer.context. Ce contexte est utilisé pour arrêter le temporisateur en appelant context.close(). Les informations qui sont extraites du temporisateur sont une combinaison d'un compteur et d'un histogramme des durées temporisées.
- Temps max/min/moy.
- Valeur temporelle au 50ème, 75ème, 95ème, 98ème, 99ème, 99,9ème percentile.
- Débit moyen.
- Débit moyen mobile pondéré exponentiellement de une/cinq/quinze minutes.
- Calcul du nombre d'événements temporisés.
Par exemple, vous pouvez utiliser un temporisateur pour mesurer des temps de réponse et mesurer le temps de traitement pour une logique complexe.
Metadata topDonationCalcTimerMetadata = new Metadata(
"topDonationCalcTimer", // name
"Top Donation Calculation Time", // display name
"Processing time to find the top donation", // description
MetricType.TIMER, // type
MetricUnits.NANOSECONDS); // units
Timer topDonationCalcTimer = registry.timer(topDonationCalcTimerMetadata);
public Long getTopDonation() {
// Start timing here
Timer.Context context = topDonationCalcTimer.time();
Long max = 0L;
for (Long amount : donationManager.getDonationsList()) {
max = amount > max ? amount : max;
}
// Stop timing
context.close();
return max;
}
curl -k -u user:password https://localhost:9443/metrics/application/topDonationCalcTimer
# TYPE application:top_donation_calc_timer_rate_per_second gauge
application:top_donation_calc_timer_rate_per_second 0.19107302754898328
# TYPE application:top_donation_calc_timer_one_min_rate_per_second gauge
application:top_donation_calc_timer_one_min_rate_per_second 0.013233974568205872
# TYPE application:top_donation_calc_timer_five_min_rate_per_second gauge
application:top_donation_calc_timer_five_min_rate_per_second 0.4845914744130395
# TYPE application:top_donation_calc_timer_fifteen_min_rate_per_second gauge
application:top_donation_calc_timer_fifteen_min_rate_per_second 0.8866728789348088
# TYPE application:top_donation_calc_timer_mean_seconds gauge
application:top_donation_calc_timer_mean_seconds 9.37780684853573E-5
# TYPE application:top_donation_calc_timer_max_seconds gauge
application:top_donation_calc_timer_max_seconds 1.97197E-4
# TYPE application:top_donation_calc_timer_min_seconds gauge
application:top_donation_calc_timer_min_seconds 4.9630000000000004E-5
# TYPE application:top_donation_calc_timer_stddev_seconds gauge
application:top_donation_calc_timer_stddev_seconds 3.082659934664267E-5
# TYPE application:top_donation_calc_timer_seconds summary
# HELP application:top_donation_calc_timer_seconds Processing time to find the top donation
application:top_donation_calc_timer_seconds_count 63
application:top_donation_calc_timer_seconds{quantile="0.5"} 8.6069E-5
application:top_donation_calc_timer_seconds{quantile="0.75"} 1.0372E-4
application:top_donation_calc_timer_seconds{quantile="0.95"} 1.53694E-4
application:top_donation_calc_timer_seconds{quantile="0.98"} 1.96615E-4
application:top_donation_calc_timer_seconds{quantile="0.99"} 1.97197E-4
application:top_donation_calc_timer_seconds{quantile="0.999"} 1.97197E-4
curl -k -u user:password -H "Accept: application/json" https://localhost:9443/metrics/application/topDonationCalcTimer
{
"topDonationCalcTimer": {
"count": 63,
"fifteenMinRate": 0.8866728789348088,
"fiveMinRate": 0.4845914744130395,
"max": 197197,
"mean": 93778.06848535729,
"meanRate": 0.19107302754898328,
"min": 49630,
"oneMinRate": 0.013233974568205872,
"p50": 86069.0,
"p75": 103720.0,
"p95": 153694.0,
"p98": 196615.0,
"p99": 197197.0,
"p999": 197197.0,
"stddev": 30826.599346642666
}
}
Injection de métriques avec CDI
- @Metric : Annotation qui décrit la métrique injectée. Cette annotation peut être utilisée sur les zones de type Mètre, Temporisateur, Compteur et Histogramme.
- Paramètres de @Metric : name, displayname, units, tags, description, absolute.
Les paramètres de l'annotation @Metric sont similaires à la zone de métadonnées correspondante, avec les différences suivantes.Le serveur crée et enregistre un compteur dans MetricRegistry et le met à la disposition de l'application. L'exemple de compteur est équivalent à l'exemple de statsHitsCounter. absolute=true signifie que le nom fourni est utilisé tel quel. Le paramètre units n'est pas utilisé et est défini par défaut sur MetricUnits.NONE.
- tags : tableau de chaînes de balises key=value
- absolute : si la valeur est true, définissez le nom de la métrique sur le nom exact qui est spécifié dans le paramètre name. Si la valeur est false, utilisez le nom complet en ajoutant un préfixe à la classe et au nom du package.
@Inject @Metric(name="statsHits", displayName="Stats Hits", description="Number of hits on the /stats endpoint", absolute=true) Counter statsHitsCounter;
@Inject @Metric(name= "topDonationCalcTimer", unit = MetricUnits.NANOSECONDS, description="Processing time to find the top donation") Timer topDonationCalcTimer; @Inject @Metric(absolute = true, tags=["appName=DonationApp"]) Counter counted;
Annotation des métriques
MicroProfile metrics utilise plusieurs intercepteurs pour traiter les annotations @Counted, @Timed, @Metered et @Gauge.
- @Counted
- Annotation permettant de marquer une méthode, un constructeur ou un type en tant que compteur. En plus des zones de métadonnées, le compteur possède également une zone monotone additionnelle. Si monotonic est défini sur false, le compteur est incrémenté lorsque la méthode annotée est appelée et il est décrémenté lorsque la méthode annotée est renvoyée, en comptant les appels en cours de la méthode annotée. Si monotonic est défini sur true, le compteur augmente de manière monotone en comptant les appels totaux de la méthode annotée.Remarque : Par défaut, monotonic est défini sur false.
@GET @Path("/no") @Counted(name="no", displayName="No donation count", description="Number of people that declined to donate.", monotonic=true) public String noDonation() { return "Maybe next time!"; }
- @Timed
- Annotation permettant de marquer un constructeur ou une méthode d'un objet annoté comme temporisé. La métrique du temporisateur contrôle la fréquence avec laquelle l'objet annoté est démarré et la durée d'exécution des appels.
@POST @Path("/creditcard") @Timed( name="donateAmountViaCreditCard.timer", displayName="Donations Via Credit Cards", description = "Donations that were made using a credit card") public String donateAmountViaCreditCard(@FormParam("amount") Long amount, @FormParam("card") String card) { if (processCard(card, amount)) return "Thanks for donating!"; return "Sorry, please try again."; }
- @Metered
- Annotation permettant de marquer un constructeur ou une méthode comme étant mesuré(e). Le mètre compte les appels du constructeur ou de la méthode et contrôle la fréquence avec laquelle ils sont appelés.
@Metered(displayName="Rate of donations", description="Rate of incoming donations (the instances not the amount)") public void addDonation(Long amount) { totalDonations += amount; donations.add(amount); donationDistribution.update(amount); }
- @Gauge
- Annotation permettant de marquer une méthode en tant que jauge.
@Gauge( name="donations", displayName="Total Donations", description="Total amount of money raised for charity!", unit = "dollars", absolute=true) public Long getTotalDonations(){ return totalDonations; }
![[18.0.0.1 and later]](../ng_v18001plus.gif)
- Réutilisation des métriques
- A partir de la version 1.1 de MicroProfile metrics, les métriques peuvent être réutilisées. Les annotations @Counted, @Metered et @Timed ont un indicateur pour indiquer que la métrique peut être réutilisée par d'autres annotations. Par exemple, votre application peut avoir plusieurs noeud finaux pour les différentes méthodes de paiement. Pour contrôler le nombre de paiements à travers toutes les méthodes de paiement, vous pouvez utiliser le même nom de métrique en définissant reusable=true. Les exemples suivants illustrent des utilisations types.
@POST @Path("/creditcard") @Counted( name="donation.counter", displayName="Number of donations", description = "Donations that were made using any method", monotonic=true, reusable=true) public String donateAmountViaCreditCard(@FormParam("amount") Long amount, @FormParam("card") String card) { if (processCard(card, amount)) return "Thanks for donating!"; return "Sorry, please try again."; }
@POST @Path("/debitcard") @Counted( name="donations.counter", displayName="Number of donations", description = "Donations that were made using any method", monotonic=true, reusable=true) public String donateAmountViaDebitCard(@FormParam("amount") Long amount, @FormParam("card") String card) { if (processDebitCard(card, amount)) return "Thanks for donating!"; return "Sorry, please try again."; }
Recommandations relatives à CDI
La fonction mpMetrics-1.0 repose sur CDI. L'injection via CDI est utilisée lorsque vous souhaitez injecter un MetricRegistry ou pour injecter l'un des types de métriques dans une zone. Les intercepteurs de CDI sont utilisés pour appliquer les métriques @Timed, @Counted, @Metered et @Gauge aux types, constructeurs ou méthodes.
- Utilisation des archives de bean
- Pour un démarrage efficace des applications, vérifiez que vos archives de bean contiennent un fichier beans.xml. Si vous créez une application Web, votre fichier beans.xml doit se trouver dans le répertoire WEB-INF. Si vous créez un module EJB ou un fichier JAR, votre fichier beans.xml doit se trouver dans le répertoire META-INF. En évitant la fonction d'archive de bean implicite dans vos applications, vous pouvez optimiser votre serveur Liberty pour éviter la recherche d'archives de bean au démarrage.
- Limitations des intercepteurs @Timed, @Counted, @Metered, @Gauge
- CDI repose sur des intercepteurs Java pour les annotations de métriques qui sont implémentées dans Liberty en tant qu'intercepteurs. Les annotations @Timed, @Counted, @Metered et @Gauge sont implémentées à l'aide des intercepteurs. Les intercepteurs ont besoin de pouvoir créer un proxy pouvant être démarré sur le chemin de code avant de pouvoir appeler les constructeurs ou les méthodes avec les annotations d'intercepteurs. Le code d'intercepteur est l'endroit où les métriques sont mises à jour. Des limites existent au niveau du type de code pouvant être en proxy et quant à l'endroit où les annotations d'intercepteurs peuvent être utilisées. Seuls les beans gérés définis par CDI qui peuvent être mis en proxy peuvent être utilisés avec les intercepteurs. Les proxy sont implémentés en tant que sous-classes du bean qu'ils mettent en proxy. Pour s'assurer qu'une classe peut être mise en proxy, la classe ne doit pas être marquée comme finale et doit/// and must a non-private, no-args constructor.
- Limitations de l'injection
- Pour injecter des types tels qu'un MetricRegistry dans une classe, cette classe doit être gérée par CDI. L'exemple de JAX-RS suivant illustre un appel automatique de someclass.setMetricsRegistry par CDI.
La classe n'est pas appelée dans l'exemple suivant :@Path("/myPath") public class MyService { // lifecyle of Someclass will be managed by CDI @Inject Someclass someclass; ... } public class Someclass { // Someclass was injected and is managed by CDI and therefore can use @Inject // setMetricRegistry will be called before the first method call to Someclass @Inject public void setMetricRegistry(final MetricRegistry metrics) { } }
@Path("/myPath") public class MyService { // CDI doesn't manage lifecycle of Someclass Someclass someclass = new Someclass(); ... } public class Someclass { // This method will never be called by CDI since Someclass was not created with CDI @Inject public void setMetricRegistry(MetricRegistry metrics) { } }