Custom Metrics in de praktijk

Metrieken over applicaties worden steeds belangrijker. Harde getallen, zoals gebruikersaantallen, responstijden of conversieratio’s, kunnen een goede, objectieve graadmeter zijn voor succes en het bewijs dat de applicatie de investering waard is. Daarnaast is het belangrijk, in de sneller veranderende wereld van continuous delivery en agile ontwikkeling, om vlotte feedback loops te hebben hoe de applicatie het in productie doet. Alleen de “standaard” metrieken, zoals cpu gebruik of aantallen http requests, zijn niet goed genoeg. We hebben behoefte aan onze eigen custom metrics.

Helaas zijn metrieken vaak een flinke uitdaging. Er zijn allerlei tools te vinden die bakken algemene meetpunten aanbieden, die echter niet altijd even nuttig zijn. Daarnaast zijn deze tools soms duur qua licenties en benodigde infrastructuur of hebben een merkbare impact op performance en beschikbaarheid. Ook kunnen metrieken verkeerd geïnterpreteerd worden binnen het team; of er kan een “metrieken-blindheid” ontstaan, waarin andere nuttige feedback die niet in een getal past wegvalt. In dit artikel daarom een aantal praktische tips hoe metrics gemakkelijk geïntroduceerd kunnen worden, met nauwelijks technische impact.

Metrieken voor iedereen

Metrieken kunnen voor iedereen interessant zijn. Enkele voorbeelden:

Infrastructuur:

  • Gebruik van CPU, geheugen en disk

  • Beschikbaarheid

Software ontwikkeling:

  • Hoe vaak treedt een bepaalde exception op in productie?

  • Hoe vaak wordt een specifieke service operatie aangeroepen?

Business:

  • Hoe snel heeft een medewerker een order verwerkt?

  • Hoe vaak retourneert een zoekfunctie in één keer het gewenste resultaat?

Bedenk metrieken als team

Het is verstandig om als team een gezamenlijke discussie te hebben over nieuwe metrieken:

  • Welk besluit wordt ondersteund door de metriek? Bijvoorbeeld: als een zoekfunctie bijna nooit direct het goede resultaat oplevert, wie gaat daar wat mee doen? Dit maakt snel helder hoe waardevol de metriek is, en wie ze echt in de gaten moet gaan houden.

  • Welke waarde, of trend (waardeverandering over tijd) heeft een bijzondere betekenis? Als dit onduidelijk is moet de meting waarschijnlijk worden aangepast.

  • Is de meting mogelijk, en wat zijn eventueel nadelige effecten (kosten, performance, complexiteit of privacy)? Het is meestal handig om met goedkope, simpele metrieken te beginnen, en pas later in meer details te investeren als de eerste stappen waardevol blijken.

Voor een goede inspiratie is het boek “How to Measure Anything” [1] een aanrader! Na deze discussie is er een gedeeld besef van mogelijke metrieken, wat ze betekenen, en voor wie ze waardevol zijn. Dit overzicht kan bijvoorbeeld gemakkelijk op een wiki worden vastgelegd. Nu kunnen deze metrieken stapsgewijs geïntroduceerd worden in de applicatie in productie.

Counters vs event storage

Metrieken opbouwen kan grof gezegd op twee manieren: interessante gebeurtenissen (events) opslaan, of onmiddellijk optellen in een metric (met zogenaamde counters). Het voordeel van event storage is dat nieuwe metrieken met terugwerkende kracht kunnen worden bedacht, en complexere analyses buiten de applicatie om gedaan kunnen worden. Het nadeel is vaak flinke kosten voor de bergen events die moeten worden opgeslagen en ingewikkelde gespecialiseerde tools die nodig zijn voor de opslag en analyse. Dit artikel begint met een “counter” aanpak, waar simpele custom metrieken mee gemaakt kunnen worden. We gebruiken hiervoor Dropwizard Metrics.

Dropwizard Metrics

Dropwizard Metrics is een heel populaire custom metrics library, die op een slimme manier in-memory metingen kan aggregeren tot metrieken, zonder dat bakken metingen in het geheugen nodig zijn. De Metrics library doet dit door middel van “decaying reservoirs” van alleen statistisch relevante metingen bij te houden. Een link naar een goede presentatie over dit concept is hier te vinden: [2]. Het enige dat je echt hoeft te snappen is dat een metriek slechts enkele kilobytes geheugenoverhead heeft, en minimale CPU kosten om bij te werken. Met de Metrics library daarom kunnen gemakkelijk enkele honderden metrieken worden bijgehouden per JVM proces, die “always on” in productie mee kunnen lopen zonder aanvullende infrastructuur.

