web-dev-qa-db-fra.com

Compteurs métriques DropWizard et minuteries

J'apprends ancienne métrique de Coda Hale (bibliothèque DropWizard Metrics) et je ne sais pas trop quand je devrais utiliser Meters vs Timers. Selon les docs:

Compteur: Un compteur mesure la vitesse à laquelle un ensemble d'événements se produit.

et:

Minuterie: Une minuterie est essentiellement un histogramme de la durée d'un type d'événement et un compteur du taux de son occurrence.

Sur la base de ces définitions, je ne peux pas discerner la différence entre celles-ci. Ce qui me dérange, c'est que Timer n'est pas utilisé comme je l'aurais prévu. Pour moi, Timer n’est que cela: une minuterie; il devrait mesurer le diff de temps entre un start() et stop(). Mais il semble que Timers saisisse également les taux d'événements, ce qui donne l'impression qu'ils marchent sur Meters orteils.

Si je pouvais voir un exemple des sorties de chaque composant, cela pourrait m'aider à comprendre quand et où utiliser l'un ou l'autre.

62
smeeb

Vous êtes en partie dérouté, car une minuterie métrique DW [~ # ~] est [~ # ~] , entre autres choses, un compteur métrique DW.

Un compteur est exclusivement concerné par les débits, mesurés en Hz (événements par seconde). Chaque compteur donne lieu à la publication de 4 (?) Métriques distinctes:

  • un taux moyen (moyen) depuis le démarrage de Metrics
  • Taux moyens glissants sur 1, 5 et 15 minutes

Vous utilisez un multimètre en enregistrant une valeur à différents points de votre code - DW Metrics note automatiquement la durée du mur de chaque appel avec la valeur que vous lui avez attribuée, et les utilise pour calculer la vitesse à laquelle cette valeur augmente:

Meter getRequests = registry.meter("some-operation.operations")
getRequests.mark() //resets the value, e.g. sets it to 0
int numberOfOps = doSomeNumberOfOperations() //takes 10 seconds, returns 333
getRequests.mark(numberOfOps) //sets the value to number of ops.

Nous nous attendions à ce que nos tarifs soient de 33,3 Hz, car 333 opérations ont eu lieu et le temps entre les deux appels à mark () était de 10 secondes.

Un minuteur calcule ces 4 métriques ci-dessus (en considérant chaque événement Timer.Context comme un événement) et leur ajoute un certain nombre de métriques supplémentaires:

  • un décompte du nombre d'événements
  • durées min, moyenne et maximale observées depuis le début de la métrique
  • déviation standard
  • un "histogramme", enregistrant la durée répartie aux 50ème, 97ème, 98ème, 99ème et 99.95 centiles

Il y a environ 15 métriques totales rapportées pour chaque minuteur.

En bref: Les minuteries rapportent BEAUCOUP de mesures, et elles peuvent être difficiles à comprendre, mais une fois que vous les avez faites, elles constituent un moyen assez puissant de repérer les comportements épineux.

Le fait est que collecter simplement le temps passé entre deux points n’est pas une mesure très utile. Considérez: vous avez un bloc de code comme ceci:

Timer timer = registry.timer("costly-operation.service-time")
Timer.Context context = timer.time()
costlyOperation() //service time 10 ms
context.stop()

Supposons que costlyOperation () ait un coût constant, une charge constante et fonctionne sur un seul thread. Dans une période de compte rendu d'une minute, nous devrions nous attendre à ce que cette opération soit programmée 6000 fois. De toute évidence, nous ne communiquerons pas le temps de service réel sur le réseau 6000x; nous aurons plutôt besoin d’un moyen de récapituler toutes ces opérations pour qu’elles correspondent à la fenêtre de rapport souhaitée. Le minuteur de DW Metrics le fait pour nous, automatiquement, une fois par minute (notre période de rapport). Après 5 minutes, notre registre de mesures rapporterait:

  • un taux de 100 (événements par seconde)
  • un taux moyen de 1 minute de 100
  • un taux moyen de 100 minutes sur 5 minutes
  • un compte de 30000 (total des événements vus)
  • un maximum de 10 (ms)
  • un min de 10
  • une moyenne de 10
  • 50ème percentile (p50) valeur de 10
  • une valeur de 99,9e centile (p999) de 10

Considérons maintenant que nous entrons dans une période où, occasionnellement, notre opération passe complètement à l'écart du Rails) et bloque pendant une période prolongée:

Timer timer = registry.timer("costly-operation.service-time")
Timer.Context context = timer.time()
costlyOperation() //takes 10 ms usually, but once every 1000 times spikes to 1000 ms
context.stop()

Sur une période de collecte d'une minute, nous aurions maintenant moins de 6000 exécutions, car chaque millième exécution prend plus de temps. Cela correspond à environ 5505. Après la première minute (temps système total de 6 minutes), nous verrions maintenant:

  • un taux moyen de 98 (événements par seconde)
  • un taux moyen de 1 minute de 91,75
  • un taux moyen de 5 minutes de 98,35
  • un compte de 35505 (total des événements vus)
  • une durée maximale de 1000 (ms)
  • une durée minimale de 10
  • une durée moyenne de 10,13
  • 50ème percentile (p50) valeur de 10
  • une valeur de 99,9e centile (p999) de 1000

Si vous présentiez cela sous forme de graphique, vous constateriez que la plupart des demandes (les p50, p75, p99, etc.) étaient terminées en 10 ms, mais qu'une demande sur 1 000 (p99) était achevée en 1. Cela serait également perçu comme une légère réduction du taux moyen (environ 2%) et une réduction appréciable de la moyenne sur une minute (près de 9%).

Si vous ne regardez que les moyennes temporelles (soit le taux, soit la durée), vous ne remarquerez jamais ces pics - ils sont entraînés dans le bruit de fond par la moyenne de nombreuses opérations réussies. De même, connaître le max n'est pas utile, car cela ne vous dit pas à quelle fréquence le max se produit. C'est pourquoi les histogrammes sont un puissant outil de suivi des performances et que le minuteur de DW Metrics publie à la fois un taux ET un histogramme.

135