Add metrics support for Azure & GCS Gateway (#8954)

We added support for caching and S3 related metrics in #8591. As
a continuation, it would be helpful to add support for Azure & GCS
gateway related metrics as well.
This commit is contained in:
Nitish Tiwari 2020-02-11 21:08:01 +05:30 committed by GitHub
parent 6b1f2fc133
commit 63be4709b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 46 deletions

View file

@ -417,3 +417,32 @@ func gatewayHandleEnvVars() {
}
}
}
// shouldMeterRequest checks whether incoming request should be added to prometheus gateway metrics
func shouldMeterRequest(req *http.Request) bool {
return !(guessIsBrowserReq(req) || guessIsHealthCheckReq(req) || guessIsMetricsReq(req))
}
// MetricsTransport is a custom wrapper around Transport to track metrics
type MetricsTransport struct {
Transport *http.Transport
Metrics *Metrics
}
// RoundTrip implements the RoundTrip method for MetricsTransport
func (m MetricsTransport) RoundTrip(r *http.Request) (*http.Response, error) {
metered := shouldMeterRequest(r)
if metered && (r.Method == http.MethodGet || r.Method == http.MethodHead) {
m.Metrics.IncRequests(r.Method)
m.Metrics.IncBytesSent(r.ContentLength)
}
// Make the request to the server.
resp, err := m.Transport.RoundTrip(r)
if err != nil {
return nil, err
}
if metered && (r.Method == http.MethodGet || r.Method == http.MethodHead) {
m.Metrics.IncBytesReceived(resp.ContentLength)
}
return resp, nil
}

View file

