Search code examples
prometheusgrafanamicrometerspring-micrometermicrometer-tracing

How to set up execution time of module in prometheus


I am trying to connect to the prometheus metrics info about how much time it takes a module to be executed. Below I am logging the amount of time it takes to create a session and then output that information. I document the time at the beggining and then at the end see the difference and then theoretically it should upload this info to prometheus, but when I go on http://localhost:8000/, I see nothing, but a blank screen.

I've tried something like this

    @Override
    public void execute() throws Exception {
        PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);

        Date startDate = Calendar.getInstance().getTime();
        IDfCollection collection = null;
        IDfSession session=null;
        CreateSession call = new CreateSession();
        try {
             session = call.privateGetSession();

            log.debug("Running test query : " + DQL_GET_TEST_RESULT, null, null);

            IDfQuery query = new DfQuery();
            query.setDQL(DQL_GET_TEST_RESULT);

            collection = query.execute(session, IDfQuery.DF_READ_QUERY);

        } catch (DfException de) {
            log.error("DFC Exception during test execution " + de.getMessage(), null, null);
        } catch (Exception e) {
            log.error("The following error ocurred: ", e);
        }
        finally {
            try {
                if (collection != null) {
                    collection.close();
                }
                call.releasesession();
            } catch (Exception e) {
                ;
            }
        }

        Date endDate = Calendar.getInstance().getTime();

        long diff = endDate.getTime() - startDate.getTime();
        prometheusRegistry.timer("processingDuration").record(diff, TimeUnit.MILLISECONDS);
}

Full code:

import java.util.Calendar;
import java.util.Date;

import com.documentum.bps.utils.PasswordUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.documentum.fc.client.DfQuery;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfQuery;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.common.DfException;
import com.pgi.tasks.bt.common.CreateSession;

import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.prometheus.client.exporter.HTTPServer;


import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;

@Component("VerifySessionCreationSpentTime")
public class VerifySessionCreationSpentTime extends AbstractTask {

    private static final Logger log = LoggerFactory.getLogger(VerifySessionCreationSpentTime.class);
    private static final String DQL_GET_TEST_RESULT = "SELECT r_object_id FROM dm_document WHERE 1=0";

    @Override
    public void execute() throws Exception {
        PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
        log.debug("VerifySessionCreationSpentTime: begin");
        System.out.println(1);

        Date startDate = Calendar.getInstance().getTime();
        IDfCollection collection = null;
        IDfSession session=null;
        CreateSession call = new CreateSession();
        try {
             session = call.privateGetSession();

            log.debug("Running test query : " + DQL_GET_TEST_RESULT, null, null);

            IDfQuery query = new DfQuery();
            query.setDQL(DQL_GET_TEST_RESULT);

            collection = query.execute(session, IDfQuery.DF_READ_QUERY);

        } catch (DfException de) {
            log.error("DFC Exception during test execution " + de.getMessage(), null, null);
        } catch (Exception e) {
            log.error("The following error ocurred: ", e);
        }
        finally {
            try {
                if (collection != null) {
                    collection.close();
                }
                call.releasesession();
            } catch (Exception e) {
                ;
            }
        }

        Date endDate = Calendar.getInstance().getTime();

        long diff = endDate.getTime() - startDate.getTime();
        prometheusRegistry.timer("processingDuration").record(diff, TimeUnit.MILLISECONDS);
        System.out.println(diff);
        log.debug("VerifySessionCreationSpentTime: end");
    }
    public static void main(String[] args) throws Exception {
        new HTTPServer(8000);
        VerifySessionCreationSpentTime task = new VerifySessionCreationSpentTime();
        task.execute();

    }

}


Solution

  • There are many things wrong with what you are doing:

    1. You are creating a new PrometheusMeterRegistry every single time, you only need one registry in the lifecycle of your app
    2. If Spring Boot Actuator is on the classpath, it will create a registry for you, you can inject a MeterRegistry to your components
    3. You are creating a new HTTPServer, exactly how should it return anything when you did not tell it what to return?
    4. Spring Boot Actuator creates such an endpoint for you (/actuator/prometheus)
    5. You are measuring elapsed time in the wrong way, (see this article why)

    How to do this right: Read the docs :)

    You should end-up with something like this:

    @Component
    public class Demo {
        private final MeterRegistry registry;
    
        public Demo(MeterRegistry registry) {
            this.registry = registry;
        }
    
        public void execute() throws Exception {
            Timer timer = Timer.builder("demo.timer").register(registry);
            timer.record(this::executeBusinessLogic);
        }
    
        void executeBusinessLogic() {
            // ...
        }
    }
    

    Plus a property to enable the Prometheus endpoint:

    management.endpoints.web.exposure.include=prometheus