github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/metrics-v3-api.go (about) 1 // Copyright (c) 2015-2024 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "context" 22 ) 23 24 const ( 25 apiRejectedAuthTotal MetricName = "rejected_auth_total" 26 apiRejectedHeaderTotal MetricName = "rejected_header_total" 27 apiRejectedTimestampTotal MetricName = "rejected_timestamp_total" 28 apiRejectedInvalidTotal MetricName = "rejected_invalid_total" 29 30 apiRequestsWaitingTotal MetricName = "waiting_total" 31 apiRequestsIncomingTotal MetricName = "incoming_total" 32 33 apiRequestsInFlightTotal MetricName = "inflight_total" 34 apiRequestsTotal MetricName = "total" 35 apiRequestsErrorsTotal MetricName = "errors_total" 36 apiRequests5xxErrorsTotal MetricName = "5xx_errors_total" 37 apiRequests4xxErrorsTotal MetricName = "4xx_errors_total" 38 apiRequestsCanceledTotal MetricName = "canceled_total" 39 40 apiRequestsTTFBSecondsDistribution MetricName = "ttfb_seconds_distribution" 41 42 apiTrafficSentBytes MetricName = "traffic_sent_bytes" 43 apiTrafficRecvBytes MetricName = "traffic_received_bytes" 44 ) 45 46 var ( 47 apiRejectedAuthTotalMD = NewCounterMD(apiRejectedAuthTotal, 48 "Total number of requests rejected for auth failure", "type") 49 apiRejectedHeaderTotalMD = NewCounterMD(apiRejectedHeaderTotal, 50 "Total number of requests rejected for invalid header", "type") 51 apiRejectedTimestampTotalMD = NewCounterMD(apiRejectedTimestampTotal, 52 "Total number of requests rejected for invalid timestamp", "type") 53 apiRejectedInvalidTotalMD = NewCounterMD(apiRejectedInvalidTotal, 54 "Total number of invalid requests", "type") 55 56 apiRequestsWaitingTotalMD = NewGaugeMD(apiRequestsWaitingTotal, 57 "Total number of requests in the waiting queue", "type") 58 apiRequestsIncomingTotalMD = NewGaugeMD(apiRequestsIncomingTotal, 59 "Total number of incoming requests", "type") 60 61 apiRequestsInFlightTotalMD = NewGaugeMD(apiRequestsInFlightTotal, 62 "Total number of requests currently in flight", "name", "type") 63 apiRequestsTotalMD = NewCounterMD(apiRequestsTotal, 64 "Total number of requests", "name", "type") 65 apiRequestsErrorsTotalMD = NewCounterMD(apiRequestsErrorsTotal, 66 "Total number of requests with (4xx and 5xx) errors", "name", "type") 67 apiRequests5xxErrorsTotalMD = NewCounterMD(apiRequests5xxErrorsTotal, 68 "Total number of requests with 5xx errors", "name", "type") 69 apiRequests4xxErrorsTotalMD = NewCounterMD(apiRequests4xxErrorsTotal, 70 "Total number of requests with 4xx errors", "name", "type") 71 apiRequestsCanceledTotalMD = NewCounterMD(apiRequestsCanceledTotal, 72 "Total number of requests canceled by the client", "name", "type") 73 74 apiRequestsTTFBSecondsDistributionMD = NewCounterMD(apiRequestsTTFBSecondsDistribution, 75 "Distribution of time to first byte across API calls", "name", "type", "le") 76 77 apiTrafficSentBytesMD = NewCounterMD(apiTrafficSentBytes, 78 "Total number of bytes sent", "type") 79 apiTrafficRecvBytesMD = NewCounterMD(apiTrafficRecvBytes, 80 "Total number of bytes received", "type") 81 ) 82 83 // loadAPIRequestsHTTPMetrics - reads S3 HTTP metrics. 84 // 85 // This is a `MetricsLoaderFn`. 86 // 87 // This includes node level S3 HTTP metrics. 88 // 89 // This function currently ignores `opts`. 90 func loadAPIRequestsHTTPMetrics(ctx context.Context, m MetricValues, _ *metricsCache) error { 91 // Collect node level S3 HTTP metrics. 92 httpStats := globalHTTPStats.toServerHTTPStats(false) 93 94 // Currently we only collect S3 API related stats, so we set the "type" 95 // label to "s3". 96 97 m.Set(apiRejectedAuthTotal, float64(httpStats.TotalS3RejectedAuth), "type", "s3") 98 m.Set(apiRejectedTimestampTotal, float64(httpStats.TotalS3RejectedTime), "type", "s3") 99 m.Set(apiRejectedHeaderTotal, float64(httpStats.TotalS3RejectedHeader), "type", "s3") 100 m.Set(apiRejectedInvalidTotal, float64(httpStats.TotalS3RejectedInvalid), "type", "s3") 101 m.Set(apiRequestsWaitingTotal, float64(httpStats.S3RequestsInQueue), "type", "s3") 102 m.Set(apiRequestsIncomingTotal, float64(httpStats.S3RequestsIncoming), "type", "s3") 103 104 for name, value := range httpStats.CurrentS3Requests.APIStats { 105 m.Set(apiRequestsInFlightTotal, float64(value), "name", name, "type", "s3") 106 } 107 for name, value := range httpStats.TotalS3Requests.APIStats { 108 m.Set(apiRequestsTotal, float64(value), "name", name, "type", "s3") 109 } 110 for name, value := range httpStats.TotalS3Errors.APIStats { 111 m.Set(apiRequestsErrorsTotal, float64(value), "name", name, "type", "s3") 112 } 113 for name, value := range httpStats.TotalS35xxErrors.APIStats { 114 m.Set(apiRequests5xxErrorsTotal, float64(value), "name", name, "type", "s3") 115 } 116 for name, value := range httpStats.TotalS34xxErrors.APIStats { 117 m.Set(apiRequests4xxErrorsTotal, float64(value), "name", name, "type", "s3") 118 } 119 for name, value := range httpStats.TotalS3Canceled.APIStats { 120 m.Set(apiRequestsCanceledTotal, float64(value), "name", name, "type", "s3") 121 } 122 return nil 123 } 124 125 // loadAPIRequestsTTFBMetrics - loads S3 TTFB metrics. 126 // 127 // This is a `MetricsLoaderFn`. 128 func loadAPIRequestsTTFBMetrics(ctx context.Context, m MetricValues, _ *metricsCache) error { 129 renameLabels := map[string]string{"api": "name"} 130 m.SetHistogram(apiRequestsTTFBSecondsDistribution, httpRequestsDuration, renameLabels, nil, 131 "type", "s3") 132 return nil 133 } 134 135 // loadAPIRequestsNetworkMetrics - loads S3 network metrics. 136 // 137 // This is a `MetricsLoaderFn`. 138 func loadAPIRequestsNetworkMetrics(ctx context.Context, m MetricValues, _ *metricsCache) error { 139 connStats := globalConnStats.toServerConnStats() 140 m.Set(apiTrafficSentBytes, float64(connStats.s3OutputBytes), "type", "s3") 141 m.Set(apiTrafficRecvBytes, float64(connStats.s3InputBytes), "type", "s3") 142 return nil 143 } 144 145 // Metric Descriptions for bucket level S3 metrics. 146 var ( 147 apiBucketTrafficSentBytesMD = NewCounterMD(apiTrafficSentBytes, 148 "Total number of bytes received for a bucket", "bucket", "type") 149 apiBucketTrafficRecvBytesMD = NewCounterMD(apiTrafficRecvBytes, 150 "Total number of bytes sent for a bucket", "bucket", "type") 151 152 apiBucketRequestsInFlightMD = NewGaugeMD(apiRequestsInFlightTotal, 153 "Total number of requests currently in flight for a bucket", "bucket", "name", "type") 154 apiBucketRequestsTotalMD = NewCounterMD(apiRequestsTotal, 155 "Total number of requests for a bucket", "bucket", "name", "type") 156 apiBucketRequestsCanceledMD = NewCounterMD(apiRequestsCanceledTotal, 157 "Total number of requests canceled by the client for a bucket", "bucket", "name", "type") 158 apiBucketRequests4xxErrorsMD = NewCounterMD(apiRequests4xxErrorsTotal, 159 "Total number of requests with 4xx errors for a bucket", "bucket", "name", "type") 160 apiBucketRequests5xxErrorsMD = NewCounterMD(apiRequests5xxErrorsTotal, 161 "Total number of requests with 5xx errors for a bucket", "bucket", "name", "type") 162 163 apiBucketRequestsTTFBSecondsDistributionMD = NewCounterMD(apiRequestsTTFBSecondsDistribution, 164 "Distribution of time to first byte across API calls for a bucket", 165 "bucket", "name", "le", "type") 166 ) 167 168 // loadAPIBucketHTTPMetrics - loads bucket level S3 HTTP metrics. 169 // 170 // This is a `MetricsLoaderFn`. 171 // 172 // This includes bucket level S3 HTTP metrics and S3 network in/out metrics. 173 func loadAPIBucketHTTPMetrics(ctx context.Context, m MetricValues, _ *metricsCache, buckets []string) error { 174 if len(buckets) == 0 { 175 return nil 176 } 177 for bucket, inOut := range globalBucketConnStats.getBucketS3InOutBytes(buckets) { 178 recvBytes := inOut.In 179 if recvBytes > 0 { 180 m.Set(apiTrafficSentBytes, float64(recvBytes), "bucket", bucket, "type", "s3") 181 } 182 sentBytes := inOut.Out 183 if sentBytes > 0 { 184 m.Set(apiTrafficRecvBytes, float64(sentBytes), "bucket", bucket, "type", "s3") 185 } 186 187 httpStats := globalBucketHTTPStats.load(bucket) 188 for k, v := range httpStats.currentS3Requests.Load(false) { 189 m.Set(apiRequestsInFlightTotal, float64(v), "bucket", bucket, "name", k, "type", "s3") 190 } 191 192 for k, v := range httpStats.totalS3Requests.Load(false) { 193 m.Set(apiRequestsTotal, float64(v), "bucket", bucket, "name", k, "type", "s3") 194 } 195 196 for k, v := range httpStats.totalS3Canceled.Load(false) { 197 m.Set(apiRequestsCanceledTotal, float64(v), "bucket", bucket, "name", k, "type", "s3") 198 } 199 200 for k, v := range httpStats.totalS34xxErrors.Load(false) { 201 m.Set(apiRequests4xxErrorsTotal, float64(v), "bucket", bucket, "name", k, "type", "s3") 202 } 203 204 for k, v := range httpStats.totalS35xxErrors.Load(false) { 205 m.Set(apiRequests5xxErrorsTotal, float64(v), "bucket", bucket, "name", k, "type", "s3") 206 } 207 } 208 209 return nil 210 } 211 212 // loadAPIBucketTTFBMetrics - loads bucket S3 TTFB metrics. 213 // 214 // This is a `MetricsLoaderFn`. 215 func loadAPIBucketTTFBMetrics(ctx context.Context, m MetricValues, _ *metricsCache, buckets []string) error { 216 renameLabels := map[string]string{"api": "name"} 217 m.SetHistogram(apiRequestsTTFBSecondsDistribution, bucketHTTPRequestsDuration, renameLabels, 218 buckets, "type", "s3") 219 return nil 220 }