All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.batch.core.observability.BatchMetrics Maven / Gradle / Ivy

/*
 * Copyright 2019-2023 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.batch.core.observability;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.LongTaskTimer;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;

import org.springframework.lang.Nullable;

/**
 * Central class for batch metrics. It provides:
 *
 * 
    *
  • the main entry point to interact with Micrometer's API to create common metrics * such as {@link Timer} and {@link LongTaskTimer}.
  • *
  • Some utility methods like calculating durations and formatting them in a human * readable format.
  • *
* * Only intended for internal use. * * @author Mahmoud Ben Hassine * @author Glenn Renfro * @since 4.2 */ public final class BatchMetrics { public static final String METRICS_PREFIX = "spring.batch."; public static final String STATUS_SUCCESS = "SUCCESS"; public static final String STATUS_FAILURE = "FAILURE"; private BatchMetrics() { } /** * Create a {@link Timer}. * @param meterRegistry the meter registry to use * @param name of the timer. Will be prefixed with * {@link BatchMetrics#METRICS_PREFIX}. * @param description of the timer * @param tags of the timer * @return a new timer instance */ public static Timer createTimer(MeterRegistry meterRegistry, String name, String description, Tag... tags) { return Timer.builder(METRICS_PREFIX + name) .description(description) .tags(Arrays.asList(tags)) .register(meterRegistry); } /** * Create a {@link Counter}. * @param meterRegistry the meter registry to use * @param name of the counter. Will be prefixed with * {@link BatchMetrics#METRICS_PREFIX}. * @param description of the counter * @param tags of the counter * @return a new timer instance */ public static Counter createCounter(MeterRegistry meterRegistry, String name, String description, Tag... tags) { return Counter.builder(METRICS_PREFIX + name) .description(description) .tags(Arrays.asList(tags)) .register(meterRegistry); } /** * Create a new {@link Observation}. It's not started, you must explicitly call * {@link Observation#start()} to start it. *

* Remember to register the {@link DefaultMeterObservationHandler} via the * {@code Metrics.globalRegistry.withTimerObservationHandler()} in the user code. * Otherwise you won't observe any metrics. * @param name of the observation * @param context of the batch job observation * @return a new observation instance * @since 5.0 */ public static Observation createObservation(String name, BatchJobContext context, ObservationRegistry observationRegistry) { return Observation.createNotStarted(name, context, observationRegistry); } /** * Create a new {@link Observation}. It's not started, you must explicitly call * {@link Observation#start()} to start it. *

* Remember to register the {@link DefaultMeterObservationHandler} via the * {@code Metrics.globalRegistry.withTimerObservationHandler()} in the user code. * Otherwise you won't observe any metrics. * @param name of the observation * @param context of the observation step context * @return a new observation instance * @since 5.0 */ public static Observation createObservation(String name, BatchStepContext context, ObservationRegistry observationRegistry) { return Observation.createNotStarted(name, context, observationRegistry); } /** * Create a new {@link Timer.Sample}. * @param meterRegistry the meter registry to use * @return a new timer sample instance */ public static Timer.Sample createTimerSample(MeterRegistry meterRegistry) { return Timer.start(meterRegistry); } /** * Create a new {@link LongTaskTimer}. * @param meterRegistry the meter registry to use * @param name of the long task timer. Will be prefixed with * {@link BatchMetrics#METRICS_PREFIX}. * @param description of the long task timer. * @param tags of the timer * @return a new long task timer instance */ public static LongTaskTimer createLongTaskTimer(MeterRegistry meterRegistry, String name, String description, Tag... tags) { return LongTaskTimer.builder(METRICS_PREFIX + name) .description(description) .tags(Arrays.asList(tags)) .register(meterRegistry); } /** * Calculate the duration between two dates. * @param startTime the start time * @param endTime the end time * @return the duration between start time and end time */ @Nullable public static Duration calculateDuration(@Nullable LocalDateTime startTime, @Nullable LocalDateTime endTime) { if (startTime == null || endTime == null) { return null; } return Duration.between(startTime, endTime); } /** * Format a duration in a human readable format like: 2h32m15s10ms. * @param duration to format * @return A human readable duration */ public static String formatDuration(@Nullable Duration duration) { if (duration == null || duration.isZero() || duration.isNegative()) { return ""; } StringBuilder formattedDuration = new StringBuilder(); long hours = duration.toHours(); long minutes = duration.toMinutes(); long seconds = duration.getSeconds(); long millis = duration.toMillis(); if (hours != 0) { formattedDuration.append(hours).append("h"); } if (minutes != 0) { formattedDuration.append(minutes - TimeUnit.HOURS.toMinutes(hours)).append("m"); } if (seconds != 0) { formattedDuration.append(seconds - TimeUnit.MINUTES.toSeconds(minutes)).append("s"); } if (millis != 0) { formattedDuration.append(millis - TimeUnit.SECONDS.toMillis(seconds)).append("ms"); } return formattedDuration.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy