MoSKitoAnleitungJava4 Min. Lesezeit

Rezept: Einen einfachen Prozess mit Countern überwachen

Ein Rezept, um erfolgreiche und fehlgeschlagene Ausführungen eines wiederkehrenden Jobs mit einem MoSKito-@Count-Counter zu zählen, in MoSKito Inspect anzuzeigen und ein eigenes Dashboard zu bauen.

Von Zeit zu Zeit fragen uns MoSKito-Nutzer, wie man dies oder jenes macht und wie sich ein bestimmter Anwendungsfall mit MoSKito umsetzen lässt. Deshalb haben wir einen Rezeptbereich in unserer Dokumentation und nun auch im Blog gestartet. Ein Rezept beschreibt, wie man ein bestimmtes Ziel erreicht.

Die ursprüngliche Frage, die zu diesem Rezept geführt hat, lautete: „Angenommen, ich habe einen Prozess, eine Art Job, der alle x Sekunden läuft, und ich möchte mit möglichst geringem Aufwand die Anzahl erfolgreicher und fehlgeschlagener Ausführungen überwachen.“ Und so geht's.

Das Beispiel aufsetzen

Zunächst haben wir ein einfaches Beispiel erstellt, das zeigt, was hier passiert. Das Beispiel finden Sie im Modul recipe im GitHub-Repository moskito-demo unter: https://github.com/anotheria/moskito-demo/tree/master/recipes/counter. Zuerst gibt es unseren Daemon-Worker:

public class Daemon {
    public static void main(String a[]) throws Exception{

        //since we are running in now container, we need to enable moskito by hand. This is not needed in a webapp or another environment if you already have moskito running.
        StartMoSKitoInspectBackendForRemote.startMoSKitoInspectBackend(9401);

        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        //perform the task every 2 seconds.
        service.scheduleAtFixedRate(new Job(), 0, 2, TimeUnit.SECONDS);
    }
}

Beachten Sie, dass das manuelle Starten des MoSKito-Backends nur nötig ist, weil das Beispiel aufs Minimum reduziert ist. In einer Web-App oder mit dem moskito-javaagent usw. wäre das nicht erforderlich. Davon abgesehen übergibt der Daemon lediglich einen neuen Job an einen Executor-Service. Weiter also zum Code des Jobs:

public class Job implements Runnable{

    //this is the annotation based counter, based on moskito-aop.
    private static Counter counter = new Counter();
    private static Random rnd = new Random(System.nanoTime());

    @Override
    public void run() {
        int result = rnd.nextInt(10);
        boolean success = result < 8;
        System.out.println("Executing job, result "+result+" success: "+success);
        if (success){
            counter.success();
        }else{
            counter.error();
        }
    }
}

Nachdem wir also festgestellt haben, ob unsere Ausführung ein Erfolg oder ein Fehlschlag war, rufen wir lediglich eine Methode in einem Counter auf. Dieser Counter muss doch eine magische Klasse sein, oder? Nein, eigentlich nicht:

@Count(producerId = "ProcessCounter")
public class Counter {
    /**
     * Call this method when the process has been successful.
     */
    public void success(){}

    /**
     * Call this method when the process has finished with an error.
     */
    public void error(){}
}

Unsere Counter-Klasse ist also nur eine „leere“ Klasse mit zwei Marker-Methoden. Und einer Annotation: @Count. Sie veranlasst MoSKito, alle Aufrufe jeder Methode dieser Klasse zu zählen. Über Counter habe ich bereits vor einiger Zeit geschrieben: http://blog.anotheria.net/msk/one-to-count-them-all/

Ausführen

Jetzt muss ich nur noch das Projekt auschecken und es in meinem Eclipse oder IntelliJ starten:

Nun gehe ich auf die MoSKito-Downloadseite: https://www.moskito.org/download.html, lade die neueste Version herunter, starte MoSKito Inspect und verbinde mich mit localhost:9401 (das ist der Port, der im Aufruf von StartMoSKitoInspectBackendForRemote verwendet wurde).

Im Counter-Bereich sehe ich, dass mein Prozess bereits arbeitet und zählt:

Ein Klick auf ProcessCounter führt mich zu den Details:

wo ich die Erfolgs- und Fehlerraten meines Prozesses sehen kann.

