1
1
/*
2
- * Copyright 2021-2022 the original author or authors.
2
+ * Copyright 2021-2023 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
25
25
26
26
import org .springframework .amqp .core .Message ;
27
27
import org .springframework .amqp .core .MessageListener ;
28
- import org .springframework .amqp .rabbit .listener .MessageListenerContainer ;
28
+ import org .springframework .amqp .rabbit .listener .MicrometerHolder ;
29
+ import org .springframework .amqp .rabbit .listener .ObservableListenerContainer ;
29
30
import org .springframework .amqp .rabbit .listener .api .ChannelAwareMessageListener ;
31
+ import org .springframework .amqp .rabbit .support .RabbitExceptionTranslator ;
30
32
import org .springframework .aop .framework .ProxyFactory ;
31
33
import org .springframework .aop .support .DefaultPointcutAdvisor ;
32
- import org .springframework .beans .factory .BeanNameAware ;
33
34
import org .springframework .core .log .LogAccessor ;
34
35
import org .springframework .lang .Nullable ;
36
+ import org .springframework .rabbit .stream .micrometer .RabbitStreamListenerObservation ;
37
+ import org .springframework .rabbit .stream .micrometer .RabbitStreamListenerObservation .DefaultRabbitStreamListenerObservationConvention ;
38
+ import org .springframework .rabbit .stream .micrometer .RabbitStreamListenerObservationConvention ;
39
+ import org .springframework .rabbit .stream .micrometer .RabbitStreamMessageReceiverContext ;
35
40
import org .springframework .rabbit .stream .support .StreamMessageProperties ;
36
41
import org .springframework .rabbit .stream .support .converter .DefaultStreamMessageConverter ;
37
42
import org .springframework .rabbit .stream .support .converter .StreamMessageConverter ;
41
46
import com .rabbitmq .stream .Consumer ;
42
47
import com .rabbitmq .stream .ConsumerBuilder ;
43
48
import com .rabbitmq .stream .Environment ;
49
+ import io .micrometer .observation .Observation ;
50
+ import io .micrometer .observation .ObservationRegistry ;
44
51
45
52
/**
46
53
* A listener container for RabbitMQ Streams.
49
56
* @since 2.4
50
57
*
51
58
*/
52
- public class StreamListenerContainer implements MessageListenerContainer , BeanNameAware {
59
+ public class StreamListenerContainer extends ObservableListenerContainer {
53
60
54
61
protected LogAccessor logger = new LogAccessor (LogFactory .getLog (getClass ())); // NOSONAR
55
62
@@ -67,10 +74,6 @@ public class StreamListenerContainer implements MessageListenerContainer, BeanNa
67
74
68
75
private int concurrency = 1 ;
69
76
70
- private String listenerId ;
71
-
72
- private String beanName ;
73
-
74
77
private boolean autoStartup = true ;
75
78
76
79
private MessageListener messageListener ;
@@ -79,6 +82,11 @@ public class StreamListenerContainer implements MessageListenerContainer, BeanNa
79
82
80
83
private Advice [] adviceChain ;
81
84
85
+ private String streamName ;
86
+
87
+ @ Nullable
88
+ private RabbitStreamListenerObservationConvention observationConvention ;
89
+
82
90
/**
83
91
* Construct an instance using the provided environment.
84
92
* @param environment the environment.
@@ -108,6 +116,7 @@ public synchronized void setQueueNames(String... queueNames) {
108
116
Assert .isTrue (queueNames != null && queueNames .length == 1 , "Only one stream is supported" );
109
117
this .builder .stream (queueNames [0 ]);
110
118
this .simpleStream = true ;
119
+ this .streamName = queueNames [0 ];
111
120
}
112
121
113
122
/**
@@ -139,6 +148,7 @@ public synchronized void superStream(String streamName, String name, int consume
139
148
.singleActiveConsumer ()
140
149
.name (name );
141
150
this .superStream = true ;
151
+ this .streamName = streamName ;
142
152
}
143
153
144
154
/**
@@ -171,34 +181,6 @@ public synchronized void setConsumerCustomizer(ConsumerCustomizer consumerCustom
171
181
this .consumerCustomizer = consumerCustomizer ;
172
182
}
173
183
174
- /**
175
- * The 'id' attribute of the listener.
176
- * @return the id (or the container bean name if no id set).
177
- */
178
- @ Nullable
179
- public String getListenerId () {
180
- return this .listenerId != null ? this .listenerId : this .beanName ;
181
- }
182
-
183
- @ Override
184
- public void setListenerId (String listenerId ) {
185
- this .listenerId = listenerId ;
186
- }
187
-
188
- /**
189
- * Return the bean name.
190
- * @return the bean name.
191
- */
192
- @ Nullable
193
- public String getBeanName () {
194
- return this .beanName ;
195
- }
196
-
197
- @ Override
198
- public void setBeanName (String beanName ) {
199
- this .beanName = beanName ;
200
- }
201
-
202
184
@ Override
203
185
public void setAutoStartup (boolean autoStart ) {
204
186
this .autoStartup = autoStart ;
@@ -226,6 +208,22 @@ public Object getMessageListener() {
226
208
return this .messageListener ;
227
209
}
228
210
211
+ /**
212
+ * Set a RabbitStreamListenerObservationConvention; used to add additional key/values
213
+ * to observations when using a {@link StreamMessageListener}.
214
+ * @param observationConvention the convention.
215
+ * @since 3.0.5
216
+ */
217
+ public void setObservationConvention (RabbitStreamListenerObservationConvention observationConvention ) {
218
+ this .observationConvention = observationConvention ;
219
+ }
220
+
221
+ @ Override
222
+ public void afterPropertiesSet () {
223
+ checkMicrometer ();
224
+ checkObservation ();
225
+ }
226
+
229
227
@ Override
230
228
public synchronized boolean isRunning () {
231
229
return this .consumers .size () > 0 ;
@@ -263,21 +261,72 @@ public synchronized void stop() {
263
261
public void setupMessageListener (MessageListener messageListener ) {
264
262
adviseIfNeeded (messageListener );
265
263
this .builder .messageHandler ((context , message ) -> {
264
+ ObservationRegistry registry = getObservationRegistry ();
265
+ Object sample = null ;
266
+ MicrometerHolder micrometerHolder = getMicrometerHolder ();
267
+ if (micrometerHolder != null ) {
268
+ sample = micrometerHolder .start ();
269
+ }
270
+ Observation observation =
271
+ RabbitStreamListenerObservation .STREAM_LISTENER_OBSERVATION .observation (this .observationConvention ,
272
+ DefaultRabbitStreamListenerObservationConvention .INSTANCE ,
273
+ () -> new RabbitStreamMessageReceiverContext (message , getListenerId (), this .streamName ),
274
+ registry );
275
+ Object finalSample = sample ;
266
276
if (this .streamListener != null ) {
267
- this .streamListener .onStreamMessage (message , context );
277
+ observation .observe (() -> {
278
+ try {
279
+ this .streamListener .onStreamMessage (message , context );
280
+ if (finalSample != null ) {
281
+ micrometerHolder .success (finalSample , this .streamName );
282
+ }
283
+ }
284
+ catch (RuntimeException rtex ) {
285
+ if (finalSample != null ) {
286
+ micrometerHolder .failure (finalSample , this .streamName , rtex .getClass ().getSimpleName ());
287
+ }
288
+ throw rtex ;
289
+ }
290
+ catch (Exception ex ) {
291
+ if (finalSample != null ) {
292
+ micrometerHolder .failure (finalSample , this .streamName , ex .getClass ().getSimpleName ());
293
+ }
294
+ throw RabbitExceptionTranslator .convertRabbitAccessException (ex );
295
+ }
296
+ });
268
297
}
269
298
else {
270
299
Message message2 = this .streamConverter .toMessage (message , new StreamMessageProperties (context ));
271
300
if (this .messageListener instanceof ChannelAwareMessageListener ) {
272
301
try {
273
- ((ChannelAwareMessageListener ) this .messageListener ).onMessage (message2 , null );
302
+ observation .observe (() -> {
303
+ try {
304
+ ((ChannelAwareMessageListener ) this .messageListener ).onMessage (message2 , null );
305
+ if (finalSample != null ) {
306
+ micrometerHolder .success (finalSample , this .streamName );
307
+ }
308
+ }
309
+ catch (RuntimeException rtex ) {
310
+ if (finalSample != null ) {
311
+ micrometerHolder .failure (finalSample , this .streamName ,
312
+ rtex .getClass ().getSimpleName ());
313
+ }
314
+ throw rtex ;
315
+ }
316
+ catch (Exception ex ) {
317
+ if (finalSample != null ) {
318
+ micrometerHolder .failure (finalSample , this .streamName , ex .getClass ().getSimpleName ());
319
+ }
320
+ throw RabbitExceptionTranslator .convertRabbitAccessException (ex );
321
+ }
322
+ });
274
323
}
275
324
catch (Exception ex ) { // NOSONAR
276
- this .logger .error (ex , "Listner threw an exception" );
325
+ this .logger .error (ex , "Listener threw an exception" );
277
326
}
278
327
}
279
328
else {
280
- this .messageListener .onMessage (message2 );
329
+ observation . observe (() -> this .messageListener .onMessage (message2 ) );
281
330
}
282
331
}
283
332
});
0 commit comments