Introdução às métricas do Dropwizard

Introdução às métricas do Dropwizard

*1. Introdução *

Metrics é uma biblioteca Java que fornece instrumentos de medição para aplicativos Java.

Ele possui vários módulos e, neste artigo, elaboraremos o módulo métricas-núcleo, o módulo métricas-verificações de saúde, o módulo métricas-servlets e o módulo métricas-servlet e esboçaremos o restante, para sua referência.

===* 2. Módulo metrics-core *

====* 2.1 Dependências do Maven *

Para usar o módulo metrics-core, há apenas uma dependência necessária que precisa ser adicionada ao arquivo pom.xml:

<dependency>
    <groupId>io.dropwizard.metrics</groupId>
    <artifactId>metrics-core</artifactId>
    <version>3.1.2</version>
</dependency>

====* 2.2 MetricRegistry *

Simplificando, usaremos a classe MetricRegistry para registrar uma ou várias métricas.

Podemos usar um registro de métricas para todas as métricas, mas se quisermos usar métodos de relatório diferentes para métricas diferentes, também podemos dividir nossas métricas em grupos e usar registros de métricas diferentes para cada grupo.

Vamos criar um MetricRegistry agora:

MetricRegistry metricRegistry = new MetricRegistry();

E então podemos registrar algumas métricas com este MetricRegistry:

Meter meter1 = new Meter();
metricRegistry.register("meter1", meter1);

Meter meter2 = metricRegistry.meter("meter2");

Existem duas maneiras básicas de criar uma nova métrica: instanciando uma você mesmo ou obtendo uma a partir do registro da métrica. Como você pode ver, usamos os dois no exemplo acima, estamos instanciando o objeto Meter "meter1" e obtendo outro objeto Meter "meter2", criado pelo metricRegistry.

Em um registro de métricas, cada métrica tem um nome exclusivo, pois usamos "meter1" e "meter2" como nomes de métricas acima. MetricRegistry também fornece um conjunto de métodos auxiliares estáticos para nos ajudar a criar nomes de métricas adequados:

String name1 = MetricRegistry.name(Filter.class, "request", "count");
String name2 = MetricRegistry.name("CustomFilter", "response", "count");

Se precisarmos gerenciar um conjunto de registros de métricas, podemos usar a classe SharedMetricRegistries, que é um singleton e é seguro para threads. Podemos adicionar um registro de métrica a ele, recuperá-lo e removê-lo:

SharedMetricRegistries.add("default", metricRegistry);
MetricRegistry retrievedMetricRegistry = SharedMetricRegistries.getOrCreate("default");
SharedMetricRegistries.remove("default");

===* 3. Conceitos de métricas *

O módulo metrics-core fornece vários tipos de métricas comumente usados: Meter, Gauge, Counter, Histogram and Timer e Reporter para gerar os valores das métricas .

====* 3.1 Metro *

Um Meter mede a contagem e a taxa de ocorrências de eventos:

Meter meter = new Meter();
long initCount = meter.getCount();
assertThat(initCount, equalTo(0L));

meter.mark();
assertThat(meter.getCount(), equalTo(1L));

meter.mark(20);
assertThat(meter.getCount(), equalTo(21L));

double meanRate = meter.getMeanRate();
double oneMinRate = meter.getOneMinuteRate();
double fiveMinRate = meter.getFiveMinuteRate();
double fifteenMinRate = meter.getFifteenMinuteRate();

O método getCount () _ retorna a contagem de ocorrências de eventos, e o método _mark () _ adiciona 1 ou n à contagem de ocorrências de eventos. O objeto _Meter fornece quatro taxas que representam taxas médias para toda a vida útil do Meter, no último minuto, nos últimos cinco minutos e no trimestre recente, respectivamente.

====* 3.2 Calibre *

Gauge é uma interface que é simplesmente usada para retornar um valor específico. O módulo metrics-core fornece várias implementações: RatioGauge, http://metrics.dropwizard.io/3.1.0/apidocs/com/codahale/metrics/anototation/CachedGauge.html [CachedGauge], DerivativeGauge e JmxAttributeGauge.

RatioGauge é uma classe abstrata e mede a proporção de um valor para outro.

Vamos ver como usá-lo. Primeiro, implementamos uma classe AttendanceRatioGauge:

public class AttendanceRatioGauge extends RatioGauge {
    private int attendanceCount;
    private int courseCount;

