Support Observations for CommandLineRunner and ApplicationRunner

First pass on observation

Added automatic docs generation

Renamed Observed -> Observation

Fixed copyright dates

Removed execution task listener - it makes runner spans share the same trace id

Updated version for micrometer docs to milestone
This commit is contained in:
Marcin Grzejszczak
2022-05-11 11:22:01 +02:00
committed by Glenn Renfro
parent 79a9a59e08
commit 3817fe14e7
16 changed files with 699 additions and 1 deletions

View File

@@ -15,6 +15,12 @@
<configprops.inclusionPattern>spring.cloud.task.*</configprops.inclusionPattern>
<upload-docs-zip.phase>deploy</upload-docs-zip.phase>
<asciidoctorj.pdf.version>1.5.0-alpha.16</asciidoctorj.pdf.version>
<!-- Observability -->
<micrometer-docs-generator.version>1.0.0-M4</micrometer-docs-generator.version>
<micrometer-docs-generator.inputPath>${maven.multiModuleProjectDirectory}/spring-cloud-task-core/</micrometer-docs-generator.inputPath>
<micrometer-docs-generator.inclusionPattern>.*</micrometer-docs-generator.inclusionPattern>
<micrometer-docs-generator.outputPath>${maven.multiModuleProjectDirectory}/target/</micrometer-docs-generator.outputPath>
</properties>
<dependencies>
<dependency>
@@ -49,6 +55,58 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-metrics-metadata</id>
<phase>prepare-package</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>io.micrometer.docs.metrics.DocsFromSources</mainClass>
<includePluginDependencies>true</includePluginDependencies>
<arguments>
<argument>${micrometer-docs-generator.inputPath}</argument>
<argument>${micrometer-docs-generator.inclusionPattern}</argument>
<argument>${micrometer-docs-generator.outputPath}</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>generate-tracing-metadata</id>
<phase>prepare-package</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>io.micrometer.docs.spans.DocsFromSources</mainClass>
<includePluginDependencies>true</includePluginDependencies>
<arguments>
<argument>${micrometer-docs-generator.inputPath}</argument>
<argument>${micrometer-docs-generator.inclusionPattern}</argument>
<argument>${micrometer-docs-generator.outputPath}</argument>
</arguments>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>io.micrometer
</groupId>
<artifactId>micrometer-docs-generator-spans</artifactId>
<version>${micrometer-docs-generator.version}
</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>io.micrometer
</groupId>
<artifactId>micrometer-docs-generator-metrics</artifactId>
<version>${micrometer-docs-generator.version}
</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>

View File

@@ -0,0 +1,8 @@
:root-target: ../../../../target/
[[observability]]
== Observability metadata
include::{root-target}_metrics.adoc[]
include::{root-target}_spans.adoc[]

View File

@@ -3,4 +3,7 @@
= Appendices
include::appendix-task-repository-schema.adoc[]
include::appendix-building-the-documentation.adoc[]
include::_observability.adoc[]

View File

