From 8620d399f4c16be6ec3bdc7293ce229bd8abb135 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 3 Nov 2021 11:41:00 +0100 Subject: [PATCH] Added opt in for SocketAddress Mongo spans; fixes gh-2050 --- docs/src/main/asciidoc/_configprops.adoc | 1 + docs/src/main/asciidoc/integrations.adoc | 10 ++++ .../brave/BraveBridgeConfiguration.java | 5 +- .../TraceMongoDbAutoConfiguration.java | 28 +++++++++-- ...itional-spring-configuration-metadata.json | 6 +++ .../sleuth/brave/bridge/BraveTracer.java | 1 + ...eMongoClientSettingsBuilderCustomizer.java | 11 +++-- .../TraceMongoClusterIdSpanCustomizer.java | 37 ++++++++++++++ .../mongodb/TraceMongoCommandListener.java | 30 +++--------- ...TraceMongoSocketAddressSpanCustomizer.java | 48 +++++++++++++++++++ .../mongodb/TraceMongoSpanCustomizer.java | 38 +++++++++++++++ 11 files changed, 182 insertions(+), 33 deletions(-) create mode 100644 spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClusterIdSpanCustomizer.java create mode 100644 spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSocketAddressSpanCustomizer.java create mode 100644 spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSpanCustomizer.java diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 6df436b44..bb68195e0 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -59,6 +59,7 @@ |spring.sleuth.messaging.rabbit.enabled | `true` | Enable tracing of RabbitMQ. |spring.sleuth.messaging.rabbit.remote-service-name | `rabbitmq` | Rabbit remote service name. |spring.sleuth.mongodb.enabled | `true` | Enable tracing for MongoDb. +|spring.sleuth.mongodb.socket-address-span-customizer.enabled | `false` | Enable setting of SocketAddress information on the Mongo span. |spring.sleuth.opentracing.enabled | `true` | Enables OpenTracing support. |spring.sleuth.propagation.type | | Tracing context propagation types. |spring.sleuth.quartz.enabled | `true` | Enable tracing for Quartz. diff --git a/docs/src/main/asciidoc/integrations.adoc b/docs/src/main/asciidoc/integrations.adoc index 392cfc923..9f4515ff7 100644 --- a/docs/src/main/asciidoc/integrations.adoc +++ b/docs/src/main/asciidoc/integrations.adoc @@ -752,6 +752,16 @@ and set `spring.sleuth.jdbc.datasource-proxy.query.enable-logging` to `true` to In order to disable this instrumentation set `spring.sleuth.jdbc.enabled` to `false`. +[[sleuth-mongodb-integration]] +== MongoDB + +This feature is available for all tracer implementations. + +We're adding command listeners that wrap all commands in a span. +If you want to have additional socket address related tags on the span set the `spring.sleuth.mongodb.socket-address-span-customizer.enabled` to `true`. + +In order to disable this instrumentation set ``spring.sleuth.mongodb.enabled`` to `false`. + [[sleuth-session-integration]] == Spring Session diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/brave/BraveBridgeConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/brave/BraveBridgeConfiguration.java index cc446473e..2410ce647 100644 --- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/brave/BraveBridgeConfiguration.java +++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/brave/BraveBridgeConfiguration.java @@ -59,8 +59,9 @@ import org.springframework.context.annotation.Configuration; class BraveBridgeConfiguration { @Bean - org.springframework.cloud.sleuth.Tracer braveTracer(brave.Tracer tracer) { - return new BraveTracer(tracer, new BraveBaggageManager()); + org.springframework.cloud.sleuth.Tracer braveTracer(brave.Tracer tracer, + org.springframework.cloud.sleuth.CurrentTraceContext braveCurrentTraceContext) { + return new BraveTracer(tracer, braveCurrentTraceContext, new BraveBaggageManager()); } @Bean diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/mongodb/TraceMongoDbAutoConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/mongodb/TraceMongoDbAutoConfiguration.java index 33bbd2d64..c5b25bcb4 100644 --- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/mongodb/TraceMongoDbAutoConfiguration.java +++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/mongodb/TraceMongoDbAutoConfiguration.java @@ -16,8 +16,12 @@ package org.springframework.cloud.sleuth.autoconfig.instrument.mongodb; +import java.util.ArrayList; +import java.util.List; + import com.mongodb.MongoClientSettings; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; @@ -27,11 +31,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; -import org.springframework.cloud.sleuth.CurrentTraceContext; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration; import org.springframework.cloud.sleuth.instrument.mongodb.TraceAllTypesMongoClientSettingsBuilderCustomizer; import org.springframework.cloud.sleuth.instrument.mongodb.TraceMongoClientSettingsBuilderCustomizer; +import org.springframework.cloud.sleuth.instrument.mongodb.TraceMongoClusterIdSpanCustomizer; +import org.springframework.cloud.sleuth.instrument.mongodb.TraceMongoSocketAddressSpanCustomizer; +import org.springframework.cloud.sleuth.instrument.mongodb.TraceMongoSpanCustomizer; import org.springframework.cloud.sleuth.instrument.mongodb.TraceReactiveMongoClientSettingsBuilderCustomizer; import org.springframework.cloud.sleuth.instrument.mongodb.TraceSynchronousMongoClientSettingsBuilderCustomizer; import org.springframework.context.annotation.Bean; @@ -57,8 +63,8 @@ public class TraceMongoDbAutoConfiguration { @ConditionalOnMissingBean @Conditional(EitherSynchronousOrReactiveContextProviderPresent.class) TraceMongoClientSettingsBuilderCustomizer traceMongoClientSettingsBuilderCustomizer(Tracer tracer, - CurrentTraceContext currentTraceContext) { - return new TraceMongoClientSettingsBuilderCustomizer(tracer, currentTraceContext); + ObjectProvider> customizers) { + return new TraceMongoClientSettingsBuilderCustomizer(tracer, customizers.getIfAvailable(ArrayList::new)); } @Bean @@ -86,6 +92,22 @@ public class TraceMongoDbAutoConfiguration { return new TraceAllTypesMongoClientSettingsBuilderCustomizer(tracer); } + @Configuration(proxyBeanMethods = false) + static class MongoCustomizersConfiguration { + + @Bean + TraceMongoSpanCustomizer traceMongoClusterIdSpanCustomizer() { + return new TraceMongoClusterIdSpanCustomizer(); + } + + @Bean + @ConditionalOnProperty("spring.sleuth.mongodb.socket-address-span-customizer.enabled") + TraceMongoSpanCustomizer traceMongoSocketAddressSpanCustomizer() { + return new TraceMongoSocketAddressSpanCustomizer(); + } + + } + static class EitherSynchronousOrReactiveContextProviderPresent extends AnyNestedCondition { EitherSynchronousOrReactiveContextProviderPresent() { diff --git a/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index f361ead6d..273edaa08 100644 --- a/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -112,6 +112,12 @@ "type": "java.lang.Boolean", "description": "Enable tracing for MongoDb.", "defaultValue": true + }, + { + "name": "spring.sleuth.mongodb.socket-address-span-customizer.enabled", + "type": "java.lang.Boolean", + "description": "Enable setting of SocketAddress information on the Mongo span.", + "defaultValue": false }, { "name": "spring.sleuth.rpc.enabled", diff --git a/spring-cloud-sleuth-brave/src/main/java/org/springframework/cloud/sleuth/brave/bridge/BraveTracer.java b/spring-cloud-sleuth-brave/src/main/java/org/springframework/cloud/sleuth/brave/bridge/BraveTracer.java index 9e93f382b..d0de994f8 100644 --- a/spring-cloud-sleuth-brave/src/main/java/org/springframework/cloud/sleuth/brave/bridge/BraveTracer.java +++ b/spring-cloud-sleuth-brave/src/main/java/org/springframework/cloud/sleuth/brave/bridge/BraveTracer.java @@ -43,6 +43,7 @@ public class BraveTracer implements Tracer { private final CurrentTraceContext currentTraceContext; + @Deprecated public BraveTracer(brave.Tracer tracer, BraveBaggageManager braveBaggageManager) { this.tracer = tracer; this.braveBaggageManager = braveBaggageManager; diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClientSettingsBuilderCustomizer.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClientSettingsBuilderCustomizer.java index f3c10b466..18b289bc8 100644 --- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClientSettingsBuilderCustomizer.java +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClientSettingsBuilderCustomizer.java @@ -16,10 +16,11 @@ package org.springframework.cloud.sleuth.instrument.mongodb; +import java.util.List; + import com.mongodb.MongoClientSettings; import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; -import org.springframework.cloud.sleuth.CurrentTraceContext; import org.springframework.cloud.sleuth.Tracer; /** @@ -32,16 +33,16 @@ public class TraceMongoClientSettingsBuilderCustomizer implements MongoClientSet private final Tracer tracer; - private final CurrentTraceContext currentTraceContext; + private final List customizers; - public TraceMongoClientSettingsBuilderCustomizer(Tracer tracer, CurrentTraceContext currentTraceContext) { + public TraceMongoClientSettingsBuilderCustomizer(Tracer tracer, List customizers) { this.tracer = tracer; - this.currentTraceContext = currentTraceContext; + this.customizers = customizers; } @Override public void customize(MongoClientSettings.Builder clientSettingsBuilder) { - clientSettingsBuilder.addCommandListener(new TraceMongoCommandListener(this.tracer, this.currentTraceContext)); + clientSettingsBuilder.addCommandListener(new TraceMongoCommandListener(this.tracer, this.customizers)); } } diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClusterIdSpanCustomizer.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClusterIdSpanCustomizer.java new file mode 100644 index 000000000..f4d6e6fb9 --- /dev/null +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoClusterIdSpanCustomizer.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2021 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 com.mongodb.connection.ConnectionDescription; +import com.mongodb.connection.ConnectionId; +import com.mongodb.event.CommandStartedEvent; + +import org.springframework.cloud.sleuth.Span; + +public class TraceMongoClusterIdSpanCustomizer implements TraceMongoSpanCustomizer { + + public void customizeCommandStartSpan(CommandStartedEvent event, Span.Builder spanBuilder) { + ConnectionDescription connectionDescription = event.getConnectionDescription(); + if (connectionDescription != null) { + ConnectionId connectionId = connectionDescription.getConnectionId(); + if (connectionId != null) { + spanBuilder.tag("mongodb.cluster_id", connectionId.getServerId().getClusterId().getValue()); + } + } + } + +} diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoCommandListener.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoCommandListener.java index 089c0cb27..3a9c47574 100644 --- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoCommandListener.java +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoCommandListener.java @@ -16,15 +16,12 @@ package org.springframework.cloud.sleuth.instrument.mongodb; -import java.net.InetSocketAddress; import java.util.Arrays; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; -import com.mongodb.MongoSocketException; import com.mongodb.RequestContext; -import com.mongodb.connection.ConnectionDescription; -import com.mongodb.connection.ConnectionId; import com.mongodb.event.CommandFailedEvent; import com.mongodb.event.CommandListener; import com.mongodb.event.CommandStartedEvent; @@ -60,9 +57,12 @@ final class TraceMongoCommandListener implements CommandListener { private final CurrentTraceContext currentTraceContext; - TraceMongoCommandListener(Tracer tracer, CurrentTraceContext currentTraceContext) { + private final List customizers; + + TraceMongoCommandListener(Tracer tracer, List customizers) { this.tracer = tracer; - this.currentTraceContext = currentTraceContext; + this.currentTraceContext = tracer.currentTraceContext(); + this.customizers = customizers; } @Override @@ -100,23 +100,7 @@ final class TraceMongoCommandListener implements CommandListener { childSpanBuilder.tag("mongodb.collection", collectionName); } - ConnectionDescription connectionDescription = event.getConnectionDescription(); - if (connectionDescription != null) { - ConnectionId connectionId = connectionDescription.getConnectionId(); - if (connectionId != null) { - childSpanBuilder.tag("mongodb.cluster_id", connectionId.getServerId().getClusterId().getValue()); - } - - try { - InetSocketAddress socketAddress = connectionDescription.getServerAddress().getSocketAddress(); - childSpanBuilder.remoteIpAndPort(socketAddress.getAddress().getHostAddress(), socketAddress.getPort()); - } - catch (MongoSocketException ignored) { - if (log.isDebugEnabled()) { - log.debug("Ignored exception when setting remote ip and port", ignored); - } - } - } + this.customizers.forEach(customizer -> customizer.customizeCommandStartSpan(event, childSpanBuilder)); Span childSpan = childSpanBuilder.start(); // TODO: What about retries? We might override the parent span diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSocketAddressSpanCustomizer.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSocketAddressSpanCustomizer.java new file mode 100644 index 000000000..f8bfb77fb --- /dev/null +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSocketAddressSpanCustomizer.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2021 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 java.net.InetSocketAddress; + +import com.mongodb.MongoSocketException; +import com.mongodb.connection.ConnectionDescription; +import com.mongodb.event.CommandStartedEvent; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.sleuth.Span; + +public class TraceMongoSocketAddressSpanCustomizer implements TraceMongoSpanCustomizer { + + private static final Log log = LogFactory.getLog(TraceMongoClusterIdSpanCustomizer.class); + + public void customizeCommandStartSpan(CommandStartedEvent event, Span.Builder spanBuilder) { + ConnectionDescription connectionDescription = event.getConnectionDescription(); + if (connectionDescription != null) { + try { + InetSocketAddress socketAddress = connectionDescription.getServerAddress().getSocketAddress(); + spanBuilder.remoteIpAndPort(socketAddress.getAddress().getHostAddress(), socketAddress.getPort()); + } + catch (MongoSocketException ignored) { + if (log.isDebugEnabled()) { + log.debug("Ignored exception when setting remote ip and port", ignored); + } + } + } + } + +} diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSpanCustomizer.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSpanCustomizer.java new file mode 100644 index 000000000..9bde576d0 --- /dev/null +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/mongodb/TraceMongoSpanCustomizer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2021 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 com.mongodb.event.CommandStartedEvent; + +import org.springframework.cloud.sleuth.Span; + +/** + * Customizer for the child span wrapping the call to Mongo. + * + * @author Marcin Grzejszczak + * @since 3.1.0 + */ +public interface TraceMongoSpanCustomizer { + + /** + * Customizes the Span created from the {@link CommandStartedEvent}. + * @param commandStartedEvent event from Mongo + * @param spanBuilder span builder to customize + */ + void customizeCommandStartSpan(CommandStartedEvent commandStartedEvent, Span.Builder spanBuilder); + +}