Create a SleuthMongoConfiguration class to tag Mongodb as a remote service

fixes gh-1627
This commit is contained in:
Marcin Grzejszczak
2020-06-29 18:35:34 +02:00
parent 18055a5ec3
commit f6b40385ab
6 changed files with 209 additions and 1 deletions

View File

@@ -176,6 +176,11 @@
<artifactId>feign-okhttp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
@@ -239,6 +244,10 @@
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-jms</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-mongodb</artifactId>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2013-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.
*/
package org.springframework.cloud.sleuth.instrument.mongodb;
import brave.Tracing;
import brave.mongodb.MongoDBTracing;
import com.mongodb.MongoClientSettings;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} enables MongoDb span information propagation.
*
* @author Marcin Grzejszczak
* @since 3.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(Tracing.class)
@AutoConfigureAfter(TraceAutoConfiguration.class)
@AutoConfigureBefore(MongoAutoConfiguration.class)
@ConditionalOnProperty(value = "spring.sleuth.mongodb.enabled", matchIfMissing = true)
@ConditionalOnClass(MongoClientSettings.Builder.class)
class TraceMongoDbAutoConfiguration {
@Bean
// for tests
@ConditionalOnMissingBean(TraceMongoClientSettingsBuilderCustomizer.class)
MongoClientSettingsBuilderCustomizer traceMongoClientSettingsBuilderCustomizer(
Tracing tracing) {
return new TraceMongoClientSettingsBuilderCustomizer(tracing);
}
}
class TraceMongoClientSettingsBuilderCustomizer
implements MongoClientSettingsBuilderCustomizer {
private final Tracing tracing;
TraceMongoClientSettingsBuilderCustomizer(Tracing tracing) {
this.tracing = tracing;
}
@Override
public void customize(MongoClientSettings.Builder clientSettingsBuilder) {
clientSettingsBuilder.addCommandListener(
MongoDBTracing.create(this.tracing).commandListener());
}
}

View File

@@ -66,6 +66,18 @@
"description": "Enable DefaultKafkaHeaderMapper tracing for Kafka.",
"defaultValue": true
},
{
"name": "spring.sleuth.quartz.enabled",
"type": "java.lang.Boolean",
"description": "Enable tracing for Quartz.",
"defaultValue": true
},
{
"name": "spring.sleuth.mongodb.enabled",
"type": "java.lang.Boolean",
"description": "Enable tracing for MongoDb.",
"defaultValue": true
},
{
"name": "spring.sleuth.rpc.enabled",
"type": "java.lang.Boolean",

View File

@@ -24,7 +24,8 @@ org.springframework.cloud.sleuth.instrument.messaging.TraceSpringMessagingAutoCo
org.springframework.cloud.sleuth.instrument.messaging.TraceWebSocketAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.opentracing.OpentracingAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.redis.TraceRedisAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.quartz.TraceQuartzAutoConfiguration
org.springframework.cloud.sleuth.instrument.quartz.TraceQuartzAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.mongodb.TraceMongoDbAutoConfiguration
# Environment Post Processor
org.springframework.boot.env.EnvironmentPostProcessor=\

View File

@@ -16,7 +16,14 @@
package org.springframework.cloud.sleuth;
import com.mongodb.client.MongoClient;
import org.mockito.BDDMockito;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -26,6 +33,22 @@ import org.springframework.context.annotation.Import;
@Configuration
class SleuthTestAutoConfiguration {
@Configuration
static class TestMongoConfiguration {
@Bean
@ConditionalOnProperty(value = "test.mongo.mock.enabled", matchIfMissing = true)
MongoClient mongoClient() {
return BDDMockito.mock(MongoClient.class);
}
@Bean(name = "mongoHealthIndicator")
HealthIndicator mongoHealthIndicator() {
return () -> Health.up().build();
}
}
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
static class ReactiveConfiguration {

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2013-2020 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.sleuth.instrument.mongodb;
import brave.Tracing;
import brave.handler.MutableSpan;
import brave.test.TestSpanHandler;
import com.mongodb.MongoClientSettings;
import com.mongodb.event.CommandListener;
import com.mongodb.event.CommandStartedEvent;
import com.mongodb.event.CommandSucceededEvent;
import org.bson.BsonDocument;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.BDDAssertions.then;
@SpringBootTest(properties = "test.mongo.mock.enabled=false")
class TraceMongoDbAutoConfigurationTests {
@Test
void should_record_a_span_when_working_with_mongodb_commands(
@Autowired TestSpanHandler handler) {
then(handler.spans()).isNotEmpty();
MutableSpan span = handler.get(0);
then(span.traceId()).isNotEmpty();
then(span.tags()).containsKey("mongodb.command");
then(span.remoteServiceName()).contains("mongodb");
}
@Configuration
@EnableAutoConfiguration
static class TestTraceMongoDbAutoConfiguration {
@Bean
TestSpanHandler testSpanHandler() {
return new TestSpanHandler();
}
@Bean
TraceMongoClientSettingsBuilderCustomizer testMongoClientSettingsBuilderCustomizer(
Tracing tracing) {
return new TestMongoClientSettingsBuilderCustomizer(tracing);
}
}
}
class TestMongoClientSettingsBuilderCustomizer
extends TraceMongoClientSettingsBuilderCustomizer {
TestMongoClientSettingsBuilderCustomizer(Tracing tracing) {
super(tracing);
}
@Override
public void customize(MongoClientSettings.Builder clientSettingsBuilder) {
super.customize(clientSettingsBuilder);
CommandListener listener = clientSettingsBuilder.build().getCommandListeners()
.get(0);
listener.commandStarted(new CommandStartedEvent(0, null, "", "",
BDDMockito.mock(BsonDocument.class)));
listener.commandSucceeded(new CommandSucceededEvent(1, null, "",
BDDMockito.mock(BsonDocument.class), 100));
}
}