harbor/src/server/middleware/metric/metric.go

81 lines
2.2 KiB
Go

package metric
import (
"context"
"net/http"
"strconv"
"time"
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/lib/metric"
)
// ContextOpIDKey ...
type contextOpIDKey struct{}
const (
// CatalogOperationID ...
CatalogOperationID = "v2_catalog"
// ListTagOperationID ...
ListTagOperationID = "v2_tags"
// ManifestOperationID ...
ManifestOperationID = "v2_manifest"
// BlobsOperationID ...
BlobsOperationID = "v2_blob"
// BlobsUploadOperationID ...
BlobsUploadOperationID = "v2_blob_upload"
// ReferrersOperationID ...
ReferrersOperationID = "v2_referrers"
// OthersOperationID ...
OthersOperationID = "v2_others"
)
// SetMetricOpID used to set operation ID for metrics
func SetMetricOpID(ctx context.Context, value string) {
if config.Metric().Enabled {
v := ctx.Value(contextOpIDKey{}).(*string)
*v = value
}
}
func instrumentHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
metric.TotalInFlightGauge.Inc()
defer metric.TotalInFlightGauge.Dec()
now, rc, op := time.Now(), lib.NewResponseRecorder(w), ""
ctx := context.WithValue(r.Context(), contextOpIDKey{}, &op)
next.ServeHTTP(rc, r.WithContext(ctx))
if len(op) == 0 {
// From swagger's perspective the operation of this legacy URL is unknown
op = "unknown"
}
metric.TotalReqDurSummary.WithLabelValues(r.Method, op).Observe(time.Since(now).Seconds())
metric.TotalReqCnt.WithLabelValues(r.Method, strconv.Itoa(rc.StatusCode), op).Inc()
})
}
func transparentHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
})
}
// Middleware returns a middleware for handling requests
func Middleware() func(http.Handler) http.Handler {
if config.Metric().Enabled {
return instrumentHandler
}
return transparentHandler
}
// InjectOpIDMiddleware returns a middleware used for injecting operations ID
func InjectOpIDMiddleware(opID string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
SetMetricOpID(r.Context(), opID)
next.ServeHTTP(w, r)
})
}
}