Skip to content

Activation of Actuator & Prometheus rise a WARN in the log due to bad configuration #4753

Open
@pkernevez

Description

@pkernevez

Bug description
When adding dependencies to Actuator & Prometheus the first time a job is run (meaning each time the JVM is restarted) there is a Warn log that is logged.
The raison is: the same metric is initialed in 2 locations with different tags.
The logs is:

19:07:27.786  WARN 62730 [        batch-1] i.m.p.PrometheusMeterRegistry  : The meter (MeterId{name='spring.batch.job.active', tags=[tag(spring.batch.job.name=cobJob),tag(spring.batch.job.status=UNKNOWN)]}) registration has failed: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter named 'spring.batch.job.active' containing tag keys [spring.batch.job.active.name]. The meter you are attempting to register has keys [spring.batch.job.name, spring.batch.job.status]. Note that subsequent logs will be logged at debug level.

Environment
Spring Boot: 3.4.2
SpringBatch: 5.2.1
Java: 21+

Steps to reproduce
Add the 2 following dependencies in your POM:

        <!--  New dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
    </dependencies>

Run a batch and the log will be outputted in your logs.

The issues is in AbstractJob.execute:

	@Override
	public final void execute(JobExecution execution) {

		Assert.notNull(execution, "jobExecution must not be null");
		execution.getExecutionContext().put(SpringBatchVersion.BATCH_VERSION_KEY, SpringBatchVersion.getVersion());

		if (logger.isDebugEnabled()) {
			logger.debug("Job execution starting: " + execution);
		}

		JobSynchronizationManager.register(execution);
		String activeJobMeterName = "job.active";
		LongTaskTimer longTaskTimer = BatchMetrics.createLongTaskTimer(this.meterRegistry, activeJobMeterName,
				"Active jobs", Tag.of(BatchMetrics.METRICS_PREFIX + activeJobMeterName + ".name",
						execution.getJobInstance().getJobName()));
		LongTaskTimer.Sample longTaskTimerSample = longTaskTimer.start();
		Observation observation = BatchMetrics
			.createObservation(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), new BatchJobContext(execution),
					this.observationRegistry)
			.contextualName(execution.getJobInstance().getJobName())
			.observationConvention(this.observationConvention)
			.start();
		try (Observation.Scope scope = observation.openScope()) {
  1. The line L285 LongTaskTimer longTaskTimer = BatchMetrics.createLongTaskTimer creates the explicit metrics with full name spring.batch.job.activeand tag spring.batch.job.active.name.

  2. And the line .createObservation(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), new BatchJobContext(execution), is creating an observation with the same name spring.batch.job.active and the execution context. This execution context is used later to create the tags:
    in io.micrometer.core.instrument.observation.DefaultMeterObservationHandler#75:

            LongTaskTimer.Sample longTaskSample = LongTaskTimer.builder(context.getName() + ".active")
                .tags(createTags(context))
                .register(meterRegistry)
                .start();

But the tags are now dynamicaly created fron the execution context:tags=[tag(spring.batch.job.name=importUserJob),tag(spring.batch.job.status=UNKNOWN)]})
3. The tags are different and this is not supported by the PrometheusMeterRegistry framework https://github.com/micrometer-metrics/micrometer/blob/074e351e03b39ff330f7890402dd44a906ee31ee/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheusmetrics/PrometheusMeterRegistry.java#L587
Because on the line L582 the tags were not the same.

Expected behavior
Not log a warn.

Minimal Complete Reproducible example
I created a fork of https://github.com/spring-guides/gs-batch-processing with a single commit.
Just run the app (not the test, because the test is not starting the full stack):
https://github.com/pkernevez/gs-batch-processing/tree/warn-issue

/opt/homebrew/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:/Applications/IntelliJ IDEA_2024_2.4.app/Contents/lib/idea_rt.jar=63083:/Applications/IntelliJ IDE..../.m2/repository/io/prometheus/prometheus-metrics-exposition-textformats/1.3.5/prometheus-metrics-exposition-textformats-1.3.5.jar com.example.batchprocessing.BatchProcessingApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.4.2)