Ein eigenes Dashboard bauen

Jetzt überwache ich meinen Prozess und er läuft, aber ich möchte mehr Kontrolle haben und ein Dashboard bauen. Ein neues Dashboard lässt sich in moskito-inspect spontan anlegen, aber damit es Neustarts übersteht (und Änderungen in der Versionskontrolle nachvollziehbar sind), müssen Sie es in die Konfigurationsdatei moskito.json eintragen. Mit dem Demo-Projekt wird eine Beispielkonfiguration mitgeliefert.

Mein Dashboard sieht so aus:

Mein Dashboard enthält einen Threshold, ein Gauge und ein Chart. Das Gauge ist für mich nur eine visuelle Hilfe, um zu erkennen, ob der aktuelle Wert in Ordnung ist oder nicht. Es basiert auf der aktuellen Fehleranzahl:

      {
        "name": "Proc Errors",
        "caption": "Process Errors",
        "@minValue": {
          "constant": 0
        },
        "@currentValue": {
          "producerName": "ProcessCounter",
          "statName": "error",
          "valueName": "Counter",
          "intervalName": "1m"
        },
        "@maxValue": {
          "constant": 50
        },

Der Minimalwert ist offensichtlich null, der rechte Wert ist 50 (den ich mir einfach ausgedacht habe), und der Wert des Gauges ist die Anzahl der Fehler in der letzten Minute.

Eine ähnliche Konfiguration wird für den Threshold verwendet. Die Details erspare ich Ihnen, stattdessen hier der Link zur Beispielkonfigurationsdatei: https://github.com/anotheria/moskito-demo/blob/master/recipes/counter/src/main/resources/moskito.json.

Zum Schluss muss ich alles zu einem neuen Dashboard zusammenfügen:

  "@dashboardsConfig": {
    "@dashboards": [
      {
        "name": "Process Dashboard",
        "refresh": 60,
        "@charts": [
          {
            "caption": "ProcessCounter",
            "accumulators": [
              "ProcessCounter SuccessPerMinute",
              "ProcessCounter ErrorPerMinute"
            ]
          }
        ],
        "@thresholds": [
          "ProcessCounter Errors"
        ],
        "@gauges": [
          "Proc Errors"
        ]
      }

    ]
  },

Das war's. Mein schickes Dashboard ist fertig, und alle im Unternehmen wissen, wie der Prozess läuft.

Eine Sache noch

Eine Sache ist noch zu erwähnen: In der ursprünglichen Anfrage wurde gefragt, ob man einen Counter auch ohne Annotation-Processing bauen kann. Annotation-basierte Counter sind zwar wirklich einfach (im Grunde nur die Hülle einer echten Klasse), aber wenn Sie aus welchen Gründen auch immer kein AOP verwenden möchten, müssen Sie das nicht. Sie können den Counter auch selbst bauen. Wir haben in dieses Rezept ein Beispiel für einen selbstgebauten Counter aufgenommen:

public class SelfMadeCounter {

    private OnDemandStatsProducer<CounterStats> producer;

    public SelfMadeCounter(){
        producer = new EntryCountLimitedOnDemandStatsProducer<>("ProcessCounter", "default", "default", CounterStatsFactory.DEFAULT_INSTANCE, 10);
        ProducerRegistryFactory.getProducerRegistryInstance().registerProducer(producer);
    }

    public void success(){
        try {
            producer.getStats("success").inc();
            producer.getDefaultStats().inc();
        }catch(OnDemandStatsProducerException e){
            //won't happen, cause we only use 2 stats.
        }
    }

    public void error(){
        try {
            producer.getStats("error").inc();
            producer.getDefaultStats().inc();
        }catch(OnDemandStatsProducerException e){
            //won't happen, cause we only use 2 stats.
        }
    }
}

Ersetzen Sie einfach in der Klasse Job die Initialisierung des Counter durch SelfMadeCounter, und schon sind Sie fertig.

Viel Spaß also beim Zählen der Fehler Ihres Prozesses und, noch wichtiger, seiner Erfolge!

Haben Sie ein System, das Sie ausbremst, oder eine Idee, die bisher niemand günstig genug bauen konnte?

Lassen Sie uns reden. 30 Minuten, ohne Pitch-Deck.

Worum geht es?