@@ -109,10 +109,19 @@
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
@@ -129,6 +138,41 @@
<version>${jmock-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-urlconnection</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import io.micrometer.common.KeyValues;
import io.micrometer.observation.Observation;
/**
* {@link Observation.KeyValuesProvider} for Spring Cloud Task.
*
* @author Marcin Grzejszczak
* @since 3.0.0
*/
public class DefaultTaskKeyValuesProvider implements TaskKeyValuesProvider {
@Override
public KeyValues getLowCardinalityKeyValues(TaskObservationContext context) {
return KeyValues.of(TaskDocumentedObservation.TaskRunnerTags.BEAN_NAME.of(context.getBeanName()));
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2018-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.cloud.task.configuration.observation;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
/**
* Observed representation of a {@link ApplicationRunner}.
*
* @author Marcin Grzejszczak
*/
class ObservationApplicationRunner implements ApplicationRunner, Observation.KeyValuesProviderAware<TaskKeyValuesProvider> {
private final BeanFactory beanFactory;
private final ApplicationRunner delegate;
private final String beanName;
private ObservationRegistry registry;
private TaskKeyValuesProvider keyValuesProvider = new DefaultTaskKeyValuesProvider();
ObservationApplicationRunner(BeanFactory beanFactory, ApplicationRunner delegate, String beanName) {
this.beanFactory = beanFactory;
this.delegate = delegate;
this.beanName = beanName;
}
@Override
public void run(ApplicationArguments args) throws Exception {
TaskObservationContext context = new TaskObservationContext(this.beanName);
Observation observation = TaskDocumentedObservation.TASK_RUNNER_OBSERVATION.observation(registry(), context)
.contextualName(this.beanName)
.keyValuesProvider(this.keyValuesProvider);
try (Observation.Scope scope = observation.start().openScope()) {
this.delegate.run(args);
}
catch (Exception error) {
observation.error(error);
throw error;
}
finally {
observation.stop();
}
}
private ObservationRegistry registry() {
if (this.registry == null) {
this.registry = this.beanFactory.getBean(ObservationRegistry.class);
}
return this.registry;
}
@Override
public void setKeyValuesProvider(TaskKeyValuesProvider keyValuesProvider) {
this.keyValuesProvider = keyValuesProvider;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.ApplicationRunner;
/**
* Registers beans related to task scheduling.
*
* @author Marcin Grzejszczak
*/
class ObservationApplicationRunnerBeanPostProcessor implements BeanPostProcessor {
private final BeanFactory beanFactory;
ObservationApplicationRunnerBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof ApplicationRunner applicationRunner && !(bean instanceof ObservationApplicationRunner)) {
return new ObservationApplicationRunner(this.beanFactory, applicationRunner, beanName);
}
return bean;
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2018-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.cloud.task.configuration.observation;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.CommandLineRunner;
/**
* Observed representation of a {@link CommandLineRunner}.
*
* @author Marcin Grzejszczak
*/
class ObservationCommandLineRunner implements CommandLineRunner, Observation.KeyValuesProviderAware<TaskKeyValuesProvider> {
private final BeanFactory beanFactory;
private final CommandLineRunner delegate;
private final String beanName;
private ObservationRegistry registry;
private TaskKeyValuesProvider keyValuesProvider = new DefaultTaskKeyValuesProvider();
ObservationCommandLineRunner(BeanFactory beanFactory, CommandLineRunner delegate, String beanName) {
this.beanFactory = beanFactory;
this.delegate = delegate;
this.beanName = beanName;
}
@Override
public void run(String... args) throws Exception {
TaskObservationContext context = new TaskObservationContext(this.beanName);
Observation observation = TaskDocumentedObservation.TASK_RUNNER_OBSERVATION.observation(registry(), context)
.contextualName(this.beanName)
.keyValuesProvider(this.keyValuesProvider);
try (Observation.Scope scope = observation.start().openScope()) {
this.delegate.run(args);
}
catch (Exception error) {
observation.error(error);
throw error;
}
finally {
observation.stop();
}
}
private ObservationRegistry registry() {
if (this.registry == null) {
this.registry = this.beanFactory.getBean(ObservationRegistry.class);
}
return this.registry;
}
@Override
public void setKeyValuesProvider(TaskKeyValuesProvider keyValuesProvider) {
this.keyValuesProvider = keyValuesProvider;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.CommandLineRunner;
/**
* Registers beans related to task scheduling.
*
* @author Marcin Grzejszczak
*/
class ObservationCommandLineRunnerBeanPostProcessor implements BeanPostProcessor {
private final BeanFactory beanFactory;
ObservationCommandLineRunnerBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof CommandLineRunner commandLineRunner && !(bean instanceof ObservationCommandLineRunner)) {
return new ObservationCommandLineRunner(this.beanFactory, commandLineRunner, beanName);
}
return bean;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} that registers instrumentation for Spring Cloud Task.
*
* @author Marcin Grzejszczak
* @since 3.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObservationRegistry.class)
@ConditionalOnProperty(value = "spring.cloud.task.observation.enabled", matchIfMissing = true)
@ConditionalOnBean(ObservationRegistry.class)
@AutoConfigureAfter(ObservationAutoConfiguration.class)
public class ObservationTaskAutoConfiguration {
@Bean
static ObservationCommandLineRunnerBeanPostProcessor observedCommandLineRunnerBeanPostProcessor(BeanFactory beanFactory) {
return new ObservationCommandLineRunnerBeanPostProcessor(beanFactory);
}
@Bean
static ObservationApplicationRunnerBeanPostProcessor observedApplicationRunnerBeanPostProcessor(BeanFactory beanFactory) {
return new ObservationApplicationRunnerBeanPostProcessor(beanFactory);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import io.micrometer.common.docs.KeyName;
import io.micrometer.observation.docs.DocumentedObservation;
enum TaskDocumentedObservation implements DocumentedObservation {
/**
* Observation created when a task runner is executed.
*/
TASK_RUNNER_OBSERVATION {
@Override
public String getName() {
return "spring.cloud.task.runner";
}
@Override
public KeyName[] getLowCardinalityKeyNames() {
return TaskRunnerTags.values();
}
@Override
public String getPrefix() {
return "spring.cloud.task";
}
};
/**
* Key names for Spring Cloud Task Command / Application runners.
*/
enum TaskRunnerTags implements KeyName {
/**
* Name of the bean that was executed by Spring Cloud Task.
*/
BEAN_NAME {
@Override
public String getKeyName() {
return "spring.cloud.task.runner.bean-name";
}
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import io.micrometer.observation.Observation;
/**
* {@link Observation.KeyValuesProvider} for Spring Cloud Task.
*
* @author Marcin Grzejszczak
* @since 3.0.0
*/
public interface TaskKeyValuesProvider extends Observation.KeyValuesProvider<TaskObservationContext> {
@Override
default boolean supportsContext(Observation.Context context) {
return context instanceof TaskObservationContext;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2013-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.cloud.task.configuration.observation;
import io.micrometer.observation.Observation;
/**
* {@link Observation.Context} for Spring Cloud Task.
*
* @author Marcin Grzejszczak
* @since 3.0.0
*/
public class TaskObservationContext extends Observation.Context {
private final String beanName;
public TaskObservationContext(String beanName) {
this.beanName = beanName;
}
public String getBeanName() {
return beanName;
}
}

View File

@@ -1,5 +1,6 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.task.configuration.SingleTaskConfiguration,\
org.springframework.cloud.task.configuration.SimpleTaskAutoConfiguration,\
org.springframework.cloud.task.configuration.MetricsAutoConfiguration\
org.springframework.cloud.task.configuration.MetricsAutoConfiguration,\
org.springframework.cloud.task.configuration.observation.ObservationTaskAutoConfiguration

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2017-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.cloud.task.configuration.observation;
import java.util.List;
import java.util.stream.Collectors;
import brave.handler.SpanHandler;
import brave.sampler.Sampler;
import brave.test.TestSpanHandler;
import io.micrometer.common.KeyValues;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.tck.MeterRegistryAssert;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.brave.bridge.BraveFinishedSpan;
import io.micrometer.tracing.exporter.FinishedSpan;
import io.micrometer.tracing.test.simple.SpansAssert;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import zipkin2.Span;
import zipkin2.reporter.Reporter;
import zipkin2.reporter.brave.ZipkinSpanHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.MicrometerTracingAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.task.configuration.EnableTask;
import org.springframework.cloud.task.configuration.SimpleTaskAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@SpringBootTest(classes = ObservationIntegrationTests.Config.class)
class ObservationIntegrationTests {
@Autowired
TestSpanHandler testSpanHandler;
@Autowired
MeterRegistry meterRegistry;
@Test
void testSuccessfulObservation() {
List<FinishedSpan> finishedSpans = finishedSpans();
SpansAssert.then(finishedSpans)
.thenASpanWithNameEqualTo("my-command-line-runner")
.hasTag("spring.cloud.task.runner.bean-name", "myCommandLineRunner")
.backToSpans()
.thenASpanWithNameEqualTo("my-application-runner")
.hasTag("spring.cloud.task.runner.bean-name", "myApplicationRunner");
MeterRegistryAssert.then(this.meterRegistry)
.hasTimerWithNameAndTags("spring.cloud.task.runner", KeyValues.of("spring.cloud.task.runner.bean-name", "myCommandLineRunner"))
.hasTimerWithNameAndTags("spring.cloud.task.runner", KeyValues.of("spring.cloud.task.runner.bean-name", "myApplicationRunner"));
}
private List<FinishedSpan> finishedSpans() {
return this.testSpanHandler.spans().stream().map(BraveFinishedSpan::fromBrave).collect(Collectors.toList());
}
@Configuration
@ImportAutoConfiguration({SimpleTaskAutoConfiguration.class, ObservationAutoConfiguration.class, ObservationTaskAutoConfiguration.class, BraveAutoConfiguration.class, MicrometerTracingAutoConfiguration.class, MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class, ZipkinAutoConfiguration.class})
@EnableTask
static class Config {
private static final Logger log = LoggerFactory.getLogger(Config.class);
@Bean
TestSpanHandler testSpanHandler() {
return new TestSpanHandler();
}
@Bean
SpanHandler zipkinSpanHandler(Reporter<Span> spanReporter) {
return ZipkinSpanHandler.newBuilder(spanReporter).build();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
CommandLineRunner myCommandLineRunner(Tracer tracer) {
return args -> log.info("<TRACE:{}> Hello from command line runner", tracer.currentSpan().context().traceId());
}
@Bean
ApplicationRunner myApplicationRunner(Tracer tracer) {
return args -> log.info("<TRACE:{}> Hello from application runner", tracer.currentSpan().context().traceId());
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<suppress files=".*ObservationTaskAutoConfiguration.*" checks="HideUtilityClassConstructorCheck"/>
</suppressions>