    @Override
    protected Ratio getRatio() {
        return Ratio.of(attendanceCount, courseCount);
    }

   //standard constructors
}

E então testamos:

RatioGauge ratioGauge = new AttendanceRatioGauge(15, 20);

assertThat(ratioGauge.getValue(), equalTo(0.75));

CachedGauge é outra classe abstrata que pode armazenar em cache o valor, portanto, é bastante útil quando os valores são caros de calcular. Para usá-lo, precisamos implementar uma classe ActiveUsersGauge:

public class ActiveUsersGauge extends CachedGauge<List<Long>> {

    @Override
    protected List<Long> loadValue() {
        return getActiveUserCount();
    }

    private List<Long> getActiveUserCount() {
        List<Long> result = new ArrayList<Long>();
        result.add(12L);
        return result;
    }

   //standard constructors
}

Em seguida, testamos para ver se funciona como esperado:

Gauge<List<Long>> activeUsersGauge = new ActiveUsersGauge(15, TimeUnit.MINUTES);
List<Long> expected = new ArrayList<>();
expected.add(12L);

assertThat(activeUsersGauge.getValue(), equalTo(expected));

Definimos o tempo de expiração do cache como 15 minutos ao instanciar o ActiveUsersGauge.

DerivativeGauge também é uma classe abstrata e permite derivar um valor de outro Gauge como seu valor.

Vejamos um exemplo:

public class ActiveUserCountGauge extends DerivativeGauge<List<Long>, Integer> {

    @Override
    protected Integer transform(List<Long> value) {
        return value.size();
    }

   //standard constructors
}

Como Gauge deriva seu valor de um ActiveUsersGauge, esperamos que seja o valor do tamanho da lista base:

Gauge<List<Long>> activeUsersGauge = new ActiveUsersGauge(15, TimeUnit.MINUTES);
Gauge<Integer> activeUserCountGauge = new ActiveUserCountGauge(activeUsersGauge);

assertThat(activeUserCountGauge.getValue(), equalTo(1));

JmxAttributeGauge é usado quando precisamos acessar as métricas de outras bibliotecas expostas via JMX.

====* 3.3 Contador *

O Counter é usado para registrar incrementos e decrementos:

Counter counter = new Counter();
long initCount = counter.getCount();
assertThat(initCount, equalTo(0L));

counter.inc();
assertThat(counter.getCount(), equalTo(1L));

counter.inc(11);
assertThat(counter.getCount(), equalTo(12L));

counter.dec();
assertThat(counter.getCount(), equalTo(11L));

counter.dec(6);
assertThat(counter.getCount(), equalTo(5L));

====* 3.4 Histogram *

Histogram é usado para acompanhar um fluxo de valores Long e analisa suas características estatísticas como max, min, média, mediana, desvio padrão, 75º percentil e assim por diante:

Histogram histogram = new Histogram(new UniformReservoir());
histogram.update(5);
long count1 = histogram.getCount();
assertThat(count1, equalTo(1L));

Snapshot snapshot1 = histogram.getSnapshot();
assertThat(snapshot1.getValues().length, equalTo(1));
assertThat(snapshot1.getValues()[0], equalTo(5L));

histogram.update(20);
long count2 = histogram.getCount();
assertThat(count2, equalTo(2L));

Snapshot snapshot2 = histogram.getSnapshot();
assertThat(snapshot2.getValues().length, equalTo(2));
assertThat(snapshot2.getValues()[1], equalTo(20L));
assertThat(snapshot2.getMax(), equalTo(20L));
assertThat(snapshot2.getMean(), equalTo(12.5));
assertEquals(10.6, snapshot2.getStdDev(), 0.1);
assertThat(snapshot2.get75thPercentile(), equalTo(20.0));
assertThat(snapshot2.get999thPercentile(), equalTo(20.0));

Histogram mostra os dados usando amostragem de reservatório e, quando instanciamos um objeto Histogram, precisamos definir explicitamente seu reservatório.

Reservoir é uma interface e o núcleo de métricas fornece quatro implementações: ExponentiallyDecayingReservoir, http://metrics.dropwizard .io/3.1.0/apidocs/com/codahale/metrics/UniformReservoir.html [UniformReservoir], SlidingTimeWindowReservoir_html , _http://metrics.dropwizard.io/3.1.0/apidocs/com/codahale/metrics/SlidingWindowReservoir.html [SlidingWindowReservoir] .