web-dev-qa-db-fra.com

Instrumenter une application Java avec Prometheus

J'essaie de surveiller plusieurs métriques dans une application Java à l'aide de la bibliothèque cliente Prometheus Java, mais j'ai des difficultés à surveiller plusieurs métriques à la fois. Si je n'enregistre et n'efface qu'une métrique, tout semble bien fonctionner et je peux voir la métrique à l'aide de l'application prometheus, mais si j'essaie d'exposer et de surveiller plus d'une métrique, une seule de ces métriques sera visible.

Donc, si j'ai une application avec la classe instrumentée ci-dessous

package com.telemetryserver.Instrumentation;

import io.prometheus.client.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import Java.io.IOException;

public class Instrumented_Class extends HttpServlet
{
    private static Instrumented_Class _instance = null;

    public static final Gauge metric_1 = Gauge.build().name("metric_1").help("metric_1").register();
    //public static final Gauge metric_2 = Gauge.build().name("metric_2").help("metric_2").register();

    public static Instrumented_Class getInstance()
    {
        if (_instance == null)
            _instance = new Instrumented_Class();

        return _instance;
    }

    //Getters and Setters

    public static void setMetric_1(double val) { metric_1.set(val); }

    public static double getMetric_1() { return metric_1.get(); }

    //public static void setMetric_2(double val) { metric_2.set(val); }

    //public static double getMetric_2() { return metric_2.get(); }

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException
    {

        double metric_1 = Instrumented_Class.getMetric_1();
        Instrumented_Class.setMetric_1(metric_1 + 1);

        //double metric_2 = Instrumented_Class.getMetric_2();
        //Instrumented_Class.setMetric_2(metric_2 + 2);

        resp.getWriter().println("Hello from Instrumented_Class!!!," +
                " metric_1 = " + metric_1
                //+ " metric_2 = " + metric_2
        );
    }
}

et la classe principale comme 

package com.telemetryserver.client;


import com.telemetryserver.Instrumentation.*;
import io.prometheus.client.exporter.MetricsServlet;
import io.prometheus.client.hotspot.DefaultExports;
import org.Eclipse.jetty.server.Server;
import org.Eclipse.jetty.servlet.ServletContextHandler;
import org.Eclipse.jetty.servlet.ServletHolder;

public class TelemetryApp
{
    public static void main(String[] args)
    {
        startTestServer(2018);
    }


    public static void startTestServer(int port)
    {
        try
        {
            Server server = new Server(port);
            ServletContextHandler context = new ServletContextHandler();
            context.setContextPath("/");
            server.setHandler(context);

            //Expose our Instrumented servlet.
            context.addServlet(new ServletHolder(Instrumented_Class.getInstance()), "/");

            //Prometheus Metrics Servlet
            context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");

            // Add metrics about CPU, JVM memory etc.
            //DefaultExports.initialize();

            // Start the webserver.
            server.start();
            server.join();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
 }

et aussi en utilisant le fichier YAML 

global:
  scrape_interval:     2s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 2s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'telemetryserver'

    metrics_path : '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:2018']

Je peux surveiller la métrique "métrique_1" en exécutant prometheus puis en exécutant la requête "métrique_1". Tout va bien, mais si j'ajoute une autre métrique appelée métrique_2 en supprimant la mise en commentaire des lignes de la classe instrumentée, la métrique_2 s'affiche sur Prometheus, mais la métrique_1 cesse de s'afficher. De plus, si je supprime la mise en commentaire de la ligne DefaultExports.initialize(); (qui ajoute toutes les métriques prometheus par défaut), alors métric_1 et métric_2 cessent tous deux d’apparaître et seule une métrique par défaut appelée "jvm_threads_current" s’affiche.

Quelqu'un peut-il m'éclairer sur la façon dont je peux surveiller plusieurs indicateurs dans Prometheus? Toute aide appréciée.

4
KillaKem

Votre demande va bien. 

Assurez-vous simplement de le tester en appuyant sur le noeud final /metrics. Voici comment Prometheus collecte les métriques de votre application.

Lorsque je teste localement, avec les deux métriques et en exportant les métriques JVM, j'ai une sortie similaire à celle-ci:

*** lots of jvm metrics
jvm_gc_collection_seconds_count{gc="PS MarkSweep",} 0.0
jvm_gc_collection_seconds_sum{gc="PS MarkSweep",} 0.0
# HELP metric_2 metric_2
# TYPE metric_2 gauge
metric_2 12.0
# HELP metric_1 metric_1
# TYPE metric_1 gauge
metric_1 6.0
# HELP jvm_threads_current Current thread count of a JVM
# TYPE jvm_threads_current gauge
jvm_threads_current 16.0

Qui contient vos métriques personnalisées et également les métriques de JVM.

Votre configuration Prometheus est également correcte. Pour tester l'intégration, allez dans "Statut"> "Cibles", et vous devriez voir votre service là-bas comme dans l'image ci-dessous:

 Targets page

Ensuite, allez à la page "Graphique" et entrez l'expression {job="telemetryserver"} pour vérifier que Prometheus est en train de collecter les métriques de votre application. Vous devriez voir quelque chose de similaire à:

 Metrics

1
fgasparini