Skip to content

Commit cff8758

Browse files
committed
Remove the static configuration of Micrometer's observation registry
Issue spring-projects#4222
1 parent 051e022 commit cff8758

File tree

12 files changed

+244
-54
lines changed

12 files changed

+244
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.core.configuration.annotation;
17+
18+
import io.micrometer.observation.ObservationRegistry;
19+
import org.apache.commons.logging.Log;
20+
import org.apache.commons.logging.LogFactory;
21+
22+
import org.springframework.batch.core.job.AbstractJob;
23+
import org.springframework.batch.core.step.AbstractStep;
24+
import org.springframework.beans.BeansException;
25+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
26+
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
27+
import org.springframework.beans.factory.config.BeanPostProcessor;
28+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
29+
30+
/**
31+
* Bean post processor that configures observable batch artifacts (jobs and steps) with
32+
* Micrometer's observation registry.
33+
*
34+
* @author Mahmoud Ben Hassine
35+
* @since 5.0
36+
*/
37+
public class BatchObservabilityBeanPostProcessor implements BeanFactoryPostProcessor, BeanPostProcessor {
38+
39+
private static final Log LOGGER = LogFactory.getLog(BatchObservabilityBeanPostProcessor.class);
40+
41+
private ConfigurableListableBeanFactory beanFactory;
42+
43+
@Override
44+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
45+
this.beanFactory = beanFactory;
46+
}
47+
48+
@Override
49+
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
50+
try {
51+
ObservationRegistry observationRegistry = this.beanFactory.getBean(ObservationRegistry.class);
52+
if (bean instanceof AbstractJob) {
53+
((AbstractJob) bean).setObservationRegistry(observationRegistry);
54+
}
55+
if (bean instanceof AbstractStep) {
56+
((AbstractStep) bean).setObservationRegistry(observationRegistry);
57+
}
58+
}
59+
catch (NoSuchBeanDefinitionException e) {
60+
LOGGER.info("No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP");
61+
}
62+
return bean;
63+
}
64+
65+
}

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@
151151
@Target(ElementType.TYPE)
152152
@Retention(RetentionPolicy.RUNTIME)
153153
@Documented
154-
@Import({ BatchRegistrar.class, ScopeConfiguration.class, AutomaticJobRegistrarBeanPostProcessor.class })
154+
@Import({ BatchRegistrar.class, ScopeConfiguration.class, AutomaticJobRegistrarBeanPostProcessor.class,
155+
BatchObservabilityBeanPostProcessor.class })
155156
public @interface EnableBatchProcessing {
156157

157158
/**

spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.micrometer.core.instrument.LongTaskTimer;
2525
import io.micrometer.core.instrument.Tag;
2626
import io.micrometer.observation.Observation;
27+
import io.micrometer.observation.ObservationRegistry;
2728
import org.apache.commons.logging.Log;
2829
import org.apache.commons.logging.LogFactory;
2930

@@ -87,6 +88,8 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
8788

8889
private StepHandler stepHandler;
8990

91+
private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
92+
9093
private BatchJobObservationConvention observationConvention = new DefaultBatchJobObservationConvention();
9194

9295
/**
@@ -289,7 +292,8 @@ public final void execute(JobExecution execution) {
289292
BatchMetrics.METRICS_PREFIX + activeJobMeterName + ".name", execution.getJobInstance().getJobName()));
290293
LongTaskTimer.Sample longTaskTimerSample = longTaskTimer.start();
291294
Observation observation = BatchMetrics
292-
.createObservation(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), new BatchJobContext(execution))
295+
.createObservation(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), new BatchJobContext(execution),
296+
this.observationRegistry)
293297
.contextualName(execution.getJobInstance().getJobName())
294298
.observationConvention(this.observationConvention).start();
295299
try (Observation.Scope scope = observation.openScope()) {
@@ -439,6 +443,10 @@ public void setObservationConvention(BatchJobObservationConvention observationCo
439443
this.observationConvention = observationConvention;
440444
}
441445

446+
public void setObservationRegistry(ObservationRegistry observationRegistry) {
447+
this.observationRegistry = observationRegistry;
448+
}
449+
442450
@Override
443451
public String toString() {
444452
return ClassUtils.getShortName(getClass()) + ": [name=" + name + "]";

spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2020 the original author or authors.
2+
* Copyright 2006-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,8 +22,10 @@
2222
import java.util.List;
2323
import java.util.Set;
2424

25+
import io.micrometer.observation.ObservationRegistry;
2526
import org.apache.commons.logging.Log;
2627
import org.apache.commons.logging.LogFactory;
28+
2729
import org.springframework.batch.core.Job;
2830
import org.springframework.batch.core.JobExecutionListener;
2931
import org.springframework.batch.core.JobParametersIncrementer;
@@ -99,6 +101,18 @@ public B repository(JobRepository jobRepository) {
99101
return result;
100102
}
101103

104+
/**
105+
* Sets the observation registry for the job.
106+
* @param observationRegistry the observation registry (optional)
107+
* @return this to enable fluent chaining
108+
*/
109+
public B observationRegistry(ObservationRegistry observationRegistry) {
110+
properties.observationRegistry = observationRegistry;
111+
@SuppressWarnings("unchecked")
112+
B result = (B) this;
113+
return result;
114+
}
115+
102116
/**
103117
* Registers objects using the annotation based listener configuration.
104118
* @param listener the object that has a method configured with listener annotation
@@ -170,6 +184,10 @@ protected void enhance(Job target) {
170184
if (jobParametersValidator != null) {
171185
job.setJobParametersValidator(jobParametersValidator);
172186
}
187+
ObservationRegistry observationRegistry = properties.getObservationRegistry();
188+
if (observationRegistry != null) {
189+
job.setObservationRegistry(observationRegistry);
190+
}
173191

174192
Boolean restartable = properties.getRestartable();
175193
if (restartable != null) {
@@ -193,6 +211,8 @@ public static class CommonJobProperties {
193211

194212
private JobRepository jobRepository;
195213

214+
private ObservationRegistry observationRegistry;
215+
196216
private JobParametersIncrementer jobParametersIncrementer;
197217

198218
private JobParametersValidator jobParametersValidator;
@@ -204,6 +224,7 @@ public CommonJobProperties(CommonJobProperties properties) {
204224
this.name = properties.name;
205225
this.restartable = properties.restartable;
206226
this.jobRepository = properties.jobRepository;
227+
this.observationRegistry = properties.observationRegistry;
207228
this.jobExecutionListeners = new LinkedHashSet<>(properties.jobExecutionListeners);
208229
this.jobParametersIncrementer = properties.jobParametersIncrementer;
209230
this.jobParametersValidator = properties.jobParametersValidator;
@@ -233,6 +254,14 @@ public void setJobRepository(JobRepository jobRepository) {
233254
this.jobRepository = jobRepository;
234255
}
235256

257+
public ObservationRegistry getObservationRegistry() {
258+
return observationRegistry;
259+
}
260+
261+
public void setObservationRegistry(ObservationRegistry observationRegistry) {
262+
this.observationRegistry = observationRegistry;
263+
}
264+
236265
public String getName() {
237266
return name;
238267
}

spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchMetrics.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,6 @@ public final class BatchMetrics {
5454

5555
public static final String STATUS_FAILURE = "FAILURE";
5656

57-
/**
58-
* Global {@link ObservationRegistry}. A {@link DefaultMeterObservationHandler} is
59-
* attached to create a {@link Timer} for every finished {@link Observation}.
60-
*/
61-
public static ObservationRegistry observationRegistry;
62-
63-
static {
64-
observationRegistry = ObservationRegistry.create();
65-
observationRegistry.observationConfig()
66-
.observationHandler(new DefaultMeterObservationHandler(Metrics.globalRegistry));
67-
}
68-
6957
private BatchMetrics() {
7058
}
7159

@@ -94,7 +82,8 @@ public static Timer createTimer(String name, String description, Tag... tags) {
9482
* @return a new observation instance
9583
* @since 5.0
9684
*/
97-
public static Observation createObservation(String name, BatchJobContext context) {
85+
public static Observation createObservation(String name, BatchJobContext context,
86+
ObservationRegistry observationRegistry) {
9887
return Observation.createNotStarted(name, context, observationRegistry);
9988
}
10089

@@ -110,7 +99,8 @@ public static Observation createObservation(String name, BatchJobContext context
11099
* @return a new observation instance
111100
* @since 5.0
112101
*/
113-
public static Observation createObservation(String name, BatchStepContext context) {
102+
public static Observation createObservation(String name, BatchStepContext context,
103+
ObservationRegistry observationRegistry) {
114104
return Observation.createNotStarted(name, context, observationRegistry);
115105
}
116106

spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.stream.Collectors;
2222

2323
import io.micrometer.observation.Observation;
24+
import io.micrometer.observation.ObservationRegistry;
2425
import org.apache.commons.logging.Log;
2526
import org.apache.commons.logging.LogFactory;
2627

@@ -75,6 +76,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
7576

7677
private JobRepository jobRepository;
7778

79+
private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
80+
7881
private BatchStepObservationConvention observationConvention = new DefaultBatchStepObservationConvention();
7982

8083
/**
@@ -203,7 +206,7 @@ public final void execute(StepExecution stepExecution)
203206
stepExecution.setStatus(BatchStatus.STARTED);
204207
Observation observation = BatchMetrics
205208
.createObservation(BatchStepObservation.BATCH_STEP_OBSERVATION.getName(),
206-
new BatchStepContext(stepExecution))
209+
new BatchStepContext(stepExecution), this.observationRegistry)
207210
.contextualName(stepExecution.getStepName()).observationConvention(this.observationConvention).start();
208211
getJobRepository().update(stepExecution);
209212

@@ -424,4 +427,8 @@ public void setObservationConvention(BatchStepObservationConvention observationC
424427
this.observationConvention = observationConvention;
425428
}
426429

430+
public void setObservationRegistry(ObservationRegistry observationRegistry) {
431+
this.observationRegistry = observationRegistry;
432+
}
433+
427434
}

spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@
1515
*/
1616
package org.springframework.batch.core.step.builder;
1717

18+
import java.lang.reflect.Method;
19+
import java.util.ArrayList;
20+
import java.util.HashSet;
21+
import java.util.List;
22+
import java.util.Set;
23+
24+
import io.micrometer.observation.ObservationRegistry;
1825
import org.apache.commons.logging.Log;
1926
import org.apache.commons.logging.LogFactory;
27+
2028
import org.springframework.batch.core.Step;
2129
import org.springframework.batch.core.StepExecutionListener;
2230
import org.springframework.batch.core.annotation.AfterStep;
2331
import org.springframework.batch.core.annotation.BeforeStep;
2432
import org.springframework.batch.core.listener.StepListenerFactoryBean;
2533
import org.springframework.batch.core.repository.JobRepository;
2634
import org.springframework.batch.core.step.AbstractStep;
27-
import org.springframework.batch.core.step.tasklet.TaskletStep;
2835
import org.springframework.batch.support.ReflectionUtils;
29-
import org.springframework.transaction.PlatformTransactionManager;
30-
31-
import java.lang.reflect.Method;
32-
import java.util.ArrayList;
33-
import java.util.HashSet;
34-
import java.util.List;
35-
import java.util.Set;
3636

3737
/**
3838
* A base class and utility for other step builders providing access to common properties
@@ -68,6 +68,11 @@ public B repository(JobRepository jobRepository) {
6868
return self();
6969
}
7070

71+
public B observationRegistry(ObservationRegistry observationRegistry) {
72+
properties.observationRegistry = observationRegistry;
73+
return self();
74+
}
75+
7176
public B startLimit(int startLimit) {
7277
properties.startLimit = startLimit;
7378
return self();
@@ -123,6 +128,11 @@ protected void enhance(Step target) {
123128
AbstractStep step = (AbstractStep) target;
124129
step.setJobRepository(properties.getJobRepository());
125130

131+
ObservationRegistry observationRegistry = properties.getObservationRegistry();
132+
if (observationRegistry != null) {
133+
step.setObservationRegistry(observationRegistry);
134+
}
135+
126136
Boolean allowStartIfComplete = properties.allowStartIfComplete;
127137
if (allowStartIfComplete != null) {
128138
step.setAllowStartIfComplete(allowStartIfComplete);
@@ -149,6 +159,8 @@ public static class CommonStepProperties {
149159

150160
private JobRepository jobRepository;
151161

162+
private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
163+
152164
public CommonStepProperties() {
153165
}
154166

@@ -157,6 +169,7 @@ public CommonStepProperties(CommonStepProperties properties) {
157169
this.startLimit = properties.startLimit;
158170
this.allowStartIfComplete = properties.allowStartIfComplete;
159171
this.jobRepository = properties.jobRepository;
172+
this.observationRegistry = properties.observationRegistry;
160173
this.stepExecutionListeners = new ArrayList<>(properties.stepExecutionListeners);
161174
}
162175

@@ -168,6 +181,14 @@ public void setJobRepository(JobRepository jobRepository) {
168181
this.jobRepository = jobRepository;
169182
}
170183

184+
public ObservationRegistry getObservationRegistry() {
185+
return observationRegistry;
186+
}
187+
188+
public void setObservationRegistry(ObservationRegistry observationRegistry) {
189+
this.observationRegistry = observationRegistry;
190+
}
191+
171192
public String getName() {
172193
return name;
173194
}

spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.batch.core.step.factory;
1717

18+
import io.micrometer.observation.ObservationRegistry;
1819
import org.apache.commons.logging.Log;
1920
import org.apache.commons.logging.LogFactory;
2021
import org.springframework.batch.core.ChunkListener;
@@ -84,6 +85,8 @@ public class SimpleStepFactoryBean<T, S> implements FactoryBean<Step>, BeanNameA
8485

8586
protected JobRepository jobRepository;
8687

88+
protected ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
89+
8790
private boolean singleton = true;
8891

8992
private ItemStream[] streams = new ItemStream[0];
@@ -270,6 +273,15 @@ public void setJobRepository(JobRepository jobRepository) {
270273
this.jobRepository = jobRepository;
271274
}
272275

276+
/**
277+
* Public setter for {@link ObservationRegistry}.
278+
* @param observationRegistry is an optional dependency (defaults to
279+
* {@link ObservationRegistry#NOOP}).
280+
*/
281+
public void setObservationRegistry(ObservationRegistry observationRegistry) {
282+
this.observationRegistry = observationRegistry;
283+
}
284+
273285
/**
274286
* Public setter for the {@link PlatformTransactionManager}.
275287
* @param transactionManager the transaction manager to set
@@ -469,6 +481,7 @@ protected void applyConfiguration(SimpleStepBuilder<T, S> builder) {
469481
builder.transactionManager(transactionManager);
470482
builder.transactionAttribute(getTransactionAttribute());
471483
builder.repository(jobRepository);
484+
builder.observationRegistry(observationRegistry);
472485
builder.startLimit(startLimit);
473486
builder.allowStartIfComplete(allowStartIfComplete);
474487
builder.chunk(commitInterval);

0 commit comments

Comments
 (0)