Skip to content

Commit 7d0a718

Browse files
committed
Allow configuration of CassandraObservationConvention.
Closes #1490
1 parent 8c7c308 commit 7d0a718

File tree

11 files changed

+169
-72
lines changed

11 files changed

+169
-72
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/CassandraObservation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* @author Greg Turnquist
2828
* @since 4.0
2929
*/
30-
enum CassandraObservation implements ObservationDocumentation {
30+
public enum CassandraObservation implements ObservationDocumentation {
3131

3232
/**
3333
* Create an {@link io.micrometer.observation.Observation} for Cassandra-based queries.

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/CqlSessionObservationInterceptor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ final class CqlSessionObservationInterceptor implements MethodInterceptor {
5050

5151
private final ObservationRegistry observationRegistry;
5252

53-
private final CassandraObservationConvention observationConvention = new DefaultCassandraObservationConvention();
53+
private final CassandraObservationConvention convention;
5454

5555
CqlSessionObservationInterceptor(CqlSession delegate, String remoteServiceName,
56-
ObservationRegistry observationRegistry) {
56+
CassandraObservationConvention convention, ObservationRegistry observationRegistry) {
5757

5858
this.delegate = delegate;
5959
this.remoteServiceName = remoteServiceName;
60+
this.convention = convention;
6061
this.observationRegistry = observationRegistry;
6162
}
6263

@@ -140,7 +141,7 @@ private static Statement<?> createStatement(Object[] args) {
140141
return SimpleStatement.newInstance((String) args[0]);
141142
}
142143

143-
if (args[0]instanceof String query && args.length == 2) {
144+
if (args[0] instanceof String query && args.length == 2) {
144145
return args[1] instanceof Map //
145146
? SimpleStatement.newInstance(query, (Map) args[1]) //
146147
: SimpleStatement.newInstance(query, (Object[]) args[1]);
@@ -179,7 +180,7 @@ private Observation startObservation(Statement<?> statement, boolean prepare, St
179180
delegate.getContext().getSessionName(),
180181
delegate.getKeyspace().map(CqlIdentifier::asInternal).orElse("system")),
181182
observationRegistry)
182-
.observationConvention(observationConvention);
183+
.observationConvention(convention);
183184

184185
if (currentObservation != null) {
185186
observation.parentObservation(currentObservation);

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/DefaultCassandraObservationConvention.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
* @author Mark Paluch
4242
* @since 4.0
4343
*/
44-
class DefaultCassandraObservationConvention implements CassandraObservationConvention {
44+
public class DefaultCassandraObservationConvention implements CassandraObservationConvention {
45+
46+
public static final CassandraObservationConvention INSTANCE = new DefaultCassandraObservationConvention();
4547

4648
@Override
4749
public KeyValues getLowCardinalityKeyValues(CassandraObservationContext context) {
@@ -104,10 +106,10 @@ public KeyValues getHighCardinalityKeyValues(CassandraObservationContext context
104106
}
105107

106108
@Nullable
107-
private InetSocketAddress tryGetSocketAddress(EndPoint endPoint) {
109+
protected InetSocketAddress tryGetSocketAddress(EndPoint endPoint) {
108110

109111
try {
110-
if (endPoint.resolve()instanceof InetSocketAddress inet) {
112+
if (endPoint.resolve() instanceof InetSocketAddress inet) {
111113
return inet;
112114
}
113115

@@ -121,13 +123,28 @@ public String getContextualName(CassandraObservationContext context) {
121123
return (context.isPrepare() ? "PREPARE: " : "") + getOperationName(getCql(context.getStatement()), "");
122124
}
123125

126+
/**
127+
* Tries to parse the CQL query or provides the default name.
128+
*
129+
* @param defaultName if there's no query
130+
* @return span name
131+
*/
132+
public String getOperationName(String cql, String defaultName) {
133+
134+
if (StringUtils.hasText(cql) && cql.indexOf(' ') > -1) {
135+
return cql.substring(0, cql.indexOf(' '));
136+
}
137+
138+
return defaultName;
139+
}
140+
124141
/**
125142
* Extract the CQL query from the delegate {@link Statement}.
126143
*
127144
* @return string-based CQL of the delegate
128145
* @param statement
129146
*/
130-
private static String getCql(Statement<?> statement) {
147+
protected static String getCql(Statement<?> statement) {
131148

132149
String query = "";
133150

@@ -155,7 +172,7 @@ private static String getCql(Statement<?> statement) {
155172
* @param statement
156173
* @return query
157174
*/
158-
private static String getQuery(Statement<?> statement) {
175+
protected static String getQuery(Statement<?> statement) {
159176

160177
if (statement instanceof SimpleStatement) {
161178
return ((SimpleStatement) statement).getQuery();
@@ -167,19 +184,4 @@ private static String getQuery(Statement<?> statement) {
167184

168185
return "";
169186
}
170-
171-
/**
172-
* Tries to parse the CQL query or provides the default name.
173-
*
174-
* @param defaultName if there's no query
175-
* @return span name
176-
*/
177-
public String getOperationName(String cql, String defaultName) {
178-
179-
if (StringUtils.hasText(cql) && cql.indexOf(' ') > -1) {
180-
return cql.substring(0, cql.indexOf(' '));
181-
}
182-
183-
return defaultName;
184-
}
185187
}

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/ObservableCqlSessionFactory.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
import io.micrometer.observation.ObservationRegistry;
1919

20-
import org.springframework.aop.RawTargetAccess;
21-
import org.springframework.aop.TargetSource;
2220
import org.springframework.aop.framework.ProxyFactory;
2321
import org.springframework.data.cassandra.observability.CqlSessionObservationInterceptor.ObservationDecoratedProxy;
2422
import org.springframework.util.Assert;
@@ -58,20 +56,36 @@ public static CqlSession wrap(CqlSession session, ObservationRegistry observatio
5856
* @return
5957
*/
6058
public static CqlSession wrap(CqlSession session, String remoteServiceName, ObservationRegistry observationRegistry) {
59+
return wrap(session, remoteServiceName, DefaultCassandraObservationConvention.INSTANCE, observationRegistry);
60+
}
61+
62+
/**
63+
* Wrap the {@link CqlSession} with a {@link CqlSessionObservationInterceptor}.
64+
*
65+
* @param session must not be {@literal null}.
66+
* @param remoteServiceName must not be {@literal null}.
67+
* @param convention the observation convention.
68+
* @param observationRegistry must not be {@literal null}.
69+
* @return
70+
* @since 4.3.4
71+
*/
72+
public static CqlSession wrap(CqlSession session, String remoteServiceName, CassandraObservationConvention convention,
73+
ObservationRegistry observationRegistry) {
6174

6275
Assert.notNull(session, "CqlSession must not be null");
63-
Assert.notNull(remoteServiceName, "CqlSessionObservationConvention must not be null");
76+
Assert.notNull(remoteServiceName, "Remote service name must not be null");
77+
Assert.notNull(convention, "CassandraObservationConvention must not be null");
6478
Assert.notNull(observationRegistry, "ObservationRegistry must not be null");
6579

6680
ProxyFactory proxyFactory = new ProxyFactory();
6781

6882
proxyFactory.setTarget(session);
69-
proxyFactory.addAdvice(new CqlSessionObservationInterceptor(session, remoteServiceName, observationRegistry));
83+
proxyFactory
84+
.addAdvice(new CqlSessionObservationInterceptor(session, remoteServiceName, convention, observationRegistry));
7085
proxyFactory.addInterface(CqlSession.class);
7186
proxyFactory.addInterface(ObservationDecoratedProxy.class);
7287

7388
return (CqlSession) proxyFactory.getProxy();
7489
}
7590

76-
7791
}

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/ObservableCqlSessionFactoryBean.java

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class ObservableCqlSessionFactoryBean extends AbstractFactoryBean<CqlSess
4343

4444
private @Nullable String remoteServiceName;
4545

46+
private CassandraObservationConvention convention = DefaultCassandraObservationConvention.INSTANCE;
47+
4648
/**
4749
* Construct a new {@link ObservableCqlSessionFactoryBean}.
4850
*
@@ -58,16 +60,39 @@ public ObservableCqlSessionFactoryBean(CqlSessionBuilder cqlSessionBuilder, Obse
5860
this.observationRegistry = observationRegistry;
5961
}
6062

63+
@Nullable
64+
public String getRemoteServiceName() {
65+
return remoteServiceName;
66+
}
67+
68+
/**
69+
* Set the remote service name.
70+
*
71+
* @param remoteServiceName
72+
*/
73+
public void setRemoteServiceName(@Nullable String remoteServiceName) {
74+
this.remoteServiceName = remoteServiceName;
75+
}
76+
77+
/**
78+
* Set the observation convention.
79+
*
80+
* @param convention
81+
* @since 4.3.4
82+
*/
83+
public void setConvention(CassandraObservationConvention convention) {
84+
this.convention = convention;
85+
}
86+
6187
@Override
6288
protected CqlSession createInstance() {
6389

6490
cqlSessionBuilder.addRequestTracker(ObservationRequestTracker.INSTANCE);
6591

66-
if (ObjectUtils.isEmpty(getRemoteServiceName())) {
67-
return ObservableCqlSessionFactory.wrap(cqlSessionBuilder.build(), observationRegistry);
68-
}
92+
String remoteServiceName = ObjectUtils.isEmpty(getRemoteServiceName()) ? "Cassandra" : getRemoteServiceName();
6993

70-
return ObservableCqlSessionFactory.wrap(cqlSessionBuilder.build(), getRemoteServiceName(), observationRegistry);
94+
return ObservableCqlSessionFactory.wrap(cqlSessionBuilder.build(), remoteServiceName, convention,
95+
observationRegistry);
7196
}
7297

7398
@Override
@@ -82,17 +107,4 @@ public Class<?> getObjectType() {
82107
return CqlSession.class;
83108
}
84109

85-
@Nullable
86-
public String getRemoteServiceName() {
87-
return remoteServiceName;
88-
}
89-
90-
/**
91-
* Set the remote service name.
92-
*
93-
* @param remoteServiceName
94-
*/
95-
public void setRemoteServiceName(@Nullable String remoteServiceName) {
96-
this.remoteServiceName = remoteServiceName;
97-
}
98110
}

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/ObservableReactiveSession.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ public class ObservableReactiveSession implements ReactiveSession {
5050

5151
private final ObservationRegistry observationRegistry;
5252

53-
private final CassandraObservationConvention convention = new DefaultCassandraObservationConvention();
53+
private final CassandraObservationConvention convention;
5454

5555
ObservableReactiveSession(ReactiveSession delegate, String remoteServiceName,
56-
ObservationRegistry observationRegistry) {
56+
CassandraObservationConvention convention, ObservationRegistry observationRegistry) {
5757
this.delegate = delegate;
5858
this.remoteServiceName = remoteServiceName;
59+
this.convention = convention;
5960
this.observationRegistry = observationRegistry;
6061
}
6162

@@ -67,19 +68,37 @@ public class ObservableReactiveSession implements ReactiveSession {
6768
* @return traced representation of a {@link ReactiveSession}.
6869
*/
6970
public static ReactiveSession create(ReactiveSession session, ObservationRegistry observationRegistry) {
70-
return new ObservableReactiveSession(session, "Cassandra", observationRegistry);
71+
return new ObservableReactiveSession(session, "Cassandra", DefaultCassandraObservationConvention.INSTANCE,
72+
observationRegistry);
7173
}
7274

7375
/**
7476
* Factory method for creation of a {@link ObservableReactiveSession}.
7577
*
7678
* @param session reactive session.
79+
* @param remoteServiceName the remote service name.
7780
* @param observationRegistry observation registry.
7881
* @return traced representation of a {@link ReactiveSession}.
7982
*/
8083
public static ReactiveSession create(ReactiveSession session, String remoteServiceName,
8184
ObservationRegistry observationRegistry) {
82-
return new ObservableReactiveSession(session, remoteServiceName, observationRegistry);
85+
return new ObservableReactiveSession(session, remoteServiceName, DefaultCassandraObservationConvention.INSTANCE,
86+
observationRegistry);
87+
}
88+
89+
/**
90+
* Factory method for creation of a {@link ObservableReactiveSession}.
91+
*
92+
* @param session reactive session.
93+
* @param remoteServiceName the remote service name.
94+
* @param convention the observation convention.
95+
* @param observationRegistry observation registry.
96+
* @return traced representation of a {@link ReactiveSession}.
97+
* @since 4.3.4
98+
*/
99+
public static ReactiveSession create(ReactiveSession session, String remoteServiceName,
100+
CassandraObservationConvention convention, ObservationRegistry observationRegistry) {
101+
return new ObservableReactiveSession(session, remoteServiceName, convention, observationRegistry);
83102
}
84103

85104
@Override

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/observability/ObservableReactiveSessionFactory.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,27 @@ public static ReactiveSession wrap(ReactiveSession session, ObservationRegistry
5555
*/
5656
public static ReactiveSession wrap(ReactiveSession session, String remoteServiceName,
5757
ObservationRegistry observationRegistry) {
58+
return wrap(session, remoteServiceName, DefaultCassandraObservationConvention.INSTANCE, observationRegistry);
59+
}
60+
61+
/**
62+
* Wrap the {@link CqlSession} with a {@link CqlSessionObservationInterceptor}.
63+
*
64+
* @param session must not be {@literal null}.
65+
* @param remoteServiceName must not be {@literal null}.
66+
* @param convention the observation convention.
67+
* @param observationRegistry must not be {@literal null}.
68+
* @return
69+
* @since 4.3.4
70+
*/
71+
public static ReactiveSession wrap(ReactiveSession session, String remoteServiceName,
72+
CassandraObservationConvention convention, ObservationRegistry observationRegistry) {
5873

5974
Assert.notNull(session, "CqlSession must not be null");
60-
Assert.notNull(remoteServiceName, "CqlSessionObservationConvention must not be null");
75+
Assert.notNull(remoteServiceName, "Remote service name must not be null");
76+
Assert.notNull(convention, "CassandraObservationConvention must not be null");
6177
Assert.notNull(observationRegistry, "ObservationRegistry must not be null");
6278

63-
return ObservableReactiveSession.create(session, remoteServiceName, observationRegistry);
79+
return ObservableReactiveSession.create(session, remoteServiceName, convention, observationRegistry);
6480
}
6581
}

0 commit comments

Comments
 (0)