Make spring-analytics-consumer as auto-config
* Fix all the Checkstyle violations
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
dependencies {
|
||||
api project(':spring-payload-converter-function')
|
||||
api 'io.micrometer:micrometer-core'
|
||||
api 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
testImplementation 'io.micrometer:micrometer-registry-wavefront'
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,65 +27,48 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.fn.common.config.SpelExpressionConverterConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The auto-configuration for analytics consumer.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfiguration(after = MetricsAutoConfiguration.class)
|
||||
@EnableConfigurationProperties(AnalyticsConsumerProperties.class)
|
||||
public class AnalyticsConsumerConfiguration {
|
||||
|
||||
/** Default tag value. Used to fill the tag when the actual value is missing. */
|
||||
/**
|
||||
* Default tag value. Used to fill the tag when the actual value is missing.
|
||||
*/
|
||||
public static final String UNAVAILABLE_TAG = "NA";
|
||||
|
||||
private final Map<Meter.Id, AtomicLong> gaugeValues = new ConcurrentHashMap<>();
|
||||
|
||||
@Bean(name = "analyticsConsumer")
|
||||
public Consumer<Message<?>> analyticsConsumer(AnalyticsConsumerProperties properties,
|
||||
MeterRegistry[] meterRegistries,
|
||||
@Lazy @Qualifier(SpelExpressionConverterConfiguration.INTEGRATION_EVALUATION_CONTEXT) EvaluationContext context) {
|
||||
@Bean
|
||||
public Consumer<Message<?>> analyticsConsumer(AnalyticsConsumerProperties properties, MeterRegistry meterRegistry) {
|
||||
|
||||
// If the CompositeMeterRegistry is present the it already contains all
|
||||
// non-composite registries.
|
||||
// In this case we override the input meterRegistries to use the
|
||||
// CompositeMeterRegistry only.
|
||||
final MeterRegistry[] finalMeterRegistries = Stream.of(meterRegistries)
|
||||
.filter(CompositeMeterRegistry.class::isInstance)
|
||||
.findFirst()
|
||||
.map(meterRegistry -> new MeterRegistry[] { meterRegistry })
|
||||
.orElse(meterRegistries);
|
||||
|
||||
return message -> {
|
||||
|
||||
CharSequence meterNameRaw = properties.getComputedNameExpression()
|
||||
.getValue(context, message, CharSequence.class);
|
||||
String meterName = StringUtils.isEmpty(meterNameRaw) ? "empty" : meterNameRaw.toString();
|
||||
return (message) -> {
|
||||
CharSequence meterNameRaw = properties.getComputedNameExpression().getValue(message, CharSequence.class);
|
||||
String meterName = StringUtils.hasText(meterNameRaw) ? meterNameRaw.toString() : "empty";
|
||||
|
||||
// All fixed tags together are passed with every meter update.
|
||||
Tags fixedTags = this.toTags(properties.getTag().getFixed());
|
||||
|
||||
double amount = properties.getComputedAmountExpression().getValue(context, message, double.class);
|
||||
Double amount = properties.getComputedAmountExpression().getValue(message, Double.class);
|
||||
|
||||
Map<String, List<Tag>> allGroupedTags = new HashMap<>();
|
||||
// Tag Expressions
|
||||
@@ -97,16 +80,15 @@ public class AnalyticsConsumerConfiguration {
|
||||
.stream()
|
||||
// maps a <name, expr> pair into [<name, expr#val_1>, ... <name,
|
||||
// expr#val_N>] Tag array.
|
||||
.map(namedExpression -> toList(namedExpression.getValue().getValue(context, message)).stream()
|
||||
.map(tagValue -> Tag.of(namedExpression.getKey(), tagValue))
|
||||
.map((namedExpression) -> toList(namedExpression.getValue().getValue(message)).stream()
|
||||
.map((tagValue) -> Tag.of(namedExpression.getKey(), tagValue))
|
||||
.collect(Collectors.toList()))
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.groupingBy(Tag::getKey, Collectors.toList()));
|
||||
allGroupedTags.putAll(groupedTags);
|
||||
}
|
||||
|
||||
this.recordMetrics(finalMeterRegistries, meterName, fixedTags, allGroupedTags, amount,
|
||||
properties.getMeterType());
|
||||
recordMetrics(meterRegistry, meterName, fixedTags, allGroupedTags, amount, properties.getMeterType());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,23 +96,23 @@ public class AnalyticsConsumerConfiguration {
|
||||
* Converts a key/value Map into Tag(key,value) list. Filters out the empty key/value
|
||||
* pairs.
|
||||
* @param keyValueMap key/value map to convert into tags.
|
||||
* @return Returns Tags list representing every non-empty key/value pair.
|
||||
* @return tags list representing every non-empty key/value pair.
|
||||
*/
|
||||
protected Tags toTags(Map<String, String> keyValueMap) {
|
||||
return CollectionUtils.isEmpty(keyValueMap) ? Tags.empty()
|
||||
: Tags.of(keyValueMap.entrySet()
|
||||
.stream()
|
||||
.filter(e -> StringUtils.hasText(e.getKey()) && StringUtils.hasText(e.getValue()))
|
||||
.map(e -> Tag.of(e.getKey(), e.getValue()))
|
||||
.collect(Collectors.toList()));
|
||||
.filter((e) -> StringUtils.hasText(e.getKey()) && StringUtils.hasText(e.getValue()))
|
||||
.map((e) -> Tag.of(e.getKey(), e.getValue()))
|
||||
.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the input value into an list of values. If the value is not a
|
||||
* Convert the input value into a list of values. If the value is not a
|
||||
* collection/array type the result is a single element list. For collection/array
|
||||
* input value the result is the list of stringified content of this collection.
|
||||
* @param value input value can be array, collection or single value.
|
||||
* @return Returns value list.
|
||||
* input value the result is the list of "stringified" content of this collection.
|
||||
* @param value input value can be an array, collection or single value.
|
||||
* @return the value list.
|
||||
*/
|
||||
protected List<String> toList(Object value) {
|
||||
if (value == null) {
|
||||
@@ -148,7 +130,7 @@ public class AnalyticsConsumerConfiguration {
|
||||
.filter(Objects::nonNull)
|
||||
.map(Object::toString)
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
return CollectionUtils.isEmpty(list) ? Collections.singletonList(UNAVAILABLE_TAG) : list;
|
||||
}
|
||||
else {
|
||||
@@ -156,10 +138,11 @@ public class AnalyticsConsumerConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private void recordMetrics(MeterRegistry[] meterRegistries, String meterName, Tags fixedTags,
|
||||
Map<String, List<Tag>> groupedTags, double amount, AnalyticsConsumerProperties.MeterType meterType) {
|
||||
private void recordMetrics(MeterRegistry meterRegistry, String meterName, Tags fixedTags,
|
||||
Map<String, List<Tag>> groupedTags, Double amount, AnalyticsConsumerProperties.MeterType meterType) {
|
||||
|
||||
if (!CollectionUtils.isEmpty(groupedTags)) {
|
||||
groupedTags.values().stream().map(List::size).max(Integer::compareTo).ifPresent(max -> {
|
||||
groupedTags.values().stream().map(List::size).max(Integer::compareTo).ifPresent((max) -> {
|
||||
for (int i = 0; i < max; i++) {
|
||||
Tags currentTags = Tags.of(fixedTags);
|
||||
for (Map.Entry<String, List<Tag>> e : groupedTags.entrySet()) {
|
||||
@@ -168,49 +151,44 @@ public class AnalyticsConsumerConfiguration {
|
||||
}
|
||||
|
||||
// Update the meterName for every configured MaterRegistry.
|
||||
record(meterRegistries, meterName, currentTags, amount, meterType);
|
||||
record(meterRegistry, meterName, currentTags, amount, meterType);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Update the meterName for every configured MaterRegistry.
|
||||
record(meterRegistries, meterName, fixedTags, amount, meterType);
|
||||
record(meterRegistry, meterName, fixedTags, amount, meterType);
|
||||
}
|
||||
}
|
||||
|
||||
private void record(MeterRegistry[] meterRegistries, String meterName, Iterable<Tag> tags, double meterAmount,
|
||||
private void record(MeterRegistry meterRegistry, String meterName, Iterable<Tag> tags, double meterAmount,
|
||||
AnalyticsConsumerProperties.MeterType meterType) {
|
||||
|
||||
for (MeterRegistry meterRegistry : meterRegistries) {
|
||||
if (meterType == AnalyticsConsumerProperties.MeterType.gauge) {
|
||||
Meter.Id gaugeId = new Meter.Id(meterName, Tags.of(tags), null, null, Meter.Type.GAUGE);
|
||||
if (!this.gaugeValues.containsKey(gaugeId)) {
|
||||
this.gaugeValues.put(gaugeId, new AtomicLong((long) meterAmount));
|
||||
}
|
||||
else {
|
||||
this.gaugeValues.get(gaugeId).set((long) meterAmount);
|
||||
}
|
||||
if (!isMeterRegistryContainsGauge(meterRegistry, gaugeId)) {
|
||||
meterRegistry.gauge(meterName, tags, this.gaugeValues.get(gaugeId), AtomicLong::doubleValue);
|
||||
}
|
||||
}
|
||||
else if (meterType == AnalyticsConsumerProperties.MeterType.counter) {
|
||||
meterRegistry.counter(meterName, tags).increment(meterAmount);
|
||||
if (meterType == AnalyticsConsumerProperties.MeterType.gauge) {
|
||||
Meter.Id gaugeId = new Meter.Id(meterName, Tags.of(tags), null, null, Meter.Type.GAUGE);
|
||||
if (!this.gaugeValues.containsKey(gaugeId)) {
|
||||
this.gaugeValues.put(gaugeId, new AtomicLong((long) meterAmount));
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Unknown meter type:" + meterType);
|
||||
this.gaugeValues.get(gaugeId).set((long) meterAmount);
|
||||
}
|
||||
if (!isMeterRegistryContainsGauge(meterRegistry, gaugeId)) {
|
||||
meterRegistry.gauge(meterName, tags, this.gaugeValues.get(gaugeId), AtomicLong::doubleValue);
|
||||
}
|
||||
}
|
||||
else if (meterType == AnalyticsConsumerProperties.MeterType.counter) {
|
||||
meterRegistry.counter(meterName, tags).increment(meterAmount);
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Unknown meter type: " + meterType);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMeterRegistryContainsGauge(MeterRegistry meterRegistry, Meter.Id gaugeId) {
|
||||
return meterRegistry.find(gaugeId.getName()).gauges().stream().anyMatch(gauge -> gauge.getId().equals(gaugeId));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SimpleMeterRegistry simpleMeterRegistry() {
|
||||
return new SimpleMeterRegistry();
|
||||
private static boolean isMeterRegistryContainsGauge(MeterRegistry meterRegistry, Meter.Id gaugeId) {
|
||||
return meterRegistry.find(gaugeId.getName())
|
||||
.gauges()
|
||||
.stream()
|
||||
.anyMatch((gauge) -> gauge.getId().equals(gaugeId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,10 +24,14 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.integration.expression.ValueExpression;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* The properties for analytics consumer.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ConfigurationProperties("analytics")
|
||||
@Validated
|
||||
@@ -86,11 +90,11 @@ public class AnalyticsConsumerProperties {
|
||||
private final MetricsTag tag = new MetricsTag();
|
||||
|
||||
public MetricsTag getTag() {
|
||||
return tag;
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public MeterType getMeterType() {
|
||||
return meterType;
|
||||
return this.meterType;
|
||||
}
|
||||
|
||||
public void setMeterType(MeterType meterType) {
|
||||
@@ -98,10 +102,10 @@ public class AnalyticsConsumerProperties {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if (name == null && nameExpression == null) {
|
||||
return defaultName;
|
||||
if (this.name == null && this.nameExpression == null) {
|
||||
return this.defaultName;
|
||||
}
|
||||
return name;
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
@@ -109,7 +113,7 @@ public class AnalyticsConsumerProperties {
|
||||
}
|
||||
|
||||
public Expression getNameExpression() {
|
||||
return nameExpression;
|
||||
return this.nameExpression;
|
||||
}
|
||||
|
||||
public void setNameExpression(Expression nameExpression) {
|
||||
@@ -117,7 +121,7 @@ public class AnalyticsConsumerProperties {
|
||||
}
|
||||
|
||||
public Expression getAmountExpression() {
|
||||
return amountExpression;
|
||||
return this.amountExpression;
|
||||
}
|
||||
|
||||
public void setAmountExpression(Expression amountExpression) {
|
||||
@@ -125,11 +129,11 @@ public class AnalyticsConsumerProperties {
|
||||
}
|
||||
|
||||
public Expression getComputedAmountExpression() {
|
||||
return (amountExpression != null ? amountExpression : new LiteralExpression("1.0"));
|
||||
return (this.amountExpression != null) ? this.amountExpression : new ValueExpression<>(1.0);
|
||||
}
|
||||
|
||||
public Expression getComputedNameExpression() {
|
||||
return (nameExpression != null ? nameExpression : new LiteralExpression(getName()));
|
||||
return (this.nameExpression != null) ? this.nameExpression : new LiteralExpression(getName());
|
||||
}
|
||||
|
||||
@AssertTrue(message = "exactly one of 'name' and 'nameExpression' must be set")
|
||||
@@ -139,19 +143,17 @@ public class AnalyticsConsumerProperties {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AnalyticsFunctionProperties{" + "defaultName='" + defaultName + '\'' + ", name=" + name + ", tag=" + tag
|
||||
+ '}';
|
||||
return "AnalyticsFunctionProperties{" + "defaultName='" + this.defaultName + '\'' + ", name=" + this.name
|
||||
+ ", tag=" + this.tag + '}';
|
||||
}
|
||||
|
||||
public static class MetricsTag {
|
||||
|
||||
/**
|
||||
* DEPRECATED: Please use the analytics.tag.expression with literal SpEL
|
||||
* expression.
|
||||
*
|
||||
* Custom, fixed Tags. Those tags have constant values, created once and then sent
|
||||
* along with every published metrics. The convention to define a fixed Tags is:
|
||||
* <code>
|
||||
* expression. Custom, fixed Tags. Those tags have constant values, created once
|
||||
* and then sent along with every published metrics. The convention to define a
|
||||
* fixed Tags is: <code>
|
||||
* analytics.tag.fixed.[tag-name]=[tag-value]
|
||||
* </code>
|
||||
*/
|
||||
@@ -167,7 +169,7 @@ public class AnalyticsConsumerProperties {
|
||||
private Map<String, Expression> expression;
|
||||
|
||||
public Map<String, String> getFixed() {
|
||||
return fixed;
|
||||
return this.fixed;
|
||||
}
|
||||
|
||||
public void setFixed(Map<String, String> fixed) {
|
||||
@@ -175,7 +177,7 @@ public class AnalyticsConsumerProperties {
|
||||
}
|
||||
|
||||
public Map<String, Expression> getExpression() {
|
||||
return expression;
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
public void setExpression(Map<String, Expression> expression) {
|
||||
@@ -184,7 +186,7 @@ public class AnalyticsConsumerProperties {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MetricsTag{" + "fixed=" + fixed + ", expression=" + expression + '}';
|
||||
return "MetricsTag{" + "fixed=" + this.fixed + ", expression=" + this.expression + '}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The analytics consumer classes.
|
||||
*/
|
||||
package org.springframework.cloud.fn.consumer.analytics;
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.cloud.fn.consumer.analytics.AnalyticsConsumerConfiguration
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,9 +28,9 @@ import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
properties = { "management.metrics.export.wavefront.enabled=false" })
|
||||
properties = { "management.wavefront.metrics.export.enabled=false" })
|
||||
@DirtiesContext
|
||||
public class AnalyticsConsumerParentTest {
|
||||
public abstract class AnalyticsConsumerParentTests {
|
||||
|
||||
@Autowired
|
||||
protected SimpleMeterRegistry meterRegistry;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@TestPropertySource(properties = { "analytics.name=counter666", "analytics.tag.expression.foo='bar'",
|
||||
"analytics.amount-expression=payload.length()" })
|
||||
class CountWithAmountTest extends AnalyticsConsumerParentTest {
|
||||
class CountWithAmountTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testCounterSink() {
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@TestPropertySource(properties = { "analytics.name=counter666", "analytics.tag.fixed.foo=",
|
||||
"analytics.tag.expression.tag666=#jsonPath(payload,'$..noField')",
|
||||
"analytics.tag.expression.test=#jsonPath(payload,'$..test')" })
|
||||
class EmptyTagsTests extends AnalyticsConsumerParentTest {
|
||||
class EmptyTagsTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testCounterSink() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,11 +29,11 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@TestPropertySource(properties = { "analytics.name-expression=payload" })
|
||||
public class ExpressionCounterNameTests extends AnalyticsConsumerParentTest {
|
||||
public class ExpressionCounterNameTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testCounterSink() {
|
||||
IntStream.range(0, 13).forEach(i -> analyticsConsumer.accept(new GenericMessage<>("hello")));
|
||||
IntStream.range(0, 13).forEach((i) -> analyticsConsumer.accept(new GenericMessage<>("hello")));
|
||||
assertThat(meterRegistry.find("hello").counter().count()).isEqualTo(13.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.fn.consumer.analytics;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -32,15 +33,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@TestPropertySource(
|
||||
properties = { "analytics.name=counter666", "analytics.tag.fixed.foo=bar", "analytics.tag.fixed.gork=bork" })
|
||||
public class FixedTagsTests extends AnalyticsConsumerParentTest {
|
||||
public class FixedTagsTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testAnalyticsSink() {
|
||||
IntStream.range(0, 13).forEach(i -> analyticsConsumer.accept(new GenericMessage<>("hello")));
|
||||
IntStream.range(0, 13).forEach((i) -> analyticsConsumer.accept(new GenericMessage<>("hello")));
|
||||
Meter counterMeter = meterRegistry.find("counter666").meter();
|
||||
assertThat(
|
||||
StreamSupport.stream(counterMeter.measure().spliterator(), false).mapToDouble(m -> m.getValue()).sum())
|
||||
.isEqualTo(13.0);
|
||||
assertThat(StreamSupport.stream(counterMeter.measure().spliterator(), false)
|
||||
.mapToDouble(Measurement::getValue)
|
||||
.sum()).isEqualTo(13.0);
|
||||
|
||||
assertThat(counterMeter.getId().getTags().size()).isEqualTo(2);
|
||||
assertThat(counterMeter.getId().getTag("foo")).isEqualTo("bar");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@TestPropertySource(properties = { "analytics.meter-type=gauge", "analytics.name=myGauge",
|
||||
"analytics.tag.expression.foo='bar'", "analytics.amount-expression=payload.length()" })
|
||||
class GaugeWithAmountTest extends AnalyticsConsumerParentTest {
|
||||
class GaugeWithAmountTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testAnalyticsSink() {
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,11 +31,11 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@TestPropertySource(properties = { "analytics.name=counter666", "analytics.tag.expression.foo='bar'",
|
||||
"analytics.tag.expression.gork='bork'" })
|
||||
public class LiteralTagExpressionsTests extends AnalyticsConsumerParentTest {
|
||||
public class LiteralTagExpressionsTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testCounterSink() {
|
||||
IntStream.range(0, 13).forEach(i -> analyticsConsumer.accept(new GenericMessage<>("hello")));
|
||||
IntStream.range(0, 13).forEach((i) -> analyticsConsumer.accept(new GenericMessage<>("hello")));
|
||||
|
||||
Counter fooCounter = meterRegistry.find("counter666").tag("foo", "bar").counter();
|
||||
assertThat(fooCounter.count()).isEqualTo(13.0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@TestPropertySource(properties = { "analytics.name=counter666", "analytics.tag.fixed.foo=",
|
||||
"analytics.tag.expression.tag666=#jsonPath(payload,'$..noField')",
|
||||
"analytics.tag.expression.test=#jsonPath(payload,'$..test')" })
|
||||
public class NullTagsTests extends AnalyticsConsumerParentTest {
|
||||
public class NullTagsTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
void testАnalyticsSink() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@TestPropertySource(properties = { "analytics.meter-type=counter", "analytics.name=stocks",
|
||||
"analytics.tag.expression.symbol=#jsonPath(payload,'$.data.symbol')",
|
||||
"analytics.tag.expression.exchange=#jsonPath(payload,'$.data.exchange')" })
|
||||
public class StockExchangeAnalyticsTests extends AnalyticsConsumerParentTest {
|
||||
public class StockExchangeAnalyticsTests extends AnalyticsConsumerParentTests {
|
||||
|
||||
@Test
|
||||
public void testCounter() throws IOException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -75,7 +75,7 @@ public class StockExchangeAnalyticsExample {
|
||||
Supplier<String> stockMessageGenerator) {
|
||||
|
||||
// Run every second.
|
||||
return args -> Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
|
||||
return (args) -> Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
|
||||
|
||||
String message = stockMessageGenerator.get();
|
||||
|
||||
@@ -86,8 +86,8 @@ public class StockExchangeAnalyticsExample {
|
||||
// Print current stock meters
|
||||
System.out.println(meterRegistry.getMeters()
|
||||
.stream()
|
||||
.filter(meter -> meter.getId().getName().contains("stocks"))
|
||||
.map(meter -> meter.getId().getType() + " | " + meter.getId() + " | " + meter.measure())
|
||||
.filter((meter) -> meter.getId().getName().contains("stocks"))
|
||||
.map((meter) -> meter.getId().getType() + " | " + meter.getId() + " | " + meter.measure())
|
||||
.collect(Collectors.joining("\n"))
|
||||
+ "\n=========================================================================");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user