@ -146,7 +146,14 @@ func (g *Azure) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, erro
return &azureObjects{}, err
}
httpClient := &http.Client{Transport: minio.NewCustomHTTPTransport()}
metrics := minio.NewMetrics()
t := &minio.MetricsTransport{
Transport: minio.NewCustomHTTPTransport(),
Metrics: metrics,
}
httpClient := &http.Client{Transport: t}
userAgent := fmt.Sprintf("APN/1.0 MinIO/1.0 MinIO/%s", minio.Version)
pipeline := azblob.NewPipeline(credential, azblob.PipelineOptions{
@ -168,6 +175,7 @@ func (g *Azure) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, erro
endpoint: endpointURL.String(),
httpClient: httpClient,
client: client,
metrics: metrics,
}, nil
}
@ -357,6 +365,7 @@ type azureObjects struct {
minio.GatewayUnsupported
endpoint string
httpClient *http.Client
metrics *minio.Metrics
client azblob.ServiceURL // Azure sdk client
}
@ -460,6 +469,11 @@ func parseAzurePart(metaPartFileName, prefix string) (partID int, err error) {
return
}
// GetMetrics returns this gateway's metrics
func (a *azureObjects) GetMetrics(ctx context.Context) (*minio.Metrics, error) {
return a.metrics, nil
}
// Shutdown - save any gateway metadata to disk
// if necessary and reload upon next restart.
func (a *azureObjects) Shutdown(ctx context.Context) error {

View file

@ -179,6 +179,13 @@ func (g *GCS) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, error)
}
}
metrics := minio.NewMetrics()
t := &minio.MetricsTransport{
Transport: minio.NewCustomHTTPTransport(),
Metrics: metrics,
}
// Initialize a GCS client.
// Send user-agent in this format for Google to obtain usage insights while participating in the
// Google Cloud Technology Partners (https://cloud.google.com/partners/)
@ -190,8 +197,9 @@ func (g *GCS) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, error)
gcs := &gcsGateway{
client: client,
projectID: g.projectID,
metrics: metrics,
httpClient: &http.Client{
Transport: minio.NewCustomHTTPTransport(),
Transport: t,
},
}
@ -333,6 +341,7 @@ type gcsGateway struct {
minio.GatewayUnsupported
client *storage.Client
httpClient *http.Client
metrics *minio.Metrics
projectID string
}
@ -349,6 +358,11 @@ func gcsParseProjectID(credsFile string) (projectID string, err error) {
return googleCreds[gcsProjectIDKey], err
}
// GetMetrics returns this gateway's metrics
func (l *gcsGateway) GetMetrics(ctx context.Context) (*minio.Metrics, error) {
return l.metrics, nil
}
// Cleanup old files in minio.sys.tmp of the given bucket.
func (l *gcsGateway) CleanupGCSMinioSysTmpBucket(ctx context.Context, bucket string) {
it := l.client.Bucket(bucket).Objects(ctx, &storage.Query{Prefix: minio.GatewayMinioSysTmp, Versions: false})

View file

@ -106,11 +106,9 @@ func (g *S3) Name() string {
const letterBytes = "abcdefghijklmnopqrstuvwxyz01234569"
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
minioReservedBucket = "minio"
minioReservedBucketPath = minio.SlashSeparator + minioReservedBucket
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
// randString generates random names and prepends them with a known prefix.
@ -158,32 +156,6 @@ var defaultAWSCredProviders = []credentials.Provider{
&credentials.EnvMinio{},
}
type metricsTransport struct {
transport *http.Transport
metrics *minio.Metrics
}
func (s metricsTransport) RoundTrip(r *http.Request) (*http.Response, error) {
isS3Request := func() bool {
return !(minio.HasPrefix(r.URL.Path, minioReservedBucketPath) ||
minio.HasSuffix(r.URL.Path, ".js") || strings.Contains(r.URL.Path, "favicon.ico") ||
strings.Contains(r.URL.Path, ".html"))
}
if isS3Request() && (r.Method == http.MethodGet || r.Method == http.MethodHead) {
s.metrics.IncRequests(r.Method)
s.metrics.IncBytesSent(r.ContentLength)
}
// Make the request to the server.
resp, err := s.transport.RoundTrip(r)
if err != nil {
return nil, err
}
if isS3Request() && (r.Method == http.MethodGet || r.Method == http.MethodHead) {
s.metrics.IncBytesReceived(resp.ContentLength)
}
return resp, nil
}
// newS3 - Initializes a new client by auto probing S3 server signature.
func newS3(urlStr string) (*miniogo.Core, error) {
if urlStr == "" {
@ -237,9 +209,9 @@ func (g *S3) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, error)
metrics := minio.NewMetrics()
t := &metricsTransport{
transport: minio.NewCustomHTTPTransport(),
metrics: metrics,
t := &minio.MetricsTransport{
Transport: minio.NewCustomHTTPTransport(),
Metrics: metrics,
}
// Set custom transport

View file

@ -272,12 +272,12 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
)
}
if globalIsGateway && globalGatewayName == "s3" {
if globalIsGateway && (globalGatewayName == "s3" || globalGatewayName == "azure" || globalGatewayName == "gcs") {
m, _ := globalObjectAPI.GetMetrics(context.Background())
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName("gateway", globalGatewayName, "bytes_received"),
"Total number of bytes received by current MinIO S3 Gateway from AWS S3",
"Total number of bytes received by current MinIO Gateway "+globalGatewayName+" backend",
nil, nil),
prometheus.CounterValue,
float64(m.GetBytesReceived()),
@ -285,7 +285,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName("gateway", globalGatewayName, "bytes_sent"),
"Total number of bytes sent by current MinIO S3 Gateway to AWS S3",
"Total number of bytes sent by current MinIO Gateway to "+globalGatewayName+" backend",
nil, nil),
prometheus.CounterValue,
float64(m.GetBytesSent()),
@ -294,7 +294,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName("gateway", globalGatewayName, "requests"),
"Total number of requests made to AWS S3 by current MinIO S3 Gateway",
"Total number of requests made to "+globalGatewayName+" by current MinIO Gateway",
[]string{"method"}, nil),
prometheus.CounterValue,
float64(s.Get.Load()),
@ -303,7 +303,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName("gateway", globalGatewayName, "requests"),
"Total number of requests made to AWS S3 by current MinIO S3 Gateway",
"Total number of requests made to "+globalGatewayName+" by current MinIO Gateway",
[]string{"method"}, nil),
prometheus.CounterValue,
float64(s.Head.Load()),

View file

@ -147,13 +147,15 @@ MinIO Gateway instances enabled with Disk-Caching expose caching related metrics
- `cache_hits_total`: Total number of cache hits.
- `cache_misses_total`: Total number of cache misses.
### S3 Gateway & Cache specific metrics
### Gateway & Cache specific metrics
MinIO S3 Gateway instance exposes metrics related to Gateway communication with AWS S3.
MinIO Gateway instance exposes metrics related to Gateway communication with the cloud backend (S3, Azure & GCS Gateway).
- `gateway_s3_requests`: Total number of GET & HEAD requests made to AWS S3. This metrics has a label `method` that identifies GET & HEAD Requests.
- `gateway_s3_bytes_sent`: Total number of bytes sent to AWS S3 (in GET & HEAD Requests).
- `gateway_s3_bytes_received`: Total number of bytes received from AWS S3 (in GET & HEAD Requests).
- `gateway_<gateway_type>_requests`: Total number of GET & HEAD requests made to cloud backend. This metrics has a label `method` that identifies GET & HEAD Requests.
- `gateway_<gateway_type>_bytes_sent`: Total number of bytes sent to cloud backend (in GET & HEAD Requests).
- `gateway_<gateway_type>_bytes_received`: Total number of bytes received from cloud backend (in GET & HEAD Requests).
Note that this is currently only support for Azure, S3 and GCS Gateway.
## Migration guide for the new set of metrics