Aangezien de Metrics library werkt op basis van een statistisch algoritme om metingen tot een metriek te maken, moet je vooraf kiezen voor de soort metriek die je wilt hebben. De Metrics library heeft hier een simpele Java API voor, die prima is gedocumenteerd. [3] De volgende soorten metrieken worden aangeboden:

  • < >: het aantal gebeurtenissen over tijd (bijv. verzoeken per seconde).< >: de huidige waarde (bijv. het aantal openstaande berichten).< >: een speciale Gauge, thread-safe teller dient die kan worden verhoogd en verlaagd (bijv. het aantal ingelogde gebruikers).< >: een histogram van een verzameling waardes (bijv. de lengtes van een zoek-tekst ingevuld door gebruikers).< >: een speciale Meter, meet zowel het aantal gebeurtenissen over tijd, als de doorlooptijd per gebeurtenis (bijv. de responsetijd van een service call). 
    
    	

    Timer timer = registry.timer(name(RestService.class, "get-requests")); try (Timer.Context context = timer.time()) { // handle request }

Dropwizard Metrics voorbeeld: Timer

De Metrics code die je toevoegt in je applicatie zul je netjes gescheiden willen houden. Het maakt anders de code nodeloos complex, en een aantal metrieken zul je willen hergebruiken op meerdere plekken. Voor de Timer metriek is een “interceptor” oplossing vaak een goede oplossing. Die is in verschillende injection frameworks, zoals CDI, Guice en Spring, al standaard voorhanden, en stelt je in staat om een methode te wrappen met een meetpunt:

 


@Interceptor
public class TimerInterceptor{
    @AroundInvoke
public Object timeMethod(InvocationContext invocationContext) throws Exception {
Timer timer = registry.timer(name(invocationContext.getMethod().getDeclaringClass(), invocationContext.getMethod().getName)); try (Timer.Context context = timer.time()) { return invocationContext.proceed(); } } }

Listing 2: CDI interceptor voorbeeld: Method timer

Metrieken rapporteren

Meten is alleen nuttig als de metrieken ook gemakkelijk in te zien zijn. DropWizard Metrics zijn bovendien in-memory, wat makkelijk en goedkoop is, maar ook betekent dat alle metrieken weg zijn als het JVM proces gestopt wordt. Een gemakkelijke methode om metrieken te verzamelen is om ze periodiek te loggen in de technische logging. Dit kan met de volgende hulpklasse van Dropwizard Metrics:


Slf4jReporter reporter = Slf4jReporter.forRegistry(registry)
    .outputTo(LoggerFactory.getLogger("com.nljug.metrics"))
    .convertRatesTo(TimeUnit.SECONDS)
    .convertDurationsTo(TimeUnit.MILLISECONDS)
    .build();
reporter.start(1, TimeUnit.MINUTES);

Listing 3: Dropwizard Metrics voorbeeld: Metrics loggen naar SLF4

Met behulp van logging aggregatie tools, die je waarschijnlijk toch al gebruikt voor het analyseren van je applicatie in productie over meerdere machines, kun je vervolgens de getallen plotten in een grafiek of dashboard. Logstash en Kibana zijn populaire tools hiervoor:

Voorbeeld van dashboard in Kibana, gebaseerd op logging

Rapporteren met CloudWatch

Cloud omgevingen bieden ook steeds vaker alternatieven om metrieken te rapporteren. Wij gebruiken momenteel Amazon Web Services (AWS), waar CloudWatch een mooie dienst biedt voor zowel AWS standaard metrics als custom metrics. Beide type metrics kunnen in dashboards getoond, en voorzien worden van alerts als een grenswaarde wordt overschreden. AWS vraagt bovendien niet veel geld voor deze dienst: de eerste 20 metrieken zijn typisch gratis, en daarna is het op het moment van schrijven ongeveer 5 cent per metriek per machine per maand.

De “Blacklocus” Metrics Cloudwatch library [4] is een aanvulling voor Dropwizards Metrics om de Metrics in AWS formaat aan te bieden aan CloudWatch. Ook hier zijn enkele regels code voldoende:


new CloudWatchReporterBuilder()
    .withNamespace("com.nljug.metrics")
    .withRegistry(registry)
    .build()
    .start(1, TimeUnit.MINUTES);

Listing 4: Blacklocus Metrics Cloudwatch voorbeeld: integratie met AWS

Met Cloudwatch zijn vervolgens ook mooie grafiekjes te realiseren:

Voorbeeld van CloudWatch dashboard

Conclusie

Goede applicatie metrieken zijn waardevol voor het hele team. Met een vlotte, praktische verkenning met het hele team kunnen snel nuttige metrieken bepaald worden. Met DropWizard Metrics kan vervolgens snel een aantal metrieken toegevoegd worden, die praktisch gratis heel veel inzicht kunnen bieden. Meten is weten!

Referenties:

[1] How to measure anything, Douglas W. Hubbard: http://www.howtomeasureanything.com

[2] Metrics Metrics everywhere, Coda Hale: https://vimeo.com/51320606

[3] Dropwizard Metrics: http://metrics.dropwizard.io

[4] Blacklocus Metrics Cloudwatch integration: https://github.com/blacklocus/metrics-cloudwatch