190 lines
6.1 KiB
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)
|
|
}
|
|
}
|