nexo/services/push-proxy/server/metrics.go

190 lines
6.1 KiB
Go

package server
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
const (
metricNotificationsTotalName = "service_notifications_total"
metricSuccessName = "service_success_total"
metricSuccessWithAckName = "service_success_with_ack_total"
metricDeliveredName = "service_delivered_total"
metricFailureName = "service_failure_total"
metricFailureWithReasonName = "service_failure_with_reason_total"
metricRemovalName = "service_removal_total"
metricBadRequestName = "service_bad_request_total"
metricFCMResponseName = "service_fcm_request_duration_seconds"
metricAPNSResponseName = "service_apns_request_duration_seconds"
metricServiceResponseName = "service_request_duration_seconds"
metricNotificationResponseName = "service_notification_duration_seconds"
)
// NewPrometheusHandler returns the http.Handler to expose Prometheus metrics
func NewPrometheusHandler() http.Handler {
return promhttp.Handler()
}
type metrics struct {
metricNotificationsTotal *prometheus.CounterVec
metricSuccess *prometheus.CounterVec
metricSuccessWithAck *prometheus.CounterVec
metricDelivered *prometheus.CounterVec
metricFailure *prometheus.CounterVec
metricFailureWithReason *prometheus.CounterVec
metricRemoval *prometheus.CounterVec
metricBadRequest prometheus.Counter
metricAPNSResponse prometheus.Histogram
metricFCMResponse prometheus.Histogram
metricNotificationResponse *prometheus.HistogramVec
metricServiceResponse prometheus.Histogram
}
// newMetrics initializes the metrics and registers them
func newMetrics() *metrics {
m := &metrics{
metricNotificationsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricNotificationsTotalName,
Help: "Number of notifications sent"},
[]string{"platform", "type"}),
metricSuccess: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricSuccessName,
Help: "Number of push success."},
[]string{"platform", "type"}),
metricSuccessWithAck: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricSuccessWithAckName,
Help: "Number of push success that contains ackId."},
[]string{"platform", "type"},
),
metricDelivered: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricDeliveredName,
Help: "Number of push delivered."},
[]string{"platform", "type"},
),
metricFailure: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricFailureName,
Help: "Number of push errors."},
[]string{"platform", "type"}),
metricFailureWithReason: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricFailureWithReasonName,
Help: "Number of push errors with reasons."},
[]string{"platform", "type", "reason"}),
metricRemoval: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricRemovalName,
Help: "Number of device token errors."},
[]string{"platform", "reason"}),
metricBadRequest: prometheus.NewCounter(prometheus.CounterOpts{
Name: metricBadRequestName,
Help: "Request to push proxy was a bad request",
}),
metricAPNSResponse: prometheus.NewHistogram(prometheus.HistogramOpts{
Name: metricAPNSResponseName,
Help: "Request latency distribution",
}),
metricFCMResponse: prometheus.NewHistogram(prometheus.HistogramOpts{
Name: metricFCMResponseName,
Help: "Request latency distribution",
}),
metricNotificationResponse: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Name: metricNotificationResponseName,
Help: "Notifiction request latency distribution"},
[]string{"platform"}),
metricServiceResponse: prometheus.NewHistogram(prometheus.HistogramOpts{
Name: metricServiceResponseName,
Help: "Request latency distribution",
}),
}
prometheus.MustRegister(
m.metricNotificationsTotal,
m.metricSuccess,
m.metricSuccessWithAck,
m.metricFailure,
m.metricFailureWithReason,
m.metricRemoval,
m.metricBadRequest,
m.metricAPNSResponse,
m.metricFCMResponse,
m.metricServiceResponse,
m.metricNotificationResponse,
)
return m
}
func (m *metrics) shutdown() {
func(cs ...prometheus.Collector) {
for _, c := range cs {
prometheus.Unregister(c)
}
}(
m.metricNotificationsTotal,
m.metricSuccess,
m.metricSuccessWithAck,
m.metricFailure,
m.metricFailureWithReason,
m.metricRemoval,
m.metricBadRequest,
m.metricAPNSResponse,
m.metricFCMResponse,
m.metricServiceResponse,
m.metricNotificationResponse,
)
}
func (m *metrics) incrementNotificationTotal(platform, pushType string) {
m.metricNotificationsTotal.WithLabelValues(platform, pushType).Inc()
}
func (m *metrics) incrementSuccess(platform, pushType string) {
m.metricSuccess.WithLabelValues(platform, pushType).Inc()
}
func (m *metrics) incrementSuccessWithAck(platform, pushType string) {
m.incrementSuccess(platform, pushType)
m.metricSuccessWithAck.WithLabelValues(platform, pushType).Inc()
}
func (m *metrics) incrementDelivered(platform, pushType string) {
m.metricDelivered.WithLabelValues(platform, pushType).Inc()
}
func (m *metrics) incrementFailure(platform, pushType, reason string) {
m.metricFailure.WithLabelValues(platform, pushType).Inc()
if reason != "" {
m.metricFailureWithReason.WithLabelValues(platform, pushType, reason).Inc()
}
}
func (m *metrics) incrementRemoval(platform, pushType, reason string) {
m.metricRemoval.WithLabelValues(platform, reason).Inc()
m.incrementFailure(platform, pushType, reason)
}
func (m *metrics) incrementBadRequest() {
m.metricBadRequest.Inc()
}
func (m *metrics) observeAPNSResponse(dur float64) {
m.metricAPNSResponse.Observe(dur)
}
func (m *metrics) observeFCMResponse(dur float64) {
m.metricFCMResponse.Observe(dur)
}
func (m *metrics) observeServiceResponse(dur float64) {
m.metricServiceResponse.Observe(dur)
}
func (m *metrics) observerNotificationResponse(platform string, dur float64) {
m.metricNotificationResponse.WithLabelValues(platform).Observe(dur)
switch platform {
case PushNotifyApple:
m.observeAPNSResponse(dur)
case PushNotifyAndroid:
m.observeFCMResponse(dur)
}
}