2025-01-28T21:27:56.755+01:00  INFO 70368 --- [           main] c.e.b.BatchProcessingApplication         : Starting BatchProcessingApplication using Java 21.0.1 with PID 70368 (/Users/pke/SCM/Git/Shift/gs-batch-processing/complete/target/classes started by pke in /Users/pke/SCM/Git/Shift/gs-batch-processing/complete)
2025-01-28T21:27:56.756+01:00  INFO 70368 --- [           main] c.e.b.BatchProcessingApplication         : No active profile set, falling back to 1 default profile: "default"
2025-01-28T21:27:57.126+01:00  INFO 70368 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2025-01-28T21:27:57.313+01:00  INFO 70368 --- [           main] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Driver does not support get/set network timeout for connections. (feature not supported)
2025-01-28T21:27:57.314+01:00  INFO 70368 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection org.hsqldb.jdbc.JDBCConnection@6cbd0674
2025-01-28T21:27:57.315+01:00  INFO 70368 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2025-01-28T21:27:57.630+01:00  INFO 70368 --- [           main] c.e.b.BatchProcessingApplication         : Started BatchProcessingApplication in 1.018 seconds (process running for 1.269)
2025-01-28T21:27:57.631+01:00  INFO 70368 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2025-01-28T21:27:57.646+01:00  INFO 70368 --- [           main] o.s.b.c.l.s.TaskExecutorJobLauncher      : Job: [SimpleJob: [name=importUserJob]] launched with the following parameters: [{}]

2025-01-28T21:27:57.651+01:00  WARN 70368 --- [           main] i.m.p.PrometheusMeterRegistry            : The meter (MeterId{name='spring.batch.job.active', tags=[tag(spring.batch.job.name=importUserJob),tag(spring.batch.job.status=UNKNOWN)]}) registration has failed: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter named 'spring.batch.job.active' containing tag keys [spring.batch.job.active.name]. The meter you are attempting to register has keys [spring.batch.job.name, spring.batch.job.status]. Note that subsequent logs will be logged at debug level.

2025-01-28T21:27:57.657+01:00  INFO 70368 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
2025-01-28T21:27:57.662+01:00  INFO 70368 --- [           main] c.e.batchprocessing.PersonItemProcessor  : Converting (Person[firstName=Jill, lastName=Doe]) into (Person[firstName=JILL, lastName=DOE])
2025-01-28T21:27:57.663+01:00  INFO 70368 --- [           main] c.e.batchprocessing.PersonItemProcessor  : Converting (Person[firstName=Joe, lastName=Doe]) into (Person[firstName=JOE, lastName=DOE])
2025-01-28T21:27:57.664+01:00  INFO 70368 --- [           main] c.e.batchprocessing.PersonItemProcessor  : Converting (Person[firstName=Justin, lastName=Doe]) into (Person[firstName=JUSTIN, lastName=DOE])
2025-01-28T21:27:57.667+01:00  INFO 70368 --- [           main] c.e.batchprocessing.PersonItemProcessor  : Converting (Person[firstName=Jane, lastName=Doe]) into (Person[firstName=JANE, lastName=DOE])
2025-01-28T21:27:57.667+01:00  INFO 70368 --- [           main] c.e.batchprocessing.PersonItemProcessor  : Converting (Person[firstName=John, lastName=Doe]) into (Person[firstName=JOHN, lastName=DOE])
2025-01-28T21:27:57.668+01:00  INFO 70368 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [step1] executed in 11ms
2025-01-28T21:27:57.670+01:00  INFO 70368 --- [           main] c.e.b.JobCompletionNotificationListener  : !!! JOB FINISHED! Time to verify the results
2025-01-28T21:27:57.672+01:00  INFO 70368 --- [           main] c.e.b.JobCompletionNotificationListener  : Found <Person[firstName=JILL, lastName=DOE]> in the database.
2025-01-28T21:27:57.672+01:00  INFO 70368 --- [           main] c.e.b.JobCompletionNotificationListener  : Found <Person[firstName=JOE, lastName=DOE]> in the database.
2025-01-28T21:27:57.672+01:00  INFO 70368 --- [           main] c.e.b.JobCompletionNotificationListener  : Found <Person[firstName=JUSTIN, lastName=DOE]> in the database.
2025-01-28T21:27:57.672+01:00  INFO 70368 --- [           main] c.e.b.JobCompletionNotificationListener  : Found <Person[firstName=JANE, lastName=DOE]> in the database.
2025-01-28T21:27:57.672+01:00  INFO 70368 --- [           main] c.e.b.JobCompletionNotificationListener  : Found <Person[firstName=JOHN, lastName=DOE]> in the database.
2025-01-28T21:27:57.673+01:00  INFO 70368 --- [           main] o.s.b.c.l.s.TaskExecutorJobLauncher      : Job: [SimpleJob: [name=importUserJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 18ms
2025-01-28T21:27:57.676+01:00  INFO 70368 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2025-01-28T21:27:57.691+01:00  INFO 70368 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Process finished with exit code 0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions