Guia Rápido para Micrômetro
1. Introdução
Micrometer fornece uma fachada simples sobre os clientes de instrumentação para vários sistemas de monitoramento populares. Atualmente, ele suporta os seguintes sistemas de monitoramento: Atlas, Datadog , Grafite, Gânglios, Influx, JMX e Prometheus.
Neste artigo, apresentaremos o uso básico do micrômetro e sua integração com o Spring.
Por uma questão de simplicidade, usaremos o Micrômetro Atlas como exemplo para demonstrar a maioria dos nossos casos de uso.
*2. Dependência Maven *
Para começar, adicione a seguinte dependência ao pom.xml:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-atlas</artifactId>
<version>0.12.0.RELEASE</version>
</dependency>
A versão mais recente pode ser encontrada em https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22micrometer-registry-atlas%22%20AND%20g%3A%20%22io.micrometer%22 [aqui].
===* 3. MeterRegistry *
No Micrômetro, MeterRegistry é o componente principal usado para registrar medidores. Podemos iterar o registro e aprofundar as métricas de cada medidor, para gerar uma série temporal no back-end com combinações de métricas e seus valores de dimensão.
A forma mais simples do registro é https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/simple/SimpleMeterRegistry.java#L31 [SimpleMeterRegistry]. Mas na maioria dos casos, devemos usar um https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/MeterRegistry.java#L41 [MeterRegistry] projetado explicitamente para o nosso sistema de monitoramento; para o Atlas, é AtlasMeterRegistry .
CompositeMeterRegistry permite que vários registros sejam ser adicionado. Ele fornece uma solução para publicar métricas de aplicativos em vários sistemas de monitoramento suportados simultaneamente.
Podemos adicionar qualquer MeterRegistry necessário para carregar os dados em várias plataformas:
CompositeMeterRegistry compositeRegistry = new CompositeMeterRegistry();
SimpleMeterRegistry oneSimpleMeter = new SimpleMeterRegistry();
AtlasMeterRegistry atlasMeterRegistry
= new AtlasMeterRegistry(atlasConfig, Clock.SYSTEM);
compositeRegistry.add(oneSimpleMeter);
compositeRegistry.add(atlasMeterRegistry);
Há um suporte estático ao registro global no Micrômetro: https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/Metrics.java#L31 [Metrics.globalRegistry]. Além disso, é fornecido um conjunto de construtores estáticos com base nesse registro global para gerar medidores em https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/Metrics.java # L30 [Metrics]:
@Test
public void givenGlobalRegistry_whenIncrementAnywhere_thenCounted() {
class CountedObject {
private CountedObject() {
Metrics.counter("objects.instance").increment(1.0);
}
}
Metrics.addRegistry(new SimpleMeterRegistry());
Metrics.counter("objects.instance").increment();
new CountedObject();
Optional<Counter> counterOptional = Metrics.globalRegistry
.find("objects.instance").counter();
assertTrue(counterOptional.isPresent());
assertTrue(counterOptional.get().count() == 2.0);
}
===* 4. Tags e Meters *
====* 4.1 Tag *
Um identificador de um Meter consiste em um nome e tags.* Sugere-se que sigamos uma convenção de nomenclatura que separa palavras com um ponto, para ajudar a garantir a portabilidade de nomes de métricas em vários sistemas de monitoramento. *
Counter counter = registry.counter("page.visitors", "age", "20s");
Tags pode ser usado para fatiar o métrica para raciocinar sobre os valores. No código acima, page.visitors é o nome do medidor, com age = 20s como sua tag. Nesse caso, o contador deve contar os visitantes da página com idade entre 20 e 30 anos.
Para um sistema grande, podemos anexar tags comuns a um registro, digamos que as métricas sejam de uma região específica:
registry.config().commonTags("region", "ua-east");
====* 4.2 Contador *
Um Counter informa apenas uma contagem uma propriedade especificada de um aplicativo. Podemos criar um contador personalizado com o construtor fluente ou o método auxiliar de qualquer MetricRegistry:
Counter counter = Counter
.builder("instance")
.description("indicates instance count of the object")
.tags("dev", "performance")
.register(registry);
counter.increment(2.0);
assertTrue(counter.count() == 2);
counter.increment(-1);
assertTrue(counter.count() == 2);
Como visto no snippet acima, tentamos diminuir o contador em um, mas* só podemos incrementar o contador monotonicamente em um valor positivo fixo. *
====* 4.3 Timers *
Para medir latências ou frequência de eventos em nosso sistema, podemos usar https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/Timer.java # L34 [Timers] _. Um _Timer relatará pelo menos a contagem total de tempo e eventos de séries temporais específicas.
Por exemplo, podemos gravar um evento de aplicativo que pode durar vários segundos:
SimpleMeterRegistry registry = new SimpleMeterRegistry();
Timer timer = registry.timer("app.event");
timer.record(() -> {
try {
TimeUnit.MILLISECONDS.sleep(1500);
} catch (InterruptedException ignored) { }
});
timer.record(3000, MILLISECONDS);
assertTrue(2 == timer.count());
assertTrue(4510 > timer.totalTime(MILLISECONDS)
&& 4500 <= timer.totalTime(MILLISECONDS));
Para gravar eventos de longa duração, usamos https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/LongTaskTimer.java# L26 [LongTaskTimer]:
SimpleMeterRegistry registry = new SimpleMeterRegistry();
LongTaskTimer longTaskTimer = LongTaskTimer
.builder("3rdPartyService")
.register(registry);
long currentTaskId = longTaskTimer.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ignored) { }
long timeElapsed = longTaskTimer.stop(currentTaskId);
assertTrue(timeElapsed/(int) 1e9 == 2);
====* 4.4 Calibre*
*Um medidor mostra o valor atual de um medidor.*
Diferente de outros medidores, Gauges deve somente relate dados quando observados. Gauges pode ser útil ao monitorar estatísticas de cache, coleções, etc .:
SimpleMeterRegistry registry = new SimpleMeterRegistry();
List<String> list = new ArrayList<>(4);
Gauge gauge = Gauge
.builder("cache.size", list, List::size)
.register(registry);
assertTrue(gauge.value() == 0.0);
list.add("1");
assertTrue(gauge.value() == 1.0);
4.5 DistributionSummary
A distribuição de eventos e um resumo simples são fornecidos por https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/DistributionSummary.java# L29 [DistributionSummary]:
SimpleMeterRegistry registry = new SimpleMeterRegistry();
DistributionSummary distributionSummary = DistributionSummary
.builder("request.size")
.baseUnit("bytes")
.register(registry);
distributionSummary.record(3);
distributionSummary.record(4);
distributionSummary.record(5);
assertTrue(3 == distributionSummary.count());
assertTrue(12 == distributionSummary.totalAmount());
Além disso, DistributionSummary e Timers podem ser enriquecidos por quantis:
SimpleMeterRegistry registry = new SimpleMeterRegistry();
Timer timer = Timer.builder("test.timer")
.quantiles(WindowSketchQuantiles
.quantiles(0.3, 0.5, 0.95)
.create())
.register(registry);
No snippet acima, três medidores com as tags quantile = 0.3, quantile = 0.5 e quantile = 0.95 estarão disponíveis no registro, indicando os valores abaixo dos quais 95%, 50% e 30% das observações caem, respectivamente.
Para ver esses quantis em ação, vamos adicionar os seguintes registros:
timer.record(2, TimeUnit.SECONDS);
timer.record(2, TimeUnit.SECONDS);
timer.record(3, TimeUnit.SECONDS);
timer.record(4, TimeUnit.SECONDS);
timer.record(8, TimeUnit.SECONDS);
timer.record(13, TimeUnit.SECONDS);
Em seguida, podemos verificar extraindo valores nesses três Gauges quantis:
List<Gauge> quantileGauges = registry.getMeters().stream()
.filter(m -> m.getType().name().equals("Gauge"))
.map(meter -> (Gauge) meter)
.collect(Collectors.toList());
assertTrue(3 == quantileGauges.size());
Map<String, Integer> quantileMap = extractTagValueMap(registry, Type.Gauge, 1e9);
assertThat(quantileMap, allOf(
hasEntry("quantile=0.3",2),
hasEntry("quantile=0.5", 3),
hasEntry("quantile=0.95", 8)));
Além disso, o micrômetro também suporta histogramas:
DistributionSummary hist = DistributionSummary
.builder("summary")
.histogram(Histogram.linear(0, 10, 5))
.register(registry);
Semelhante aos quantis, depois de anexar vários registros, podemos ver que o histograma lida muito bem com a computação:
Map<String, Integer> histograms = extractTagValueMap(registry, Type.Counter, 1.0);
assertThat(histograms, allOf(
hasEntry("bucket=0.0", 0),
hasEntry("bucket=10.0", 2),
hasEntry("bucket=20.0", 2),
hasEntry("bucket=30.0", 1),
hasEntry("bucket=40.0", 1),
hasEntry("bucket=Infinity", 0)));
Geralmente, os histogramas podem ajudar a ilustrar uma comparação direta em baldes separados. Os histogramas também podem ser redimensionados, o que é bastante útil para analisar o tempo de resposta do serviço de back-end:
SimpleMeterRegistry registry = new SimpleMeterRegistry();
Timer timer = Timer
.builder("timer")
.histogram(Histogram.linearTime(TimeUnit.MILLISECONDS, 0, 200, 3))
.register(registry);
//...
assertThat(histograms, allOf(
hasEntry("bucket=0.0", 0),
hasEntry("bucket=2.0E8", 1),
hasEntry("bucket=4.0E8", 1),
hasEntry("bucket=Infinity", 3)));
*5. Pastas *
O micrômetro possui vários ligadores internos para monitorar os serviços JVM, caches, ExecutorService e log.
No que diz respeito à JVM e ao monitoramento do sistema, podemos monitorar as métricas do carregador de classes (https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ClassLoaderMetrics.java # L27 [ClassLoaderMetrics]), conjunto de memórias JVM (https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrômetro/núcleo/instrumento/fichário/jvm/JvmMemoryMetrics.java # L38 [JvmMemoryMetrics]) e métricas de GC (JvmGcMetrics), utilização de thread e CPU (https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/principal/java/io/micrômetro/núcleo/instrumento/fichário/jvm/JvmThreadMetrics.java # L27 [JvmThreadMetrics], https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrômetro/núcleo/instrumento/fichário/sistema/processador Metrics.java # L30 [ProcessorMetrics]).
O monitoramento de cache (atualmente, apenas Guava, EhCache, Hazelcast e Caffeine são suportados) é suportado por instrumentos com https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrômetro/núcleo/instrumento/fichário/cache/GuavaCacheMetrics.java # L31 [GuavaCacheMetrics], EhCache2Metrics, https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrômetro/núcleo/instrumento/fichário/cache/HazelcastCacheMetrics.java # L27 [HazelcastCacheMetrics] e https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrômetro/núcleo/instrumento/fichário/cache/CaffeineCacheMetrics.java # L42 [CaffeineCacheMetrics]. E para monitorar o serviço de logoff, podemos vincular https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/logging/LogbackMetrics.java # L36 [LogbackMetrics] para qualquer registro válido:
new LogbackMetrics().bind(registry);
O uso dos fichários acima é bastante semelhante ao LogbackMetrics e é bastante simples, portanto, não vamos abordar mais detalhes aqui.
===* 6. Integração com molas *
O Spring Boot Actuator fornece gerenciamento de dependência e configuração automática para o micrômetro.* Agora ele é suportado no Spring Boot 2.0/1.xe no Spring Framework 5.0/4.x.
Necessitaremos da seguinte dependência (a versão mais recente pode ser encontrada https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22io.micrometer%22%20AND%20a%3A%22micrometer -spring-legacy% 22 [aqui]):
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-spring-legacy</artifactId>
<version>0.12.0.RELEASE</version>
</dependency>
Sem nenhuma alteração adicional no código existente, ativamos o suporte ao Spring com o micrômetro. As métricas de memória da JVM de nosso aplicativo Spring serão registradas automaticamente no registro global e publicadas no terminal padrão do atlas: http://localhost: 7101/api/v1/publish.
Existem várias propriedades configuráveis disponíveis para controlar comportamentos de exportação de métricas, começando com spring.metrics.atlas. * _. Verifique _AtlasConfig