diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 07996d33c..195c7c9ef 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -263,6 +263,7 @@ type ServerHTTPStats struct { CurrentS3Requests ServerHTTPAPIStats `json:"currentS3Requests"` TotalS3Requests ServerHTTPAPIStats `json:"totalS3Requests"` TotalS3Errors ServerHTTPAPIStats `json:"totalS3Errors"` + TotalS3Canceled ServerHTTPAPIStats `json:"totalS3Canceled"` } // ServerInfoData holds storage, connections and other diff --git a/cmd/http-stats.go b/cmd/http-stats.go index 7065a95c1..a97aa11eb 100644 --- a/cmd/http-stats.go +++ b/cmd/http-stats.go @@ -17,6 +17,7 @@ package cmd import ( + "context" "net/http" "strings" "sync" @@ -141,6 +142,7 @@ type HTTPStats struct { currentS3Requests HTTPAPIStats totalS3Requests HTTPAPIStats totalS3Errors HTTPAPIStats + totalS3Canceled HTTPAPIStats } func (st *HTTPStats) addRequestsInQueue(i int32) { @@ -160,6 +162,9 @@ func (st *HTTPStats) toServerHTTPStats() ServerHTTPStats { serverStats.TotalS3Errors = ServerHTTPAPIStats{ APIStats: st.totalS3Errors.Load(), } + serverStats.TotalS3Canceled = ServerHTTPAPIStats{ + APIStats: st.totalS3Canceled.Load(), + } return serverStats } @@ -175,6 +180,13 @@ func (st *HTTPStats) updateStats(api string, r *http.Request, w *logger.Response if !successReq && w.StatusCode != 0 { st.totalS3Errors.Inc(api) } + select { + case <-r.Context().Done(): + if err := r.Context().Err(); err == context.Canceled { + st.totalS3Canceled.Inc(api) + } + default: + } } // Increment the prometheus http request response histogram with appropriate label diff --git a/cmd/logger/audit.go b/cmd/logger/audit.go index 5ee599007..c7b3f06ca 100644 --- a/cmd/logger/audit.go +++ b/cmd/logger/audit.go @@ -49,7 +49,7 @@ type ResponseWriter struct { } // NewResponseWriter - returns a wrapped response writer to trap -// http status codes for auditiing purposes. +// http status codes for auditing purposes. func NewResponseWriter(w http.ResponseWriter) *ResponseWriter { return &ResponseWriter{ ResponseWriter: w, diff --git a/cmd/metrics-v2.go b/cmd/metrics-v2.go index 73149a0ed..de19c8385 100644 --- a/cmd/metrics-v2.go +++ b/cmd/metrics-v2.go @@ -74,6 +74,7 @@ type MetricName string const ( total MetricName = "total" errorsTotal MetricName = "error_total" + canceledTotal MetricName = "canceled_total" healTotal MetricName = "heal_total" hitsTotal MetricName = "hits_total" inflightTotal MetricName = "inflight_total" @@ -495,6 +496,15 @@ func getS3RequestsErrorsMD() MetricDescription { Type: counterMetric, } } +func getS3RequestsCanceledMD() MetricDescription { + return MetricDescription{ + Namespace: s3MetricNamespace, + Subsystem: requestsSubsystem, + Name: canceledTotal, + Help: "Total number S3 requests that were canceled from the client while processing", + Type: counterMetric, + } +} func getCacheHitsTotalMD() MetricDescription { return MetricDescription{ Namespace: minioNamespace, @@ -576,6 +586,7 @@ func getHealObjectsHealTotalMD() MetricDescription { Type: gaugeMetric, } } + func getHealObjectsFailTotalMD() MetricDescription { return MetricDescription{ Namespace: healMetricNamespace, @@ -1077,6 +1088,13 @@ func getHTTPMetrics() MetricsGroup { VariableLabels: map[string]string{"api": api}, }) } + for api, value := range httpStats.TotalS3Canceled.APIStats { + metrics = append(metrics, Metric{ + Description: getS3RequestsCanceledMD(), + Value: float64(value), + VariableLabels: map[string]string{"api": api}, + }) + } return }, } diff --git a/cmd/metrics.go b/cmd/metrics.go index 1184005b6..19d138c16 100644 --- a/cmd/metrics.go +++ b/cmd/metrics.go @@ -372,6 +372,18 @@ func httpMetricsPrometheus(ch chan<- prometheus.Metric) { api, ) } + + for api, value := range httpStats.TotalS3Canceled.APIStats { + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(s3Namespace, "canceled", "total"), + "Total number of client canceled s3 request in current MinIO server instance", + []string{"api"}, nil), + prometheus.CounterValue, + float64(value), + api, + ) + } } // collects network metrics for MinIO server in Prometheus specific format