mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
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:
parent
6b1f2fc133
commit
63be4709b7
@ -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
|
||||||
|
}
|
||||||
|
@ -146,7 +146,14 @@ func (g *Azure) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, erro
|
|||||||
return &azureObjects{}, err
|
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)
|
userAgent := fmt.Sprintf("APN/1.0 MinIO/1.0 MinIO/%s", minio.Version)
|
||||||
|
|
||||||
pipeline := azblob.NewPipeline(credential, azblob.PipelineOptions{
|
pipeline := azblob.NewPipeline(credential, azblob.PipelineOptions{
|
||||||
@ -168,6 +175,7 @@ func (g *Azure) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, erro
|
|||||||
endpoint: endpointURL.String(),
|
endpoint: endpointURL.String(),
|
||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
client: client,
|
client: client,
|
||||||
|
metrics: metrics,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +365,7 @@ type azureObjects struct {
|
|||||||
minio.GatewayUnsupported
|
minio.GatewayUnsupported
|
||||||
endpoint string
|
endpoint string
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
metrics *minio.Metrics
|
||||||
client azblob.ServiceURL // Azure sdk client
|
client azblob.ServiceURL // Azure sdk client
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,6 +469,11 @@ func parseAzurePart(metaPartFileName, prefix string) (partID int, err error) {
|
|||||||
return
|
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
|
// Shutdown - save any gateway metadata to disk
|
||||||
// if necessary and reload upon next restart.
|
// if necessary and reload upon next restart.
|
||||||
func (a *azureObjects) Shutdown(ctx context.Context) error {
|
func (a *azureObjects) Shutdown(ctx context.Context) error {
|
||||||
|
@ -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.
|
// Initialize a GCS client.
|
||||||
// Send user-agent in this format for Google to obtain usage insights while participating in the
|
// 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/)
|
// 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{
|
gcs := &gcsGateway{
|
||||||
client: client,
|
client: client,
|
||||||
projectID: g.projectID,
|
projectID: g.projectID,
|
||||||
|
metrics: metrics,
|
||||||
httpClient: &http.Client{
|
httpClient: &http.Client{
|
||||||
Transport: minio.NewCustomHTTPTransport(),
|
Transport: t,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,6 +341,7 @@ type gcsGateway struct {
|
|||||||
minio.GatewayUnsupported
|
minio.GatewayUnsupported
|
||||||
client *storage.Client
|
client *storage.Client
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
metrics *minio.Metrics
|
||||||
projectID string
|
projectID string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,6 +358,11 @@ func gcsParseProjectID(credsFile string) (projectID string, err error) {
|
|||||||
return googleCreds[gcsProjectIDKey], err
|
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.
|
// Cleanup old files in minio.sys.tmp of the given bucket.
|
||||||
func (l *gcsGateway) CleanupGCSMinioSysTmpBucket(ctx context.Context, bucket string) {
|
func (l *gcsGateway) CleanupGCSMinioSysTmpBucket(ctx context.Context, bucket string) {
|
||||||
it := l.client.Bucket(bucket).Objects(ctx, &storage.Query{Prefix: minio.GatewayMinioSysTmp, Versions: false})
|
it := l.client.Bucket(bucket).Objects(ctx, &storage.Query{Prefix: minio.GatewayMinioSysTmp, Versions: false})
|
||||||
|
@ -106,11 +106,9 @@ func (g *S3) Name() string {
|
|||||||
|
|
||||||
const letterBytes = "abcdefghijklmnopqrstuvwxyz01234569"
|
const letterBytes = "abcdefghijklmnopqrstuvwxyz01234569"
|
||||||
const (
|
const (
|
||||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||||
minioReservedBucket = "minio"
|
|
||||||
minioReservedBucketPath = minio.SlashSeparator + minioReservedBucket
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// randString generates random names and prepends them with a known prefix.
|
// randString generates random names and prepends them with a known prefix.
|
||||||
@ -158,32 +156,6 @@ var defaultAWSCredProviders = []credentials.Provider{
|
|||||||
&credentials.EnvMinio{},
|
&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.
|
// newS3 - Initializes a new client by auto probing S3 server signature.
|
||||||
func newS3(urlStr string) (*miniogo.Core, error) {
|
func newS3(urlStr string) (*miniogo.Core, error) {
|
||||||
if urlStr == "" {
|
if urlStr == "" {
|
||||||
@ -237,9 +209,9 @@ func (g *S3) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, error)
|
|||||||
|
|
||||||
metrics := minio.NewMetrics()
|
metrics := minio.NewMetrics()
|
||||||
|
|
||||||
t := &metricsTransport{
|
t := &minio.MetricsTransport{
|
||||||
transport: minio.NewCustomHTTPTransport(),
|
Transport: minio.NewCustomHTTPTransport(),
|
||||||
metrics: metrics,
|
Metrics: metrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set custom transport
|
// Set custom transport
|
||||||
|
@ -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())
|
m, _ := globalObjectAPI.GetMetrics(context.Background())
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName("gateway", globalGatewayName, "bytes_received"),
|
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),
|
nil, nil),
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
float64(m.GetBytesReceived()),
|
float64(m.GetBytesReceived()),
|
||||||
@ -285,7 +285,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
|
|||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName("gateway", globalGatewayName, "bytes_sent"),
|
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),
|
nil, nil),
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
float64(m.GetBytesSent()),
|
float64(m.GetBytesSent()),
|
||||||
@ -294,7 +294,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
|
|||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName("gateway", globalGatewayName, "requests"),
|
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),
|
[]string{"method"}, nil),
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
float64(s.Get.Load()),
|
float64(s.Get.Load()),
|
||||||
@ -303,7 +303,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
|
|||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName("gateway", globalGatewayName, "requests"),
|
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),
|
[]string{"method"}, nil),
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
float64(s.Head.Load()),
|
float64(s.Head.Load()),
|
||||||
|
@ -147,13 +147,15 @@ MinIO Gateway instances enabled with Disk-Caching expose caching related metrics
|
|||||||
- `cache_hits_total`: Total number of cache hits.
|
- `cache_hits_total`: Total number of cache hits.
|
||||||
- `cache_misses_total`: Total number of cache misses.
|
- `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_<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_s3_bytes_sent`: Total number of bytes sent to AWS S3 (in GET & HEAD Requests).
|
- `gateway_<gateway_type>_bytes_sent`: Total number of bytes sent to cloud backend (in GET & HEAD Requests).
|
||||||
- `gateway_s3_bytes_received`: Total number of bytes received from AWS S3 (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
|
## Migration guide for the new set of metrics
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user