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  }