Drop support for Wavefront
Closes gh-45713
This commit is contained in:
@@ -33,7 +33,6 @@ dependencies {
|
||||
optional("io.micrometer:micrometer-tracing")
|
||||
optional("io.micrometer:micrometer-tracing-bridge-brave")
|
||||
optional("io.micrometer:micrometer-tracing-bridge-otel")
|
||||
optional("io.micrometer:micrometer-tracing-reporter-wavefront")
|
||||
optional("io.micrometer:micrometer-registry-appoptics")
|
||||
optional("io.micrometer:micrometer-registry-atlas") {
|
||||
exclude group: "javax.inject", module: "javax.inject"
|
||||
@@ -55,7 +54,6 @@ dependencies {
|
||||
}
|
||||
optional("io.micrometer:micrometer-registry-signalfx")
|
||||
optional("io.micrometer:micrometer-registry-statsd")
|
||||
optional("io.micrometer:micrometer-registry-wavefront")
|
||||
optional("io.zipkin.reporter2:zipkin-reporter-brave")
|
||||
optional("io.opentelemetry:opentelemetry-exporter-zipkin")
|
||||
optional("io.opentelemetry:opentelemetry-exporter-otlp")
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.application.ApplicationTags;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import io.micrometer.wavefront.WavefrontConfig;
|
||||
import io.micrometer.wavefront.WavefrontMeterRegistry;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontSenderConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Wavefront.
|
||||
*
|
||||
* @author Jon Schneider
|
||||
* @author Artsiom Yudovin
|
||||
* @author Stephane Nicoll
|
||||
* @author Glenn Oppegard
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@AutoConfiguration(
|
||||
before = { CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class },
|
||||
after = { MetricsAutoConfiguration.class, WavefrontAutoConfiguration.class })
|
||||
@ConditionalOnBean(Clock.class)
|
||||
@ConditionalOnClass({ WavefrontMeterRegistry.class, WavefrontSender.class })
|
||||
@ConditionalOnEnabledMetricsExport("wavefront")
|
||||
@EnableConfigurationProperties(WavefrontProperties.class)
|
||||
@Import(WavefrontSenderConfiguration.class)
|
||||
public class WavefrontMetricsExportAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public WavefrontConfig wavefrontConfig(WavefrontProperties properties) {
|
||||
return new WavefrontPropertiesConfigAdapter(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(WavefrontSender.class)
|
||||
public WavefrontMeterRegistry wavefrontMeterRegistry(WavefrontConfig wavefrontConfig, Clock clock,
|
||||
WavefrontSender wavefrontSender) {
|
||||
return WavefrontMeterRegistry.builder(wavefrontConfig).clock(clock).wavefrontSender(wavefrontSender).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(ApplicationTags.class)
|
||||
MeterRegistryCustomizer<WavefrontMeterRegistry> wavefrontApplicationTagsCustomizer(
|
||||
ApplicationTags wavefrontApplicationTags) {
|
||||
Tags commonTags = Tags.of(wavefrontApplicationTags.toPointTags().entrySet().stream().map(this::asTag).toList());
|
||||
return (registry) -> registry.config().commonTags(commonTags);
|
||||
}
|
||||
|
||||
private Tag asTag(Map.Entry<String, String> entry) {
|
||||
return Tag.of(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront;
|
||||
|
||||
import com.wavefront.sdk.common.clients.service.token.TokenService.Type;
|
||||
import io.micrometer.wavefront.WavefrontConfig;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryPropertiesConfigAdapter;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.Metrics.Export;
|
||||
|
||||
/**
|
||||
* Adapter to convert {@link WavefrontProperties} to a {@link WavefrontConfig}.
|
||||
*
|
||||
* @author Jon Schneider
|
||||
* @author Moritz Halbritter
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class WavefrontPropertiesConfigAdapter
|
||||
extends PushRegistryPropertiesConfigAdapter<WavefrontProperties.Metrics.Export> implements WavefrontConfig {
|
||||
|
||||
private final WavefrontProperties properties;
|
||||
|
||||
public WavefrontPropertiesConfigAdapter(WavefrontProperties properties) {
|
||||
super(properties.getMetrics().getExport());
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prefix() {
|
||||
return "management.wavefront.metrics.export";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uri() {
|
||||
return this.properties.getEffectiveUri().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String source() {
|
||||
return this.properties.getSourceOrDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchSize() {
|
||||
return this.properties.getSender().getBatchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiToken() {
|
||||
return this.properties.getApiTokenOrThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String globalPrefix() {
|
||||
return get(Export::getGlobalPrefix, WavefrontConfig.super::globalPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reportMinuteDistribution() {
|
||||
return get(Export::isReportMinuteDistribution, WavefrontConfig.super::reportMinuteDistribution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reportHourDistribution() {
|
||||
return get(Export::isReportHourDistribution, WavefrontConfig.super::reportHourDistribution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reportDayDistribution() {
|
||||
return get(Export::isReportDayDistribution, WavefrontConfig.super::reportDayDistribution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type apiTokenType() {
|
||||
return this.properties.getWavefrontApiTokenType();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for exporting actuator metrics to Wavefront.
|
||||
*/
|
||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront;
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing.wavefront;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.tracing.reporter.wavefront.SpanMetrics;
|
||||
|
||||
/**
|
||||
* Bridges {@link SpanMetrics} to a {@link MeterRegistry}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class MeterRegistrySpanMetrics implements SpanMetrics {
|
||||
|
||||
private final Counter spansReceived;
|
||||
|
||||
private final Counter spansDropped;
|
||||
|
||||
private final Counter reportErrors;
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
MeterRegistrySpanMetrics(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
this.spansReceived = meterRegistry.counter("wavefront.reporter.spans.received");
|
||||
this.spansDropped = meterRegistry.counter("wavefront.reporter.spans.dropped");
|
||||
this.reportErrors = meterRegistry.counter("wavefront.reporter.errors");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDropped() {
|
||||
this.spansDropped.increment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportReceived() {
|
||||
this.spansReceived.increment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportErrors() {
|
||||
this.reportErrors.increment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerQueueSize(BlockingQueue<?> queue) {
|
||||
this.meterRegistry.gauge("wavefront.reporter.queue.size", queue, (q) -> (double) q.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerQueueRemainingCapacity(BlockingQueue<?> queue) {
|
||||
this.meterRegistry.gauge("wavefront.reporter.queue.remaining_capacity", queue, this::remainingCapacity);
|
||||
}
|
||||
|
||||
private double remainingCapacity(BlockingQueue<?> queue) {
|
||||
return queue.remainingCapacity();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing.wavefront;
|
||||
|
||||
import brave.handler.SpanHandler;
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.application.ApplicationTags;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.tracing.reporter.wavefront.SpanMetrics;
|
||||
import io.micrometer.tracing.reporter.wavefront.WavefrontBraveSpanHandler;
|
||||
import io.micrometer.tracing.reporter.wavefront.WavefrontOtelSpanExporter;
|
||||
import io.micrometer.tracing.reporter.wavefront.WavefrontSpanHandler;
|
||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontSenderConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Wavefront tracing.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Glenn Oppegard
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
|
||||
WavefrontAutoConfiguration.class })
|
||||
@ConditionalOnClass({ WavefrontSender.class, WavefrontSpanHandler.class })
|
||||
@EnableConfigurationProperties(WavefrontProperties.class)
|
||||
@Import(WavefrontSenderConfiguration.class)
|
||||
public class WavefrontTracingAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(WavefrontSender.class)
|
||||
@ConditionalOnEnabledTracing("wavefront")
|
||||
WavefrontSpanHandler wavefrontSpanHandler(WavefrontProperties properties, WavefrontSender wavefrontSender,
|
||||
SpanMetrics spanMetrics, ApplicationTags applicationTags) {
|
||||
return new WavefrontSpanHandler(properties.getSender().getMaxQueueSize(), wavefrontSender, spanMetrics,
|
||||
properties.getSourceOrDefault(), applicationTags, properties.getTraceDerivedCustomTagKeys());
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(MeterRegistry.class)
|
||||
static class MeterRegistrySpanMetricsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
MeterRegistrySpanMetrics meterRegistrySpanMetrics(MeterRegistry meterRegistry) {
|
||||
return new MeterRegistrySpanMetrics(meterRegistry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(MeterRegistry.class)
|
||||
static class NoopSpanMetricsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SpanMetrics meterRegistrySpanMetrics() {
|
||||
return SpanMetrics.NOOP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(SpanHandler.class)
|
||||
static class WavefrontBrave {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledTracing("wavefront")
|
||||
WavefrontBraveSpanHandler wavefrontBraveSpanHandler(WavefrontSpanHandler wavefrontSpanHandler) {
|
||||
return new WavefrontBraveSpanHandler(wavefrontSpanHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(SpanExporter.class)
|
||||
static class WavefrontOpenTelemetry {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledTracing("wavefront")
|
||||
WavefrontOtelSpanExporter wavefrontOtelSpanExporter(WavefrontSpanHandler wavefrontSpanHandler) {
|
||||
return new WavefrontOtelSpanExporter(wavefrontSpanHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for tracing with Wavefront.
|
||||
*/
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing.wavefront;
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.application.ApplicationTags;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.Application;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Wavefront common infrastructure.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Glenn Oppegard
|
||||
* @author Phillip Webb
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass({ ApplicationTags.class, WavefrontSender.class })
|
||||
@EnableConfigurationProperties(WavefrontProperties.class)
|
||||
public class WavefrontAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ApplicationTags wavefrontApplicationTags(Environment environment, WavefrontProperties properties) {
|
||||
Application application = properties.getApplication();
|
||||
String serviceName = application.getServiceName();
|
||||
serviceName = (StringUtils.hasText(serviceName)) ? serviceName
|
||||
: environment.getProperty("spring.application.name", "unnamed_service");
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
ApplicationTags.Builder builder = new ApplicationTags.Builder(application.getName(), serviceName);
|
||||
map.from(application::getClusterName).to(builder::cluster);
|
||||
map.from(application::getShardName).to(builder::shard);
|
||||
map.from(application::getCustomTags).to(builder::customTags);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,446 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.wavefront.sdk.common.clients.service.token.TokenService.Type;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
|
||||
/**
|
||||
* Configuration properties to configure Wavefront.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Glenn Oppegard
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@ConfigurationProperties("management.wavefront")
|
||||
public class WavefrontProperties {
|
||||
|
||||
/**
|
||||
* URI to ship metrics and traces to.
|
||||
*/
|
||||
private URI uri = URI.create("https://longboard.wavefront.com");
|
||||
|
||||
/**
|
||||
* Unique identifier for the app instance that is the source of metrics and traces
|
||||
* being published to Wavefront. Defaults to the local host name.
|
||||
*/
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* API token used when publishing metrics and traces directly to the Wavefront API
|
||||
* host.
|
||||
*/
|
||||
private String apiToken;
|
||||
|
||||
/**
|
||||
* Type of the API token.
|
||||
*/
|
||||
private TokenType apiTokenType;
|
||||
|
||||
/**
|
||||
* Application configuration.
|
||||
*/
|
||||
private final Application application = new Application();
|
||||
|
||||
/**
|
||||
* Sender configuration.
|
||||
*/
|
||||
private final Sender sender = new Sender();
|
||||
|
||||
/**
|
||||
* Metrics configuration.
|
||||
*/
|
||||
private final Metrics metrics = new Metrics();
|
||||
|
||||
/**
|
||||
* Customized span tags for RED metrics.
|
||||
*/
|
||||
private Set<String> traceDerivedCustomTagKeys = new HashSet<>();
|
||||
|
||||
public Application getApplication() {
|
||||
return this.application;
|
||||
}
|
||||
|
||||
public Sender getSender() {
|
||||
return this.sender;
|
||||
}
|
||||
|
||||
public Metrics getMetrics() {
|
||||
return this.metrics;
|
||||
}
|
||||
|
||||
public URI getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public void setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public String getApiToken() {
|
||||
return this.apiToken;
|
||||
}
|
||||
|
||||
public void setApiToken(String apiToken) {
|
||||
this.apiToken = apiToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective URI of the wavefront instance. This will not be the same URI
|
||||
* given through {@link #setUri(URI)} when a proxy is used.
|
||||
* @return the effective URI of the wavefront instance
|
||||
*/
|
||||
public URI getEffectiveUri() {
|
||||
if (usesProxy()) {
|
||||
// See io.micrometer.wavefront.WavefrontMeterRegistry.getWavefrontReportingUri
|
||||
return URI.create(this.uri.toString().replace("proxy://", "http://"));
|
||||
}
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API token or throws an exception if the API token is mandatory. If a
|
||||
* proxy is used, the API token is optional.
|
||||
* @return the API token
|
||||
*/
|
||||
public String getApiTokenOrThrow() {
|
||||
if (this.apiTokenType != TokenType.NO_TOKEN && this.apiToken == null && !usesProxy()) {
|
||||
throw new InvalidConfigurationPropertyValueException("management.wavefront.api-token", null,
|
||||
"This property is mandatory whenever publishing directly to the Wavefront API");
|
||||
}
|
||||
return this.apiToken;
|
||||
}
|
||||
|
||||
public String getSourceOrDefault() {
|
||||
if (this.source != null) {
|
||||
return this.source;
|
||||
}
|
||||
return getSourceDefault();
|
||||
}
|
||||
|
||||
private String getSourceDefault() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch (UnknownHostException ex) {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private boolean usesProxy() {
|
||||
return "proxy".equals(this.uri.getScheme());
|
||||
}
|
||||
|
||||
public Set<String> getTraceDerivedCustomTagKeys() {
|
||||
return this.traceDerivedCustomTagKeys;
|
||||
}
|
||||
|
||||
public void setTraceDerivedCustomTagKeys(Set<String> traceDerivedCustomTagKeys) {
|
||||
this.traceDerivedCustomTagKeys = traceDerivedCustomTagKeys;
|
||||
}
|
||||
|
||||
public TokenType getApiTokenType() {
|
||||
return this.apiTokenType;
|
||||
}
|
||||
|
||||
public void setApiTokenType(TokenType apiTokenType) {
|
||||
this.apiTokenType = apiTokenType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Type Wavefront token type}.
|
||||
* @return the Wavefront token type
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public Type getWavefrontApiTokenType() {
|
||||
if (this.apiTokenType == null) {
|
||||
return usesProxy() ? Type.NO_TOKEN : Type.WAVEFRONT_API_TOKEN;
|
||||
}
|
||||
return switch (this.apiTokenType) {
|
||||
case NO_TOKEN -> Type.NO_TOKEN;
|
||||
case WAVEFRONT_API_TOKEN -> Type.WAVEFRONT_API_TOKEN;
|
||||
case CSP_API_TOKEN -> Type.CSP_API_TOKEN;
|
||||
case CSP_CLIENT_CREDENTIALS -> Type.CSP_CLIENT_CREDENTIALS;
|
||||
};
|
||||
}
|
||||
|
||||
public static class Application {
|
||||
|
||||
/**
|
||||
* Wavefront 'Application' name used in ApplicationTags.
|
||||
*/
|
||||
private String name = "unnamed_application";
|
||||
|
||||
/**
|
||||
* Wavefront 'Service' name used in ApplicationTags, falling back to
|
||||
* 'spring.application.name'. If both are unset it defaults to 'unnamed_service'.
|
||||
*/
|
||||
private String serviceName;
|
||||
|
||||
/**
|
||||
* Wavefront Cluster name used in ApplicationTags.
|
||||
*/
|
||||
private String clusterName;
|
||||
|
||||
/**
|
||||
* Wavefront Shard name used in ApplicationTags.
|
||||
*/
|
||||
private String shardName;
|
||||
|
||||
/**
|
||||
* Wavefront custom tags used in ApplicationTags.
|
||||
*/
|
||||
private Map<String, String> customTags = new HashMap<>();
|
||||
|
||||
public String getServiceName() {
|
||||
return this.serviceName;
|
||||
}
|
||||
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return this.clusterName;
|
||||
}
|
||||
|
||||
public void setClusterName(String clusterName) {
|
||||
this.clusterName = clusterName;
|
||||
}
|
||||
|
||||
public String getShardName() {
|
||||
return this.shardName;
|
||||
}
|
||||
|
||||
public void setShardName(String shardName) {
|
||||
this.shardName = shardName;
|
||||
}
|
||||
|
||||
public Map<String, String> getCustomTags() {
|
||||
return this.customTags;
|
||||
}
|
||||
|
||||
public void setCustomTags(Map<String, String> customTags) {
|
||||
this.customTags = customTags;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Sender {
|
||||
|
||||
/**
|
||||
* Maximum size of queued messages.
|
||||
*/
|
||||
private int maxQueueSize = 50000;
|
||||
|
||||
/**
|
||||
* Flush interval to send queued messages.
|
||||
*/
|
||||
private Duration flushInterval = Duration.ofSeconds(1);
|
||||
|
||||
/**
|
||||
* Maximum size of a message.
|
||||
*/
|
||||
private DataSize messageSize = DataSize.ofBytes(Integer.MAX_VALUE);
|
||||
|
||||
/**
|
||||
* Number of measurements per request to use for Wavefront. If more measurements
|
||||
* are found, then multiple requests will be made.
|
||||
*/
|
||||
private int batchSize = 10000;
|
||||
|
||||
public int getMaxQueueSize() {
|
||||
return this.maxQueueSize;
|
||||
}
|
||||
|
||||
public void setMaxQueueSize(int maxQueueSize) {
|
||||
this.maxQueueSize = maxQueueSize;
|
||||
}
|
||||
|
||||
public Duration getFlushInterval() {
|
||||
return this.flushInterval;
|
||||
}
|
||||
|
||||
public void setFlushInterval(Duration flushInterval) {
|
||||
this.flushInterval = flushInterval;
|
||||
}
|
||||
|
||||
public DataSize getMessageSize() {
|
||||
return this.messageSize;
|
||||
}
|
||||
|
||||
public void setMessageSize(DataSize messageSize) {
|
||||
this.messageSize = messageSize;
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return this.batchSize;
|
||||
}
|
||||
|
||||
public void setBatchSize(int batchSize) {
|
||||
this.batchSize = batchSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Metrics {
|
||||
|
||||
/**
|
||||
* Export configuration.
|
||||
*/
|
||||
private Export export = new Export();
|
||||
|
||||
public Export getExport() {
|
||||
return this.export;
|
||||
}
|
||||
|
||||
public void setExport(Export export) {
|
||||
this.export = export;
|
||||
}
|
||||
|
||||
public static class Export extends PushRegistryProperties {
|
||||
|
||||
/**
|
||||
* Global prefix to separate metrics originating from this app's
|
||||
* instrumentation from those originating from other Wavefront integrations
|
||||
* when viewed in the Wavefront UI.
|
||||
*/
|
||||
private String globalPrefix;
|
||||
|
||||
/**
|
||||
* Whether to report histogram distributions aggregated into minute intervals.
|
||||
*/
|
||||
private boolean reportMinuteDistribution = true;
|
||||
|
||||
/**
|
||||
* Whether to report histogram distributions aggregated into hour intervals.
|
||||
*/
|
||||
private boolean reportHourDistribution;
|
||||
|
||||
/**
|
||||
* Whether to report histogram distributions aggregated into day intervals.
|
||||
*/
|
||||
private boolean reportDayDistribution;
|
||||
|
||||
public String getGlobalPrefix() {
|
||||
return this.globalPrefix;
|
||||
}
|
||||
|
||||
public void setGlobalPrefix(String globalPrefix) {
|
||||
this.globalPrefix = globalPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link PushRegistryProperties#getBatchSize()}.
|
||||
*/
|
||||
@Override
|
||||
public Integer getBatchSize() {
|
||||
throw new UnsupportedOperationException("Use Sender.getBatchSize() instead");
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link PushRegistryProperties#setBatchSize(Integer)}.
|
||||
*/
|
||||
@Override
|
||||
public void setBatchSize(Integer batchSize) {
|
||||
throw new UnsupportedOperationException("Use Sender.setBatchSize(int) instead");
|
||||
}
|
||||
|
||||
public boolean isReportMinuteDistribution() {
|
||||
return this.reportMinuteDistribution;
|
||||
}
|
||||
|
||||
public void setReportMinuteDistribution(boolean reportMinuteDistribution) {
|
||||
this.reportMinuteDistribution = reportMinuteDistribution;
|
||||
}
|
||||
|
||||
public boolean isReportHourDistribution() {
|
||||
return this.reportHourDistribution;
|
||||
}
|
||||
|
||||
public void setReportHourDistribution(boolean reportHourDistribution) {
|
||||
this.reportHourDistribution = reportHourDistribution;
|
||||
}
|
||||
|
||||
public boolean isReportDayDistribution() {
|
||||
return this.reportDayDistribution;
|
||||
}
|
||||
|
||||
public void setReportDayDistribution(boolean reportDayDistribution) {
|
||||
this.reportDayDistribution = reportDayDistribution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wavefront token type.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public enum TokenType {
|
||||
|
||||
/**
|
||||
* No token.
|
||||
*/
|
||||
NO_TOKEN,
|
||||
/**
|
||||
* Wavefront API token.
|
||||
*/
|
||||
WAVEFRONT_API_TOKEN,
|
||||
/**
|
||||
* CSP API token.
|
||||
*/
|
||||
CSP_API_TOKEN,
|
||||
/**
|
||||
* CSP client credentials.
|
||||
*/
|
||||
CSP_CLIENT_CREDENTIALS
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.clients.WavefrontClient.Builder;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
|
||||
import org.springframework.boot.actuate.autoconfigure.tracing.wavefront.WavefrontTracingAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
|
||||
/**
|
||||
* Configuration for {@link WavefrontSender}. This configuration is imported from
|
||||
* {@link WavefrontMetricsExportAutoConfiguration} and
|
||||
* {@link WavefrontTracingAutoConfiguration}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(WavefrontSender.class)
|
||||
@EnableConfigurationProperties(WavefrontProperties.class)
|
||||
public class WavefrontSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(WavefrontTracingOrMetricsCondition.class)
|
||||
public WavefrontSender wavefrontSender(WavefrontProperties properties) {
|
||||
Builder builder = new Builder(properties.getEffectiveUri().toString(), properties.getWavefrontApiTokenType(),
|
||||
properties.getApiTokenOrThrow());
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
WavefrontProperties.Sender sender = properties.getSender();
|
||||
map.from(sender.getMaxQueueSize()).to(builder::maxQueueSize);
|
||||
map.from(sender.getFlushInterval()).asInt(Duration::getSeconds).to(builder::flushIntervalSeconds);
|
||||
map.from(sender.getMessageSize()).asInt(DataSize::toBytes).to(builder::messageSizeBytes);
|
||||
map.from(sender.getBatchSize()).to(builder::batchSize);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static final class WavefrontTracingOrMetricsCondition extends AnyNestedCondition {
|
||||
|
||||
WavefrontTracingOrMetricsCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnEnabledTracing("wavefront")
|
||||
static class TracingCondition {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnEnabledMetricsExport("wavefront")
|
||||
static class MetricsCondition {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes shared between Wavefront tracing and metrics.
|
||||
*/
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
@@ -1823,107 +1823,6 @@
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.api-token",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.api-token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.batch-size",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.sender.batch-size"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.connect-timeout",
|
||||
"type": "java.time.Duration",
|
||||
"deprecation": {
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.metrics.export.enabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.global-prefix",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.metrics.export.global-prefix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.num-threads",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.read-timeout",
|
||||
"type": "java.time.Duration",
|
||||
"deprecation": {
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.sender.flush-interval",
|
||||
"type": "java.time.Duration",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.sender.flush-interval"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.sender.max-queue-size",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.sender.max-queue-size"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.sender.message-size",
|
||||
"type": "org.springframework.util.unit.DataSize",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.sender.message-size"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.source",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.source"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.step",
|
||||
"type": "java.time.Duration",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.metrics.export.step"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.export.wavefront.uri",
|
||||
"type": "java.net.URI",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "management.wavefront.uri"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.metrics.graphql.autotime.enabled",
|
||||
"description": "Whether to automatically time web client requests.",
|
||||
@@ -2146,11 +2045,6 @@
|
||||
"W3C"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "management.wavefront.tracing.export.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether auto-configuration of tracing is enabled to export Wavefront traces."
|
||||
},
|
||||
{
|
||||
"name": "management.zipkin.tracing.encoding",
|
||||
"defaultValue": [
|
||||
|
||||
@@ -69,7 +69,6 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.signalfx.SignalFxM
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.export.stackdriver.StackdriverMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.batch.BatchObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.graphql.GraphQlObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration
|
||||
@@ -112,9 +111,7 @@ org.springframework.boot.actuate.autoconfigure.tracing.NoopTracerAutoConfigurati
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryTracingAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpTracingAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.prometheus.PrometheusExemplarsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.wavefront.WavefrontTracingAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.application.ApplicationTags;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.wavefront.WavefrontConfig;
|
||||
import io.micrometer.wavefront.WavefrontMeterRegistry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontMetricsExportAutoConfiguration}.
|
||||
*
|
||||
* @author Jon Schneider
|
||||
* @author Stephane Nicoll
|
||||
* @author Glenn Oppegard
|
||||
*/
|
||||
class WavefrontMetricsExportAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(WavefrontAutoConfiguration.class, WavefrontMetricsExportAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void backsOffWithoutAClock() {
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(WavefrontMeterRegistry.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigurationCanBeDisabledWithDefaultsEnabledProperty() {
|
||||
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
|
||||
.withPropertyValues("management.wavefront.api-token=abcde",
|
||||
"management.defaults.metrics.export.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontMeterRegistry.class)
|
||||
.doesNotHaveBean(WavefrontConfig.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigurationCanBeDisabledWithSpecificEnabledProperty() {
|
||||
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
|
||||
.withPropertyValues("management.wavefront.api-token=abcde",
|
||||
"management.wavefront.metrics.export.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontMeterRegistry.class)
|
||||
.doesNotHaveBean(WavefrontConfig.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowsConfigToBeCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomConfigConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(Clock.class)
|
||||
.hasSingleBean(WavefrontMeterRegistry.class)
|
||||
.hasSingleBean(WavefrontConfig.class)
|
||||
.hasSingleBean(WavefrontSender.class)
|
||||
.hasBean("customConfig"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowsRegistryToBeCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomRegistryConfiguration.class)
|
||||
.withPropertyValues("management.wavefront.api-token=abcde")
|
||||
.run((context) -> assertThat(context).hasSingleBean(Clock.class)
|
||||
.hasSingleBean(WavefrontConfig.class)
|
||||
.hasSingleBean(WavefrontMeterRegistry.class)
|
||||
.hasBean("customRegistry"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportsApplicationTagsInWavefrontRegistryWhenApplicationTagsBean() {
|
||||
ApplicationTags.Builder builder = new ApplicationTags.Builder("super-application", "super-service");
|
||||
builder.cluster("super-cluster");
|
||||
builder.shard("super-shard");
|
||||
builder.customTags(Map.of("custom-key", "custom-val"));
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class))
|
||||
.withUserConfiguration(BaseConfiguration.class)
|
||||
.withBean(ApplicationTags.class, builder::build)
|
||||
.run((context) -> {
|
||||
WavefrontMeterRegistry registry = context.getBean(WavefrontMeterRegistry.class);
|
||||
registry.counter("my.counter", "env", "qa");
|
||||
assertThat(registry.find("my.counter")
|
||||
.tags("env", "qa")
|
||||
.tags("application", "super-application")
|
||||
.tags("service", "super-service")
|
||||
.tags("cluster", "super-cluster")
|
||||
.tags("shard", "super-shard")
|
||||
.tags("custom-key", "custom-val")
|
||||
.counter()).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportsApplicationTagsInWavefrontRegistryWhenInProperties() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class))
|
||||
.withPropertyValues("management.wavefront.application.service-name=super-service",
|
||||
"management.wavefront.application.name=super-application",
|
||||
"management.wavefront.application.cluster-name=super-cluster",
|
||||
"management.wavefront.application.shard-name=super-shard")
|
||||
.withUserConfiguration(BaseConfiguration.class)
|
||||
.run((context) -> {
|
||||
WavefrontMeterRegistry registry = context.getBean(WavefrontMeterRegistry.class);
|
||||
registry.counter("my.counter", "env", "qa");
|
||||
assertThat(registry.find("my.counter")
|
||||
.tags("env", "qa")
|
||||
.tags("application", "super-application")
|
||||
.tags("service", "super-service")
|
||||
.tags("cluster", "super-cluster")
|
||||
.tags("shard", "super-shard")
|
||||
.counter()).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void stopsMeterRegistryWhenContextIsClosed() {
|
||||
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
|
||||
.withPropertyValues("management.wavefront.api-token=abcde")
|
||||
.run((context) -> {
|
||||
WavefrontMeterRegistry registry = context.getBean(WavefrontMeterRegistry.class);
|
||||
assertThat(registry.isClosed()).isFalse();
|
||||
context.close();
|
||||
assertThat(registry.isClosed()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class BaseConfiguration {
|
||||
|
||||
@Bean
|
||||
WavefrontSender customWavefrontSender() {
|
||||
return mock(WavefrontSender.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
Clock clock() {
|
||||
return Clock.SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(BaseConfiguration.class)
|
||||
static class CustomConfigConfiguration {
|
||||
|
||||
@Bean
|
||||
WavefrontConfig customConfig() {
|
||||
return new WavefrontConfig() {
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uri() {
|
||||
return WavefrontConfig.DEFAULT_DIRECT.uri();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiToken() {
|
||||
return "abc-def";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(BaseConfiguration.class)
|
||||
static class CustomSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
WavefrontSender customSender() {
|
||||
return mock(WavefrontSender.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(BaseConfiguration.class)
|
||||
static class CustomRegistryConfiguration {
|
||||
|
||||
@Bean
|
||||
WavefrontMeterRegistry customRegistry(WavefrontConfig config, Clock clock) {
|
||||
return new WavefrontMeterRegistry(config, clock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.wavefront.sdk.common.clients.service.token.TokenService.Type;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryPropertiesConfigAdapterTests;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.Metrics.Export;
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.TokenType;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontPropertiesConfigAdapter}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class WavefrontPropertiesConfigAdapterTests extends
|
||||
PushRegistryPropertiesConfigAdapterTests<WavefrontProperties.Metrics.Export, WavefrontPropertiesConfigAdapter> {
|
||||
|
||||
protected WavefrontPropertiesConfigAdapterTests() {
|
||||
super(WavefrontPropertiesConfigAdapter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WavefrontProperties.Metrics.Export createProperties() {
|
||||
return new WavefrontProperties.Metrics.Export();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WavefrontPropertiesConfigAdapter createConfigAdapter(WavefrontProperties.Metrics.Export export) {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.getMetrics().setExport(export);
|
||||
return new WavefrontPropertiesConfigAdapter(properties);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesGlobalPrefixIsSetAdapterGlobalPrefixReturnsIt() {
|
||||
Export properties = createProperties();
|
||||
properties.setGlobalPrefix("test");
|
||||
assertThat(createConfigAdapter(properties).globalPrefix()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void whenPropertiesBatchSizeIsSetAdapterBatchSizeReturnsIt() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.getSender().setBatchSize(10042);
|
||||
assertThat(new WavefrontPropertiesConfigAdapter(properties).batchSize()).isEqualTo(10042);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesUriIsSetAdapterUriReturnsIt() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setUri(URI.create("https://example.wavefront.com"));
|
||||
assertThat(new WavefrontPropertiesConfigAdapter(properties).uri()).isEqualTo("https://example.wavefront.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesApiTokenIsSetAdapterApiTokenReturnsIt() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setApiToken("my-token");
|
||||
assertThat(new WavefrontPropertiesConfigAdapter(properties).apiToken()).isEqualTo("my-token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesSourceIsSetAdapterSourceReturnsIt() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setSource("DESKTOP-GA5");
|
||||
assertThat(new WavefrontPropertiesConfigAdapter(properties).source()).isEqualTo("DESKTOP-GA5");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesReportMinuteDistributionIsSetAdapterReportMinuteDistributionReturnsIt() {
|
||||
Export properties = createProperties();
|
||||
properties.setReportMinuteDistribution(false);
|
||||
assertThat(createConfigAdapter(properties).reportMinuteDistribution()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesReportHourDistributionIsSetAdapterReportHourDistributionReturnsIt() {
|
||||
Export properties = createProperties();
|
||||
properties.setReportHourDistribution(true);
|
||||
assertThat(createConfigAdapter(properties).reportHourDistribution()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesReportDayDistributionIsSetAdapterReportDayDistributionReturnsIt() {
|
||||
Export properties = createProperties();
|
||||
properties.setReportDayDistribution(true);
|
||||
assertThat(createConfigAdapter(properties).reportDayDistribution()).isTrue();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource(textBlock = """
|
||||
null, WAVEFRONT_API_TOKEN
|
||||
NO_TOKEN, NO_TOKEN
|
||||
WAVEFRONT_API_TOKEN, WAVEFRONT_API_TOKEN
|
||||
CSP_API_TOKEN, CSP_API_TOKEN
|
||||
CSP_CLIENT_CREDENTIALS, CSP_CLIENT_CREDENTIALS
|
||||
""")
|
||||
void whenTokenTypeIsSetAdapterReturnsIt(String property, String wavefront) {
|
||||
TokenType propertyTokenType = property.equals("null") ? null : TokenType.valueOf(property);
|
||||
Type wavefrontTokenType = Type.valueOf(wavefront);
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setApiTokenType(propertyTokenType);
|
||||
assertThat(new WavefrontPropertiesConfigAdapter(properties).apiTokenType()).isEqualTo(wavefrontTokenType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing.wavefront;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link MeterRegistrySpanMetrics}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class MeterRegistrySpanMetricsTests {
|
||||
|
||||
private SimpleMeterRegistry meterRegistry;
|
||||
|
||||
private MeterRegistrySpanMetrics sut;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.meterRegistry = new SimpleMeterRegistry();
|
||||
this.sut = new MeterRegistrySpanMetrics(this.meterRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void reportDroppedShouldIncreaseCounter() {
|
||||
this.sut.reportDropped();
|
||||
assertThat(getCounterValue("wavefront.reporter.spans.dropped")).isOne();
|
||||
this.sut.reportDropped();
|
||||
assertThat(getCounterValue("wavefront.reporter.spans.dropped")).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void reportReceivedShouldIncreaseCounter() {
|
||||
this.sut.reportReceived();
|
||||
assertThat(getCounterValue("wavefront.reporter.spans.received")).isOne();
|
||||
this.sut.reportReceived();
|
||||
assertThat(getCounterValue("wavefront.reporter.spans.received")).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void reportErrorsShouldIncreaseCounter() {
|
||||
this.sut.reportErrors();
|
||||
assertThat(getCounterValue("wavefront.reporter.errors")).isOne();
|
||||
this.sut.reportErrors();
|
||||
assertThat(getCounterValue("wavefront.reporter.errors")).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerQueueSizeShouldCreateGauge() {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(2);
|
||||
this.sut.registerQueueSize(queue);
|
||||
assertThat(getGaugeValue("wavefront.reporter.queue.size")).isZero();
|
||||
queue.offer(1);
|
||||
assertThat(getGaugeValue("wavefront.reporter.queue.size")).isOne();
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerQueueRemainingCapacityShouldCreateGauge() {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(2);
|
||||
this.sut.registerQueueRemainingCapacity(queue);
|
||||
assertThat(getGaugeValue("wavefront.reporter.queue.remaining_capacity")).isEqualTo(2);
|
||||
queue.offer(1);
|
||||
assertThat(getGaugeValue("wavefront.reporter.queue.remaining_capacity")).isOne();
|
||||
}
|
||||
|
||||
private double getGaugeValue(String name) {
|
||||
Gauge gauge = this.meterRegistry.find(name).gauge();
|
||||
assertThat(gauge).withFailMessage("Gauge '%s' not found", name).isNotNull();
|
||||
return gauge.value();
|
||||
}
|
||||
|
||||
private double getCounterValue(String name) {
|
||||
Counter counter = this.meterRegistry.find(name).counter();
|
||||
assertThat(counter).withFailMessage("Counter '%s' not found", name).isNotNull();
|
||||
return counter.count();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing.wavefront;
|
||||
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.application.ApplicationTags;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.tracing.reporter.wavefront.SpanMetrics;
|
||||
import io.micrometer.tracing.reporter.wavefront.WavefrontBraveSpanHandler;
|
||||
import io.micrometer.tracing.reporter.wavefront.WavefrontOtelSpanExporter;
|
||||
import io.micrometer.tracing.reporter.wavefront.WavefrontSpanHandler;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontTracingAutoConfiguration}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Glenn Oppegard
|
||||
*/
|
||||
class WavefrontTracingAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(WavefrontAutoConfiguration.class, WavefrontTracingAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void shouldSupplyBeans() {
|
||||
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(ApplicationTags.class);
|
||||
assertThat(context).hasSingleBean(WavefrontSpanHandler.class);
|
||||
assertThat(context).hasSingleBean(SpanMetrics.class);
|
||||
assertThat(context).hasSingleBean(WavefrontBraveSpanHandler.class);
|
||||
assertThat(context).hasSingleBean(WavefrontOtelSpanExporter.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfWavefrontSenderIsMissing() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(WavefrontSender.class)).run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(ApplicationTags.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(SpanMetrics.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfMicrometerReporterWavefrontIsMissing() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("io.micrometer.tracing.reporter.wavefront"))
|
||||
.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(WavefrontSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(SpanMetrics.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfGlobalTracingIsDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
|
||||
.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(WavefrontSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfWavefrontTracingIsDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.wavefront.tracing.export.enabled=false")
|
||||
.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(WavefrontSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class);
|
||||
assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyMeterRegistrySpanMetricsIfMeterRegistryIsAvailable() {
|
||||
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class, MeterRegistryConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(SpanMetrics.class);
|
||||
assertThat(context).hasSingleBean(MeterRegistrySpanMetrics.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyWavefrontBraveSpanHandlerIfBraveIsMissing() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("brave"))
|
||||
.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyWavefrontOtelSpanExporterIfOtelIsMissing() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("io.opentelemetry.sdk.trace"))
|
||||
.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveADefaultApplicationNameAndServiceName() {
|
||||
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class).run((context) -> {
|
||||
ApplicationTags applicationTags = context.getBean(ApplicationTags.class);
|
||||
assertThat(applicationTags.getApplication()).isEqualTo("unnamed_application");
|
||||
assertThat(applicationTags.getService()).isEqualTo("unnamed_service");
|
||||
assertThat(applicationTags.getCluster()).isNull();
|
||||
assertThat(applicationTags.getShard()).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseSpringApplicationNameForServiceName() {
|
||||
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.withPropertyValues("spring.application.name=super-service")
|
||||
.run((context) -> {
|
||||
ApplicationTags applicationTags = context.getBean(ApplicationTags.class);
|
||||
assertThat(applicationTags.getApplication()).isEqualTo("unnamed_application");
|
||||
assertThat(applicationTags.getService()).isEqualTo("super-service");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHonorConfigProperties() {
|
||||
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.withPropertyValues("spring.application.name=ignored",
|
||||
"management.wavefront.application.name=super-application",
|
||||
"management.wavefront.application.service-name=super-service",
|
||||
"management.wavefront.application.cluster-name=super-cluster",
|
||||
"management.wavefront.application.shard-name=super-shard")
|
||||
.run((context) -> {
|
||||
ApplicationTags applicationTags = context.getBean(ApplicationTags.class);
|
||||
assertThat(applicationTags.getApplication()).isEqualTo("super-application");
|
||||
assertThat(applicationTags.getService()).isEqualTo("super-service");
|
||||
assertThat(applicationTags.getCluster()).isEqualTo("super-cluster");
|
||||
assertThat(applicationTags.getShard()).isEqualTo("super-shard");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldBackOffOnCustomBeans() {
|
||||
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class, CustomConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasBean("customApplicationTags");
|
||||
assertThat(context).hasSingleBean(ApplicationTags.class);
|
||||
assertThat(context).hasBean("customWavefrontSpanHandler");
|
||||
assertThat(context).hasSingleBean(WavefrontSpanHandler.class);
|
||||
assertThat(context).hasBean("customSpanMetrics");
|
||||
assertThat(context).hasSingleBean(SpanMetrics.class);
|
||||
assertThat(context).hasBean("customWavefrontBraveSpanHandler");
|
||||
assertThat(context).hasSingleBean(WavefrontBraveSpanHandler.class);
|
||||
assertThat(context).hasBean("customWavefrontOtelSpanExporter");
|
||||
assertThat(context).hasSingleBean(WavefrontOtelSpanExporter.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static final class CustomConfiguration {
|
||||
|
||||
@Bean
|
||||
ApplicationTags customApplicationTags() {
|
||||
return mock(ApplicationTags.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
WavefrontSpanHandler customWavefrontSpanHandler() {
|
||||
return mock(WavefrontSpanHandler.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
SpanMetrics customSpanMetrics() {
|
||||
return mock(SpanMetrics.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
WavefrontBraveSpanHandler customWavefrontBraveSpanHandler() {
|
||||
return mock(WavefrontBraveSpanHandler.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
WavefrontOtelSpanExporter customWavefrontOtelSpanExporter() {
|
||||
return mock(WavefrontOtelSpanExporter.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static final class WavefrontSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
WavefrontSender wavefrontSender() {
|
||||
return mock(WavefrontSender.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static final class MeterRegistryConfiguration {
|
||||
|
||||
@Bean
|
||||
MeterRegistry meterRegistry() {
|
||||
return new SimpleMeterRegistry();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -61,11 +61,9 @@ class ZipkinConfigurationsBraveConfigurationTests {
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyIfZipkinReporterBraveIsNotOnClasspath() {
|
||||
// Note: Technically, Brave can work without zipkin-reporter. For example,
|
||||
// WavefrontSpanHandler doesn't require this to operate. If we remove this
|
||||
// dependency enforcement when WavefrontSpanHandler is in use, we can resolve
|
||||
// micrometer-metrics/tracing#509. We also need this for any configuration that
|
||||
// uses senders defined in the Spring Boot source tree, such as HttpSender.
|
||||
// Note: Technically, Brave can work without zipkin-reporter. We also need this
|
||||
// for any configuration that uses senders defined in the Spring Boot source tree,
|
||||
// such as HttpSender.
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("zipkin2.reporter.brave"))
|
||||
.withUserConfiguration(SenderConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AsyncZipkinSpanHandler.class));
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.wavefront.sdk.common.application.ApplicationTags;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontAutoConfiguration}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class WavefrontAutoConfigurationTests {
|
||||
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(WavefrontAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void wavefrontApplicationTagsWhenHasUserBeanBacksOff() {
|
||||
this.contextRunner.withUserConfiguration(TestApplicationTagsConfiguration.class).run((context) -> {
|
||||
ApplicationTags tags = context.getBean(ApplicationTags.class);
|
||||
assertThat(tags.getApplication()).isEqualTo("test-application");
|
||||
assertThat(tags.getService()).isEqualTo("test-service");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void wavefrontApplicationTagsMapsProperties() {
|
||||
List<String> properties = new ArrayList<>();
|
||||
properties.add("management.wavefront.application.name=test-application");
|
||||
properties.add("management.wavefront.application.service-name=test-service");
|
||||
properties.add("management.wavefront.application.cluster-name=test-cluster");
|
||||
properties.add("management.wavefront.application.shard-name=test-shard");
|
||||
properties.add("management.wavefront.application.custom-tags.foo=FOO");
|
||||
properties.add("management.wavefront.application.custom-tags.bar=BAR");
|
||||
this.contextRunner.withPropertyValues(properties.toArray(String[]::new)).run((context) -> {
|
||||
ApplicationTags tags = context.getBean(ApplicationTags.class);
|
||||
assertThat(tags.getApplication()).isEqualTo("test-application");
|
||||
assertThat(tags.getService()).isEqualTo("test-service");
|
||||
assertThat(tags.getCluster()).isEqualTo("test-cluster");
|
||||
assertThat(tags.getShard()).isEqualTo("test-shard");
|
||||
assertThat(tags.getCustomTags()).hasSize(2).containsEntry("foo", "FOO").containsEntry("bar", "BAR");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void wavefrontApplicationTagsWhenNoPropertiesUsesDefaults() {
|
||||
this.contextRunner.withPropertyValues("spring.application.name=spring-app").run((context) -> {
|
||||
ApplicationTags tags = context.getBean(ApplicationTags.class);
|
||||
assertThat(tags.getApplication()).isEqualTo("unnamed_application");
|
||||
assertThat(tags.getService()).isEqualTo("spring-app");
|
||||
assertThat(tags.getCluster()).isNull();
|
||||
assertThat(tags.getShard()).isNull();
|
||||
assertThat(tags.getCustomTags()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void wavefrontApplicationTagsWhenHasNoServiceNamePropertyAndNoSpringApplicationNameUsesDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
ApplicationTags tags = context.getBean(ApplicationTags.class);
|
||||
assertThat(tags.getService()).isEqualTo("unnamed_service");
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TestApplicationTagsConfiguration {
|
||||
|
||||
@Bean
|
||||
ApplicationTags applicationTags() {
|
||||
return new ApplicationTags.Builder("test-application", "test-service").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import io.micrometer.wavefront.WavefrontConfig;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontProperties.Metrics.Export}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class WavefrontPropertiesMetricsExportTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void defaultValuesAreConsistent() {
|
||||
WavefrontProperties.Metrics.Export properties = new WavefrontProperties.Metrics.Export();
|
||||
WavefrontConfig config = WavefrontConfig.DEFAULT_DIRECT;
|
||||
assertThat(properties.getConnectTimeout()).isEqualTo(config.connectTimeout());
|
||||
assertThat(properties.getGlobalPrefix()).isEqualTo(config.globalPrefix());
|
||||
assertThat(properties.getReadTimeout()).isEqualTo(config.readTimeout());
|
||||
assertThat(properties.getStep()).isEqualTo(config.step());
|
||||
assertThat(properties.isEnabled()).isEqualTo(config.enabled());
|
||||
assertThat(properties.isReportMinuteDistribution()).isEqualTo(config.reportMinuteDistribution());
|
||||
assertThat(properties.isReportHourDistribution()).isEqualTo(config.reportHourDistribution());
|
||||
assertThat(properties.isReportDayDistribution()).isEqualTo(config.reportDayDistribution());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.wavefront.sdk.common.clients.service.token.TokenService.Type;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.TokenType;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontProperties}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class WavefrontPropertiesTests {
|
||||
|
||||
@Test
|
||||
void apiTokenIsOptionalWhenUsingProxy() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setUri(URI.create("proxy://localhost:2878"));
|
||||
properties.setApiToken(null);
|
||||
assertThat(properties.getApiTokenOrThrow()).isNull();
|
||||
assertThat(properties.getEffectiveUri()).isEqualTo(URI.create("http://localhost:2878"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void apiTokenIsMandatoryWhenNotUsingProxy() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setUri(URI.create("http://localhost:2878"));
|
||||
properties.setApiToken(null);
|
||||
assertThat(properties.getEffectiveUri()).isEqualTo(URI.create("http://localhost:2878"));
|
||||
assertThatExceptionOfType(InvalidConfigurationPropertyValueException.class)
|
||||
.isThrownBy(properties::getApiTokenOrThrow)
|
||||
.withMessageContaining("management.wavefront.api-token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotFailIfTokenTypeIsSetToNoToken() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setUri(URI.create("http://localhost:2878"));
|
||||
properties.setApiTokenType(TokenType.NO_TOKEN);
|
||||
properties.setApiToken(null);
|
||||
assertThat(properties.getApiTokenOrThrow()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void wavefrontApiTokenTypeWhenUsingProxy() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setUri(URI.create("proxy://localhost:2878"));
|
||||
assertThat(properties.getWavefrontApiTokenType()).isEqualTo(Type.NO_TOKEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void wavefrontApiTokenTypeWhenNotUsingProxy() {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setUri(URI.create("http://localhost:2878"));
|
||||
assertThat(properties.getWavefrontApiTokenType()).isEqualTo(Type.WAVEFRONT_API_TOKEN);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource
|
||||
void wavefrontApiTokenMapping(TokenType from) {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
properties.setApiTokenType(from);
|
||||
Type expected = Type.valueOf(from.name());
|
||||
assertThat(properties.getWavefrontApiTokenType()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.wavefront;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import com.wavefront.sdk.common.WavefrontSender;
|
||||
import com.wavefront.sdk.common.clients.service.token.CSPTokenService;
|
||||
import com.wavefront.sdk.common.clients.service.token.NoopProxyTokenService;
|
||||
import com.wavefront.sdk.common.clients.service.token.WavefrontTokenService;
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.as;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link WavefrontSenderConfiguration}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class WavefrontSenderConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(WavefrontSenderConfiguration.class));
|
||||
|
||||
private final ApplicationContextRunner metricsDisabledContextRunner = this.contextRunner.withPropertyValues(
|
||||
"management.defaults.metrics.export.enabled=false", "management.simple.metrics.export.enabled=true");
|
||||
|
||||
@Test
|
||||
void shouldNotFailIfWavefrontIsMissing() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("com.wavefront"))
|
||||
.run(((context) -> assertThat(context).doesNotHaveBean(WavefrontSender.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void failsWithoutAnApiTokenWhenPublishingDirectly() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasFailed());
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultWavefrontSenderSettingsAreConsistent() {
|
||||
this.contextRunner.withPropertyValues("management.wavefront.api-token=abcde").run((context) -> {
|
||||
WavefrontProperties properties = new WavefrontProperties();
|
||||
WavefrontSender sender = context.getBean(WavefrontSender.class);
|
||||
assertThat(sender)
|
||||
.extracting("metricsBuffer", as(InstanceOfAssertFactories.type(LinkedBlockingQueue.class)))
|
||||
.satisfies((queue) -> assertThat(queue.remainingCapacity() + queue.size())
|
||||
.isEqualTo(properties.getSender().getMaxQueueSize()));
|
||||
assertThat(sender).hasFieldOrPropertyWithValue("batchSize", properties.getSender().getBatchSize());
|
||||
assertThat(sender).hasFieldOrPropertyWithValue("messageSizeBytes",
|
||||
(int) properties.getSender().getMessageSize().toBytes());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWavefrontSender() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.wavefront.api-token=abcde", "management.wavefront.sender.batch-size=50",
|
||||
"management.wavefront.sender.max-queue-size=100", "management.wavefront.sender.message-size=1KB")
|
||||
.run((context) -> {
|
||||
WavefrontSender sender = context.getBean(WavefrontSender.class);
|
||||
assertThat(sender).hasFieldOrPropertyWithValue("batchSize", 50);
|
||||
assertThat(sender)
|
||||
.extracting("metricsBuffer", as(InstanceOfAssertFactories.type(LinkedBlockingQueue.class)))
|
||||
.satisfies((queue) -> assertThat(queue.remainingCapacity() + queue.size()).isEqualTo(100));
|
||||
assertThat(sender).hasFieldOrPropertyWithValue("messageSizeBytes", 1024);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyWavefrontSenderIfMetricsAndGlobalTracingIsDisabled() {
|
||||
this.metricsDisabledContextRunner
|
||||
.withPropertyValues("management.tracing.enabled=false", "management.wavefront.api-token=abcde")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontSender.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyWavefrontSenderIfMetricsAndWavefrontTracingIsDisabled() {
|
||||
this.metricsDisabledContextRunner
|
||||
.withPropertyValues("management.wavefront.tracing.export.enabled=false",
|
||||
"management.wavefront.api-token=abcde")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontSender.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyWavefrontSenderIfOnlyGlobalTracingIsDisabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.tracing.enabled=false", "management.wavefront.api-token=abcde")
|
||||
.run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyWavefrontSenderIfOnlyWavefrontTracingIsDisabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.wavefront.tracing.export.enabled=false",
|
||||
"management.wavefront.api-token=abcde")
|
||||
.run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyWavefrontSenderIfOnlyMetricsAreDisabled() {
|
||||
this.metricsDisabledContextRunner.withPropertyValues("management.wavefront.api-token=abcde")
|
||||
.run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowsWavefrontSenderToBeCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomSenderConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class).hasBean("customSender"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyTokenTypeWavefrontApiToken() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.wavefront.api-token-type=WAVEFRONT_API_TOKEN",
|
||||
"management.wavefront.api-token=abcde")
|
||||
.run((context) -> {
|
||||
WavefrontSender sender = context.getBean(WavefrontSender.class);
|
||||
assertThat(sender).extracting("tokenService").isInstanceOf(WavefrontTokenService.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyTokenTypeCspApiToken() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.wavefront.api-token-type=CSP_API_TOKEN",
|
||||
"management.wavefront.api-token=abcde")
|
||||
.run((context) -> {
|
||||
WavefrontSender sender = context.getBean(WavefrontSender.class);
|
||||
assertThat(sender).extracting("tokenService").isInstanceOf(CSPTokenService.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyTokenTypeCspClientCredentials() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.wavefront.api-token-type=CSP_CLIENT_CREDENTIALS",
|
||||
"management.wavefront.api-token=clientid=cid,clientsecret=csec")
|
||||
.run((context) -> {
|
||||
WavefrontSender sender = context.getBean(WavefrontSender.class);
|
||||
assertThat(sender).extracting("tokenService").isInstanceOf(CSPTokenService.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyTokenTypeNoToken() {
|
||||
this.contextRunner.withPropertyValues("management.wavefront.api-token-type=NO_TOKEN").run((context) -> {
|
||||
WavefrontSender sender = context.getBean(WavefrontSender.class);
|
||||
assertThat(sender).extracting("tokenService").isInstanceOf(NoopProxyTokenService.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
WavefrontSender customSender() {
|
||||
return mock(WavefrontSender.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1140,8 +1140,6 @@
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export.stackdriver[#production-ready-metrics-export-stackdriver]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export.statsd[#actuator.metrics.export.statsd]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export.statsd[#production-ready-metrics-export-statsd]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export.wavefront[#actuator.metrics.export.wavefront]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export.wavefront[#production-ready-metrics-export-wavefront]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export[#actuator.metrics.export]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.export[#production-ready-metrics-export]
|
||||
* xref:reference:actuator/metrics.adoc#actuator.metrics.getting-started[#actuator.metrics.getting-started]
|
||||
@@ -1228,10 +1226,8 @@
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.micrometer-observation[#actuator.micrometer-tracing.micrometer-observation]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.propagating-traces[#actuator.micrometer-tracing.propagating-traces]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tests[#actuator.micrometer-tracing.tests]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracer-implementations.brave-wavefront[#actuator.micrometer-tracing.tracer-implementations.brave-wavefront]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracer-implementations.brave-zipkin[#actuator.micrometer-tracing.tracer-implementations.brave-zipkin]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracer-implementations.otel-otlp[#actuator.micrometer-tracing.tracer-implementations.otel-otlp]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracer-implementations.otel-wavefront[#actuator.micrometer-tracing.tracer-implementations.otel-wavefront]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracer-implementations.otel-zipkin[#actuator.micrometer-tracing.tracer-implementations.otel-zipkin]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracer-implementations[#actuator.micrometer-tracing.tracer-implementations]
|
||||
* xref:reference:actuator/tracing.adoc#actuator.micrometer-tracing.tracers[#actuator.micrometer-tracing.tracers]
|
||||
|
||||
@@ -20,7 +20,6 @@ Spring Boot Actuator provides dependency management and auto-configuration for {
|
||||
- xref:actuator/metrics.adoc#actuator.metrics.export.simple[] (in-memory)
|
||||
- xref:actuator/metrics.adoc#actuator.metrics.export.stackdriver[]
|
||||
- xref:actuator/metrics.adoc#actuator.metrics.export.statsd[]
|
||||
- xref:actuator/metrics.adoc#actuator.metrics.export.wavefront[]
|
||||
|
||||
TIP: To learn more about Micrometer's capabilities, see its {url-micrometer-docs}[reference documentation], in particular the {url-micrometer-docs-concepts}[concepts section].
|
||||
|
||||
@@ -650,43 +649,6 @@ management:
|
||||
|
||||
|
||||
|
||||
[[actuator.metrics.export.wavefront]]
|
||||
=== Wavefront
|
||||
|
||||
The Wavefront registry periodically pushes metrics to {url-micrometer-docs-implementations}/wavefront[Wavefront].
|
||||
If you are exporting metrics to https://www.wavefront.com/[Wavefront] directly, you must provide your API token:
|
||||
|
||||
[configprops,yaml]
|
||||
----
|
||||
management:
|
||||
wavefront:
|
||||
api-token: "YOUR_API_TOKEN"
|
||||
----
|
||||
|
||||
Alternatively, you can use a Wavefront sidecar or an internal proxy in your environment to forward metrics data to the Wavefront API host:
|
||||
|
||||
[configprops,yaml]
|
||||
----
|
||||
management:
|
||||
wavefront:
|
||||
uri: "proxy://localhost:2878"
|
||||
----
|
||||
|
||||
NOTE: If you publish metrics to a Wavefront proxy (as described in https://docs.wavefront.com/proxies_installing.html[the Wavefront documentation]), the host must be in the `proxy://HOST:PORT` format.
|
||||
|
||||
You can also change the interval at which metrics are sent to Wavefront:
|
||||
|
||||
[configprops,yaml]
|
||||
----
|
||||
management:
|
||||
wavefront:
|
||||
metrics:
|
||||
export:
|
||||
step: "30s"
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[actuator.metrics.supported]]
|
||||
== Supported Metrics and Meters
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ TIP: To learn more about Micrometer Tracing capabilities, see its {url-micromete
|
||||
|
||||
Spring Boot ships auto-configuration for the following tracers:
|
||||
|
||||
* https://opentelemetry.io/[OpenTelemetry] with https://zipkin.io/[Zipkin], https://docs.wavefront.com/[Wavefront], or https://opentelemetry.io/docs/reference/specification/protocol/[OTLP]
|
||||
* https://github.com/openzipkin/brave[OpenZipkin Brave] with https://zipkin.io/[Zipkin] or https://docs.wavefront.com/[Wavefront]
|
||||
* https://opentelemetry.io/[OpenTelemetry] with https://zipkin.io/[Zipkin] or https://opentelemetry.io/docs/reference/specification/protocol/[OTLP].
|
||||
* https://github.com/openzipkin/brave[OpenZipkin Brave] with https://zipkin.io/[Zipkin].
|
||||
|
||||
|
||||
|
||||
@@ -128,18 +128,6 @@ Use the `management.zipkin.tracing.*` configuration properties to configure repo
|
||||
|
||||
|
||||
|
||||
[[actuator.micrometer-tracing.tracer-implementations.otel-wavefront]]
|
||||
=== OpenTelemetry With Wavefront
|
||||
|
||||
Tracing with OpenTelemetry and reporting to Wavefront requires the following dependencies:
|
||||
|
||||
* `io.micrometer:micrometer-tracing-bridge-otel` - bridges the Micrometer Observation API to OpenTelemetry.
|
||||
* `io.micrometer:micrometer-tracing-reporter-wavefront` - reports traces to Wavefront.
|
||||
|
||||
Use the `management.wavefront.*` configuration properties to configure reporting to Wavefront.
|
||||
|
||||
|
||||
|
||||
[[actuator.micrometer-tracing.tracer-implementations.otel-otlp]]
|
||||
=== OpenTelemetry With OTLP
|
||||
|
||||
@@ -168,18 +156,6 @@ Use the `management.zipkin.tracing.*` configuration properties to configure repo
|
||||
|
||||
|
||||
|
||||
[[actuator.micrometer-tracing.tracer-implementations.brave-wavefront]]
|
||||
=== OpenZipkin Brave With Wavefront
|
||||
|
||||
Tracing with OpenZipkin Brave and reporting to Wavefront requires the following dependencies:
|
||||
|
||||
* `io.micrometer:micrometer-tracing-bridge-brave` - bridges the Micrometer Observation API to Brave.
|
||||
* `io.micrometer:micrometer-tracing-reporter-wavefront` - reports traces to Wavefront.
|
||||
|
||||
Use the `management.wavefront.*` configuration properties to configure reporting to Wavefront.
|
||||
|
||||
|
||||
|
||||
[[actuator.micrometer-tracing.micrometer-observation]]
|
||||
== Integration with Micrometer Observation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user