Skip to content

Commit

Permalink
add http metrics (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
iCell authored Jan 27, 2023
1 parent 009a7ad commit be75226
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 8 deletions.
106 changes: 106 additions & 0 deletions metrics/http_metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package metrics

import (
"github.com/prometheus/client_golang/prometheus"
"time"
)

const (
requestStartedKey = "request_started"
requestDurationSecondsKey = "request_duration_seconds"
requestSucceededTotalKey = "request_succeeded_total"
requestClientErrTotalKey = "request_client_error_total"
requestServerErrTotalKey = "request_server_error_total"
)

type HttpServerMetric interface {
Start(labelValues ...string) time.Time
Duration(start time.Time, labelValues ...string)
Success(labelValues ...string)
ServerError(labelValues ...string)
ClientError(labelValues ...string)
}

type httpServerMetric struct {
requestStarted *prometheus.GaugeVec
requestDurationSeconds *prometheus.HistogramVec
requestSucceededTotal *prometheus.CounterVec
requestClientErrTotal *prometheus.CounterVec
requestServerErrTotal *prometheus.CounterVec
}

func NewHttpServerMetric(
namespace string,
labelNames []string,
staticLabels prometheus.Labels,
reg prometheus.Registerer,
) HttpServerMetric {
requestStarted := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Name: requestStartedKey,
Help: "Last Unix time when request started.",
}, labelNames)

requestDurationSeconds := prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespace,
Name: requestDurationSecondsKey,
Help: "Duration of the executions.",
}, labelNames)

requestSucceededTotal := prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Name: requestSucceededTotalKey,
Help: "Total number of the 2xx requests which succeeded.",
}, labelNames)

requestClientErrTotal := prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Name: requestClientErrTotalKey,
Help: "Total number of the 4xx requests.",
}, labelNames)

requestServerErrTotal := prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Name: requestServerErrTotalKey,
Help: "Total number of the 5xx requests.",
}, labelNames)

Register(staticLabels, reg, requestStarted, requestDurationSeconds, requestSucceededTotal, requestClientErrTotal, requestServerErrTotal)

return &httpServerMetric{
requestStarted: requestStarted,
requestDurationSeconds: requestDurationSeconds,
requestSucceededTotal: requestSucceededTotal,
requestClientErrTotal: requestClientErrTotal,
requestServerErrTotal: requestServerErrTotal,
}
}

func (m *httpServerMetric) Start(labelValues ...string) time.Time {
start := time.Now()
m.requestStarted.WithLabelValues(labelValues...).SetToCurrentTime()
return start
}

func (m *httpServerMetric) Duration(start time.Time, labelValues ...string) {
duration := time.Since(start)
m.requestDurationSeconds.WithLabelValues(labelValues...).Observe(duration.Seconds())
}

func (m *httpServerMetric) Success(labelValues ...string) {
m.requestSucceededTotal.WithLabelValues(labelValues...).Inc()
m.requestServerErrTotal.WithLabelValues(labelValues...).Add(0)
m.requestClientErrTotal.WithLabelValues(labelValues...).Add(0)
}

func (m *httpServerMetric) ServerError(labelValues ...string) {
m.requestSucceededTotal.WithLabelValues(labelValues...).Add(0)
m.requestServerErrTotal.WithLabelValues(labelValues...).Inc()
m.requestClientErrTotal.WithLabelValues(labelValues...).Add(0)
}

func (m *httpServerMetric) ClientError(labelValues ...string) {
m.requestSucceededTotal.WithLabelValues(labelValues...).Add(0)
m.requestServerErrTotal.WithLabelValues(labelValues...).Add(0)
m.requestClientErrTotal.WithLabelValues(labelValues...).Inc()
}
15 changes: 7 additions & 8 deletions middleware/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const labelPath = "path"
const labelMethod = "method"

func MetricsMiddleware(namespace string, labels prometheus.Labels, reg prometheus.Registerer) gin.HandlerFunc {
perfMetric := metrics.NewPerformanceMetric(namespace, []string{labelPath, labelMethod}, labels, reg)
perfMetric := metrics.NewHttpServerMetric(namespace, []string{labelPath, labelMethod}, labels, reg)
return func(c *gin.Context) {
path := c.FullPath()
method := c.Request.Method
Expand All @@ -29,14 +29,13 @@ func MetricsMiddleware(namespace string, labels prometheus.Labels, reg prometheu
perfMetric.Duration(startTime, labelValues...)

statusCode := c.Writer.Status()
if successfulHttpStatusCode(statusCode) {
switch {
case 200 <= statusCode && statusCode <= 299:
perfMetric.Success(labelValues...)
} else {
perfMetric.Failure(labelValues...)
case 500 <= statusCode && statusCode <= 599:
perfMetric.ServerError(labelValues...)
case 400 <= statusCode && statusCode <= 499:
perfMetric.ClientError(labelValues...)
}
}
}

func successfulHttpStatusCode(statusCode int) bool {
return 200 <= statusCode && statusCode < 300
}

0 comments on commit be75226

Please sign in to comment.