Pemantauan Real-time Watermill menggunakan Prometheus
Metrik
Watermill dapat dipantau dengan menggunakan decorator untuk penerbit/langganan dan middleware untuk penangan. Kami menyediakan implementasi default menggunakan klien Prometheus resmi untuk Go.
Paket components/metrics
mengekspor PrometheusMetricsBuilder
, yang menyediakan fungsi-fungsi yang nyaman untuk melipatgandakan penerbit, langganan, dan penangan untuk memperbarui registri Prometheus yang relevan:
Kode sumber lengkap: github.com/ThreeDotsLabs/watermill/components/metrics/builder.go
// ...
// PrometheusMetricsBuilder menyediakan metode untuk mendekorasi penerbit, langganan, dan penangan.
type PrometheusMetricsBuilder struct {
// PrometheusRegistry dapat diisi dengan registri Prometheus yang ada atau kosong untuk menggunakan registri default.
PrometheusRegistry prometheus.Registerer
Namespace string
Subsystem string
}
// AddPrometheusRouterMetrics adalah fungsi yang nyaman untuk menambahkan middleware metrik ke semua penangan pada router pesan. Ini juga mendekorasi penerbit dan langganan dari penangan.
func (b PrometheusMetricsBuilder) AddPrometheusRouterMetrics(r *message.Router) {
// ...
Melipatgandakan Penerbit, Langganan, dan Penangan
Jika Anda menggunakan router Watermill (yang direkomendasikan dalam kebanyakan kasus), Anda dapat menggunakan fungsi yang nyaman AddPrometheusRouterMetrics
untuk memastikan bahwa semua penangan yang ditambahkan ke router ini dilipatgandakan untuk memperbarui registri Prometheus, begitu juga dengan penerbit dan langganan mereka:
Kode sumber lengkap: github.com/ThreeDotsLabs/watermill/components/metrics/builder.go
// ...
// AddPrometheusRouterMetrics adalah fungsi yang nyaman untuk menambahkan middleware metrik ke semua penangan pada router pesan. Ini juga mendekorasi penerbit dan langganan dari penangan.
func (b PrometheusMetricsBuilder) AddPrometheusRouterMetrics(r *message.Router) {
r.AddPublisherDecorators(b.DecoratePublisher)
r.AddSubscriberDecorators(b.DecorateSubscriber)
r.AddMiddleware(b.NewRouterMiddleware().Middleware)
}
// ...
Contoh penggunaan AddPrometheusRouterMetrics
:
Kode sumber lengkap: github.com/ThreeDotsLabs/watermill/_examples/basic/4-metrics/main.go
// ...
// Kami biarkan namespace dan subsystem kosong
metricsBuilder := metrics.NewPrometheusMetricsBuilder(prometheusRegistry, "", "")
metricsBuilder.AddPrometheusRouterMetrics(router)
// ...
Pada potongan kode di atas, kami membiarkan parameter namespace
dan subsystem
kosong. Pustaka klien Prometheus menggunakan parameter-parameter ini untuk menambahkan awalan ke nama-nama metrik. Anda mungkin ingin menggunakan namespace atau subsystem, namun perhatikan bahwa ini akan memengaruhi nama-nama metrik, sehingga Anda perlu menyesuaikan dasbor Grafana sesuai.
Penerbit dan langganan independen juga dapat dilipatgandakan menggunakan metode-metode khusus dari PrometheusMetricsBuilder
:
Kode sumber lengkap: 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)
}
// ...
Memaparkan /metrics Endpoint
Menurut prinsip kerja Prometheus, sebuah layanan perlu memaparkan sebuah endpoint HTTP untuk pengambilan data. Biasanya ini merupakan endpoint GET, dan jalurnya biasanya /metrics
.
Untuk menyediakan endpoint ini, terdapat dua fungsi yang nyaman tersedia, satu menggunakan Prometheus Registry yang sebelumnya dibuat dan yang lainnya secara bersamaan membuat Registry baru:
Source code lengkap: github.com/ThreeDotsLabs/watermill/components/metrics/http.go
// ...
// CreateRegistryAndServeHTTP membentuk sebuah server HTTP di alamat yang diberikan untuk memaparkan endpoint /metrics ke Prometheus.
// Ini mengembalikan Prometheus Registry baru (untuk registrasi metrik) dan fungsi pembatalan untuk mematikan server.
func CreateRegistryAndServeHTTP(addr string) (registry *prometheus.Registry, cancel func()) {
registry = prometheus.NewRegistry()
return registry, ServeHTTP(addr, registry)
}
// ServeHTTP membentuk sebuah server HTTP di alamat yang diberikan untuk memaparkan endpoint /metrics ke Prometheus.
// Ini menerima Prometheus Registry yang sudah ada dan mengembalikan fungsi pembatalan untuk mematikan server.
func ServeHTTP(addr string, registry *prometheus.Registry) (cancel func()) {
// ...
Berikut adalah contoh penggunaan:
Source code lengkap: github.com/ThreeDotsLabs/watermill/_examples/basic/4-metrics/main.go
// ...
prometheusRegistry, closeMetricsServer := metrics.CreateRegistryAndServeHTTP(*metricsAddr)
defer closeMetricsServer()
// Kami meninggalkan namespace dan subsistem kosong
metricsBuilder := metrics.NewPrometheusMetricsBuilder(prometheusRegistry, "", "")
metricsBuilder.AddPrometheusRouterMetrics(router)
// ...
Contoh Aplikasi
Untuk memahami bagaimana dasbor bekerja dalam praktek, Anda dapat merujuk ke contoh metrik.
Ikuti petunjuk di README contoh untuk menjalankannya dan tambahkan sumber data Prometheus ke Grafana.
Dasbor Grafana
Kami telah menyiapkan sebuah dasbor Grafana untuk digunakan dengan implementasi metrik sebelumnya. Ini menyediakan informasi dasar tentang throughput, tingkat kegagalan, dan durasi penerbitan/pemrosesan.
Jika Anda ingin melihat dasbor ini secara lokal, Anda dapat menggunakan contoh aplikasi.
Untuk informasi lebih lanjut mengenai metrik-metrik yang diekspor ke Prometheus, lihat Metrik yang Diekspor.
Mengimpor Dasbor
Untuk mengimpor dasbor Grafana, pilih Dashboard/Kelola dari menu kiri, lalu klik +Impor
.
Masukkan URL dasbor https://grafana.com/dashboards/9777 (atau hanya ID, 9777), lalu klik Muat.
Kemudian pilih sumber data Prometheus yang digunakan untuk mengambil endpoint /metrics
. Klik Impor
dan Anda selesai!
Metrik yang diekspor
Berikut adalah daftar semua metrik yang terdaftar dalam registri Prometheus oleh PrometheusMetricsBuilder
.
Untuk informasi lebih lanjut mengenai jenis metrik Prometheus, silakan lihat dokumentasi Prometheus.
Objek | Metrik | Deskripsi | Label/Nilai |
---|---|---|---|
Subscriber | subscriber_messages_received_total |
Counter Prometheus. Menghitung jumlah pesan yang diterima oleh seorang subscriber. | acked adalah "acked" atau "nacked". |
Jika subscriber beroperasi dalam suatu handler, atur nama_handler ; jika tidak, " |
|||
nama_subscriber mengidentifikasi subscriber. Jika mengimplementasikan antarmuka fmt.Stringer , itu adalah hasil dari String() ; jika tidak, itu adalah package.structName . |
|||
Handler | handler_execution_time_seconds |
Histogram Prometheus. Merekam waktu eksekusi fungsi handler yang dibungkus oleh middleware. | nama_handler adalah nama handler. |
sukses adalah "true" atau "false", tergantung apakah fungsi handler yang dibungkus mengembalikan kesalahan. |
|||
Publisher | publish_time_seconds |
Histogram Prometheus. Merekam waktu eksekusi fungsi publish dari publisher yang dihiasi. | sukses adalah "true" atau "false", tergantung apakah publisher yang dihiasi mengembalikan kesalahan. |
Jika publisher beroperasi dalam suatu handler, atur nama_handler ; jika tidak, " |
|||
nama_publisher mengidentifikasi publisher. Jika mengimplementasikan antarmuka fmt.Stringer , itu adalah hasil dari String() ; jika tidak, itu adalah package.structName . |
Selain itu, setiap metrik memiliki label node
yang disediakan oleh Prometheus, dengan nilainya sesuai dengan contoh sumber metrik, dan sebuah job
yang ditetapkan sebagai nama pekerjaan dalam berkas konfigurasi Prometheus.
Catatan: Seperti yang disebutkan di atas, penggunaan namespace
atau subsystem
yang tidak kosong akan mengakibatkan awalan nama metrik. Anda mungkin perlu membuat penyesuaian yang sesuai, seperti dalam definisi panel dari dasbor Grafana.
Kustomisasi
Jika Anda merasa ada metrik tertentu yang terlewat, Anda dapat dengan mudah memperluas implementasi dasar ini. Cara terbaik adalah menggunakan registri Prometheus yang digunakan dengan metode ServeHTTP
dan mendaftarkan metrik sesuai dengan dokumentasi klien Prometheus di sini.
Metode yang ringkas untuk memperbarui metrik-metrik ini adalah dengan menggunakan dekorator. Kode sumber lengkap dapat ditemukan di github.com/ThreeDotsLabs/watermill/message/decorator.go.
// ...
// MessageTransformSubscriberDecorator membuat decorator subscriber yang memanggil fungsi transform pada setiap pesan yang dilewatkan melalui subscriber.
func MessageTransformSubscriberDecorator(transform func(*Message)) SubscriberDecorator {
if transform == nil {
panic("fungsi transform nil")
}
return func(sub Subscriber) (Subscriber, error) {
return &messageTransformSubscriberDecorator{
sub: sub,
transform: transform,
}, nil
}
}
// MessageTransformPublisherDecorator membuat decorator publisher yang memanggil fungsi transform pada setiap pesan yang dilewatkan melalui publisher.
func MessageTransformPublisherDecorator(transform func(*Message)) PublisherDecorator {
if transform == nil {
panic("fungsi transform nil")
}
return func(pub Publisher) (Publisher, error) {
return &messageTransformPublisherDecorator{
Publisher: pub,
transform: transform,
}, nil
}
}
type messageTransformSubscriberDecorator struct {
// ...
Dan/atau middleware dalam router.
Metode yang lebih sederhana adalah dengan memperbarui metrik yang diperlukan hanya dalam fungsi handler.