Echtzeitüberwachung von Watermill mit Prometheus
Metriken
Watermill kann über Dekorateure für Veröffentlicher/Abonnenten und Middleware für Handler überwacht werden. Wir bieten eine Standardimplementierung unter Verwendung des offiziellen Prometheus-Clients für Go.
Das Paket components/metrics
exportiert PrometheusMetricsBuilder
, das praktische Funktionen bereitstellt, um Veröffentlicher, Abonnenten und Handler zu verpacken, um das entsprechende Prometheus-Register zu aktualisieren.
Vollständiger Quellcode: github.com/ThreeDotsLabs/watermill/components/metrics/builder.go
// ...
// Der PrometheusMetricsBuilder bietet Methoden zum Dekorieren von Veröffentlichern, Abonnenten und Handlern.
type PrometheusMetricsBuilder struct {
// PrometheusRegistry kann ein vorhandenes Prometheus-Register befüllen oder leer sein, um das Standardregister zu verwenden.
PrometheusRegistry prometheus.Registerer
Namespace string
Subsystem string
}
// AddPrometheusRouterMetrics ist eine praktische Funktion zum Hinzufügen von Metrik-Middleware zu allen Handlern im Nachrichtenrouter. Es dekoriert auch die Veröffentlicher und Abonnenten der Handler.
func (b PrometheusMetricsBuilder) AddPrometheusRouterMetrics(r *message.Router) {
// ...
Verpacken von Veröffentlichern, Abonnenten und Handlern
Wenn Sie den Router von Watermill verwenden (was in den meisten Fällen empfohlen wird), können Sie die praktische Funktion AddPrometheusRouterMetrics
verwenden, um sicherzustellen, dass alle zu diesem Router hinzugefügten Handler verpackt werden, um das Prometheus-Register zu aktualisieren, sowie deren Veröffentlichern und Abonnenten:
Vollständiger Quellcode: github.com/ThreeDotsLabs/watermill/components/metrics/builder.go
// ...
// AddPrometheusRouterMetrics ist eine praktische Funktion zum Hinzufügen von Metrik-Middleware zu allen Handlern im Nachrichtenrouter. Es dekoriert auch die Veröffentlicher und Abonnenten der Handler.
func (b PrometheusMetricsBuilder) AddPrometheusRouterMetrics(r *message.Router) {
r.AddPublisherDecorators(b.DecoratePublisher)
r.AddSubscriberDecorators(b.DecorateSubscriber)
r.AddMiddleware(b.NewRouterMiddleware().Middleware)
}
// ...
Beispiel zur Verwendung von AddPrometheusRouterMetrics
:
Vollständiger Quellcode: github.com/ThreeDotsLabs/watermill/_examples/basic/4-metrics/main.go
// ...
// Wir lassen die Namespace- und Subsystem-Parameter leer
metricsBuilder := metrics.NewPrometheusMetricsBuilder(prometheusRegistry, "", "")
metricsBuilder.AddPrometheusRouterMetrics(router)
// ...
Im obigen Codeausschnitt lassen wir die Parameter namespace
und subsystem
leer. Die Prometheus-Clientbibliothek verwendet diese Parameter, um Metriknamen zu präfixieren. Sie können Namespace oder Subsystem verwenden, aber beachten Sie, dass dies die Metriknamen beeinflussen wird, sodass Sie das Grafana-Dashboard entsprechend anpassen müssen.
Unabhängige Veröffentlicher und Abonnenten können auch mit dedizierten Methoden von PrometheusMetricsBuilder
dekoriert werden:
Vollständiger Quellcode: github.com/ThreeDotsLabs/watermill/_examples/basic/4-metrics/main.go
// ...
subWithMetrics, err := metricsBuilder.DecorateSubscriber(pubSub)
if err != nil {
panic(err)
}
pubWithMetrics, err := metricsBuilder.DecoratePublisher(pub)
if err != nil {
panic(err)
}
// ...
/metrics-Endpunkt freigeben
Gemäß dem Arbeitsprinzip von Prometheus muss ein Dienst einen HTTP-Endpunkt zur Datenabfrage freigeben. Konventionell handelt es sich dabei um einen GET-Endpunkt und der Pfad ist in der Regel /metrics
.
Um diesen Endpunkt bereitzustellen, stehen zwei praktische Funktionen zur Verfügung, eine, die das zuvor erstellte Prometheus-Register verwendet, und die andere, die gleichzeitig ein neues Register erstellt:
Vollständiger Quellcode: github.com/ThreeDotsLabs/watermill/components/metrics/http.go
// ...
// CreateRegistryAndServeHTTP richtet einen HTTP-Server unter der angegebenen Adresse ein, um den /metrics-Endpunkt für Prometheus freizugeben.
// Es gibt ein neues Prometheus-Register (zur Metrikregistrierung) und eine Stornierungsfunktion zum Herunterfahren des Servers zurück.
func CreateRegistryAndServeHTTP(addr string) (register *prometheus.Register, cancel func()) {
register = prometheus.NewRegistry()
return register, ServeHTTP(addr, register)
}
// ServeHTTP richtet einen HTTP-Server unter der angegebenen Adresse ein, um den /metrics-Endpunkt für Prometheus freizugeben.
// Es akzeptiert ein bestehendes Prometheus-Register und gibt eine Stornierungsfunktion zurück, um den Server herunterzufahren.
func ServeHTTP(addr string, register *prometheus.Register) (cancel func()) {
// ...
Hier ist ein Anwendungsbeispiel:
Vollständiger Quellcode: github.com/ThreeDotsLabs/watermill/_examples/basic/4-metrics/main.go
// ...
prometheusRegister, closeMetricsServer := metrics.CreateRegistryAndServeHTTP(*metricsAddr)
defer closeMetricsServer()
// Wir lassen den Namespace und das Subsystem leer
metricsBuilder := metrics.NewPrometheusMetricsBuilder(prometheusRegister, "", "")
metricsBuilder.AddPrometheusRouterMetrics(router)
// ...
Beispielanwendung
Um zu verstehen, wie das Dashboard in der Praxis funktioniert, können Sie das Beispiel für Metriken konsultieren.
Folgen Sie den Anweisungen in der README des Beispiels, um es auszuführen und die Prometheus-Datenquelle zu Grafana hinzuzufügen.
Grafana-Dashboard
Wir haben ein Grafana-Dashboard für die oben genannte Metrikimplementierung vorbereitet. Es bietet grundlegende Informationen über Durchsatz, Fehlerquote und Veröffentlichungs-/Verarbeitungsdauer.
Wenn Sie dieses Dashboard lokal anzeigen möchten, können Sie die Beispielanwendung verwenden.
Für weitere Informationen zu den an Prometheus exportierten Metriken, siehe Exportierte Metriken.
Dashboard importieren
Um das Grafana-Dashboard zu importieren, wählen Sie Dashboard/Verwalten aus dem linken Menü und klicken Sie dann auf +Import
.
Geben Sie die URL des Dashboards ein https://grafana.com/dashboards/9777 (oder nur die ID, 9777) und klicken Sie dann auf Laden.
Wählen Sie dann die Prometheus-Datenquelle aus, die zum Abrufen des /metrics
-Endpunkts verwendet wird. Klicken Sie auf Importieren
und fertig!
Exportierte Metriken
Im Folgenden sind alle Metriken aufgeführt, die im Prometheus-Register von PrometheusMetricsBuilder
registriert sind.
Für weitere Informationen zu Prometheus-Metrikenarten siehe die Prometheus-Dokumentation.
Objekt | Metrik | Beschreibung | Labels/Werte |
---|---|---|---|
Abonnent | subscriber_messages_received_total |
Ein Prometheus-Zähler. Zählt die Anzahl der vom Abonnenten empfangenen Nachrichten. | acked ist "acked" oder "nacked". |
Wenn der Abonnent in einem Handler arbeitet, wird handler_name gesetzt; andernfalls " |
|||
subscriber_name identifiziert den Abonnenten. Wenn er das fmt.Stringer -Interface implementiert, ist es das Ergebnis von String() ; andernfalls ist es package.structName . |
|||
Handler | handler_execution_time_seconds |
Ein Prometheus-Histogramm. Zeichnet die Ausführungszeit der von Middleware umgebenen Handler-Funktion auf. | handler_name ist der Name des Handlers. |
success ist "true" oder "false", je nachdem, ob die umgebene Handler-Funktion einen Fehler zurückgibt. |
|||
Verleger | publish_time_seconds |
Ein Prometheus-Histogramm. Zeichnet die Ausführungszeit der dekorierten Veröffentlichungsfunktion des Verlegers auf. | success ist "true" oder "false", je nachdem, ob der dekorierte Verleger einen Fehler zurückgibt. |
Wenn der Verleger in einem Handler arbeitet, wird handler_name gesetzt; andernfalls " |
|||
publisher_name identifiziert den Verleger. Wenn er das fmt.Stringer -Interface implementiert, ist es das Ergebnis von String() ; andernfalls ist es package.structName . |
Zusätzlich hat jede Metrik ein node
-Label von Prometheus mit seinem Wert entsprechend der Instanz der Metrikquelle und ein job
, das als Jobname in der Prometheus-Konfigurationsdatei angegeben ist.
Hinweis: Wie oben erwähnt, führt die Verwendung eines nicht leeren namespace
oder subsystem
zu einem Metriknamenpräfix. Es können entsprechende Anpassungen erforderlich sein, z. B. in der Paneldefinition eines Grafana-Dashboards.
Anpassung
Wenn Sie der Meinung sind, dass bestimmte Metriken übersehen wurden, können Sie diese grundlegende Implementierung problemlos erweitern. Der beste Weg ist die Verwendung des mit der ServeHTTP
-Methode verwendeten Prometheus-Registers und die Registrierung der Metriken gemäß der Dokumentation des Prometheus-Clients hier.
Eine kurze Methode zur Aktualisierung dieser Metriken besteht darin, Dekorateure zu verwenden. Der vollständige Quellcode finden Sie unter github.com/ThreeDotsLabs/watermill/message/decorator.go.
// ...
// MessageTransformSubscriberDecorator erstellt einen Abonnentendekorator, der die Transformationsfunktion für jede Nachricht aufruft, die durch den Abonnenten übergeben wird.
func MessageTransformSubscriberDecorator(transform func(*Message)) SubscriberDecorator {
if transform == nil {
panic("Transformationsfunktion ist nil")
}
return func(sub Subscriber) (Subscriber, error) {
return &messageTransformSubscriberDecorator{
sub: sub,
transform: transform,
}, nil
}
}
// MessageTransformPublisherDecorator erstellt einen Verlegerdek