Skip to content

Commit a629212

Browse files
authored
feat(thanos): add new metric to track status codes (#14937)
1 parent 83e680f commit a629212

File tree

6 files changed

+60
-18
lines changed

6 files changed

+60
-18
lines changed

‎pkg/storage/bucket/azure/bucket_client.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import (
88
"github.com/thanos-io/objstore/providers/azure"
99
)
1010

11-
func NewBucketClient(cfg Config, name string, logger log.Logger) (objstore.Bucket, error) {
12-
return newBucketClient(cfg, name, logger, azure.NewBucketWithConfig)
11+
func NewBucketClient(cfg Config, name string, logger log.Logger, wrapRT func(http.RoundTripper) http.RoundTripper) (objstore.Bucket, error) {
12+
return newBucketClient(cfg, name, logger, wrapRT, azure.NewBucketWithConfig)
1313
}
1414

15-
func newBucketClient(cfg Config, name string, logger log.Logger, factory func(log.Logger, azure.Config, string, func(http.RoundTripper) http.RoundTripper) (*azure.Bucket, error)) (objstore.Bucket, error) {
15+
func newBucketClient(cfg Config, name string, logger log.Logger, wrapRT func(http.RoundTripper) http.RoundTripper, factory func(log.Logger, azure.Config, string, func(http.RoundTripper) http.RoundTripper) (*azure.Bucket, error)) (objstore.Bucket, error) {
1616
// Start with default config to make sure that all parameters are set to sensible values, especially
1717
// HTTP Config field.
1818
bucketConfig := azure.DefaultConfig
@@ -29,5 +29,5 @@ func newBucketClient(cfg Config, name string, logger log.Logger, factory func(lo
2929
bucketConfig.Endpoint = cfg.Endpoint
3030
}
3131

32-
return factory(logger, bucketConfig, name, nil)
32+
return factory(logger, bucketConfig, name, wrapRT)
3333
}

‎pkg/storage/bucket/client.go

+42-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"net/http"
99
"regexp"
10+
"strconv"
1011

1112
"github.com/go-kit/log"
1213
"github.com/prometheus/client_golang/prometheus"
@@ -46,9 +47,24 @@ var (
4647
ErrUnsupportedStorageBackend = errors.New("unsupported storage backend")
4748
ErrInvalidCharactersInStoragePrefix = errors.New("storage prefix contains invalid characters, it may only contain digits and English alphabet letters")
4849

49-
metrics = objstore.BucketMetrics(prometheus.WrapRegistererWithPrefix("loki_", prometheus.DefaultRegisterer), "")
50+
metrics *objstore.Metrics
51+
52+
// added to track the status codes by method
53+
bucketRequestsTotal = prometheus.NewCounterVec(
54+
prometheus.CounterOpts{
55+
Namespace: "loki",
56+
Name: "objstore_bucket_transport_requests_total",
57+
Help: "Total number of HTTP transport requests made to the bucket backend by status code and method.",
58+
},
59+
[]string{"status_code", "method"},
60+
)
5061
)
5162

63+
func init() {
64+
prometheus.MustRegister(bucketRequestsTotal)
65+
metrics = objstore.BucketMetrics(prometheus.WrapRegistererWithPrefix("loki_", prometheus.DefaultRegisterer), "")
66+
}
67+
5268
// StorageBackendConfig holds configuration for accessing long-term storage.
5369
type StorageBackendConfig struct {
5470
// Backends
@@ -176,13 +192,13 @@ func NewClient(ctx context.Context, backend string, cfg Config, name string, log
176192
// TODO: add support for other backends that loki already supports
177193
switch backend {
178194
case S3:
179-
client, err = s3.NewBucketClient(cfg.S3, name, logger)
195+
client, err = s3.NewBucketClient(cfg.S3, name, logger, instrumentTransport())
180196
case GCS:
181-
client, err = gcs.NewBucketClient(ctx, cfg.GCS, name, logger)
197+
client, err = gcs.NewBucketClient(ctx, cfg.GCS, name, logger, instrumentTransport())
182198
case Azure:
183-
client, err = azure.NewBucketClient(cfg.Azure, name, logger)
199+
client, err = azure.NewBucketClient(cfg.Azure, name, logger, instrumentTransport())
184200
case Swift:
185-
client, err = swift.NewBucketClient(cfg.Swift, name, logger)
201+
client, err = swift.NewBucketClient(cfg.Swift, name, logger, instrumentTransport())
186202
case Filesystem:
187203
client, err = filesystem.NewBucketClient(cfg.Filesystem)
188204
default:
@@ -209,3 +225,24 @@ func NewClient(ctx context.Context, backend string, cfg Config, name string, log
209225

210226
return instrumentedClient, nil
211227
}
228+
229+
type instrumentedRoundTripper struct {
230+
next http.RoundTripper
231+
}
232+
233+
func instrumentTransport() func(http.RoundTripper) http.RoundTripper {
234+
return func(rt http.RoundTripper) http.RoundTripper {
235+
return &instrumentedRoundTripper{next: rt}
236+
}
237+
}
238+
239+
func (i *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
240+
resp, err := i.next.RoundTrip(req)
241+
if err != nil {
242+
return resp, err
243+
}
244+
245+
// Record status code and method metrics
246+
bucketRequestsTotal.WithLabelValues(strconv.Itoa(resp.StatusCode), req.Method).Inc()
247+
return resp, nil
248+
}

‎pkg/storage/bucket/gcs/bucket_client.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package gcs
22

33
import (
44
"context"
5+
"net/http"
56

67
"github.com/go-kit/log"
78
"github.com/thanos-io/objstore"
89
"github.com/thanos-io/objstore/providers/gcs"
910
)
1011

1112
// NewBucketClient creates a new GCS bucket client
12-
func NewBucketClient(ctx context.Context, cfg Config, name string, logger log.Logger) (objstore.Bucket, error) {
13+
func NewBucketClient(ctx context.Context, cfg Config, name string, logger log.Logger, wrapRT func(http.RoundTripper) http.RoundTripper) (objstore.Bucket, error) {
1314
// start with default http configs
1415
bucketConfig := gcs.DefaultConfig
1516
bucketConfig.Bucket = cfg.BucketName
@@ -18,5 +19,5 @@ func NewBucketClient(ctx context.Context, cfg Config, name string, logger log.Lo
1819
bucketConfig.MaxRetries = cfg.MaxRetries
1920
bucketConfig.HTTPConfig.Transport = cfg.Transport
2021

21-
return gcs.NewBucketWithConfig(ctx, logger, bucketConfig, name, nil)
22+
return gcs.NewBucketWithConfig(ctx, logger, bucketConfig, name, wrapRT)
2223
}

‎pkg/storage/bucket/s3/bucket_client.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package s3
22

33
import (
4+
"net/http"
5+
46
"github.com/go-kit/log"
57
"github.com/prometheus/common/model"
68
"github.com/thanos-io/objstore"
@@ -14,23 +16,23 @@ const (
1416
)
1517

1618
// NewBucketClient creates a new S3 bucket client
17-
func NewBucketClient(cfg Config, name string, logger log.Logger) (objstore.Bucket, error) {
19+
func NewBucketClient(cfg Config, name string, logger log.Logger, wrapRT func(http.RoundTripper) http.RoundTripper) (objstore.Bucket, error) {
1820
s3Cfg, err := newS3Config(cfg)
1921
if err != nil {
2022
return nil, err
2123
}
2224

23-
return s3.NewBucketWithConfig(logger, s3Cfg, name, nil)
25+
return s3.NewBucketWithConfig(logger, s3Cfg, name, wrapRT)
2426
}
2527

2628
// NewBucketReaderClient creates a new S3 bucket client
27-
func NewBucketReaderClient(cfg Config, name string, logger log.Logger) (objstore.BucketReader, error) {
29+
func NewBucketReaderClient(cfg Config, name string, logger log.Logger, wrapRT func(http.RoundTripper) http.RoundTripper) (objstore.BucketReader, error) {
2830
s3Cfg, err := newS3Config(cfg)
2931
if err != nil {
3032
return nil, err
3133
}
3234

33-
return s3.NewBucketWithConfig(logger, s3Cfg, name, nil)
35+
return s3.NewBucketWithConfig(logger, s3Cfg, name, wrapRT)
3436
}
3537

3638
func newS3Config(cfg Config) (s3.Config, error) {

‎pkg/storage/bucket/sse_bucket_client_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func TestSSEBucketClient_Upload_ShouldInjectCustomSSEConfig(t *testing.T) {
5656
Insecure: true,
5757
}
5858

59-
s3Client, err := s3.NewBucketClient(s3Cfg, "test", log.NewNopLogger())
59+
s3Client, err := s3.NewBucketClient(s3Cfg, "test", log.NewNopLogger(), nil)
6060
require.NoError(t, err)
6161

6262
// Configure the config provider with NO KMS key ID.

‎pkg/storage/bucket/swift/bucket_client.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package swift
22

33
import (
4+
"net/http"
5+
46
"github.com/go-kit/log"
57
"github.com/prometheus/common/model"
68
"github.com/thanos-io/objstore"
@@ -9,7 +11,7 @@ import (
911
)
1012

1113
// NewBucketClient creates a new Swift bucket client
12-
func NewBucketClient(cfg Config, _ string, logger log.Logger) (objstore.Bucket, error) {
14+
func NewBucketClient(cfg Config, _ string, logger log.Logger, wrapper func(http.RoundTripper) http.RoundTripper) (objstore.Bucket, error) {
1315
bucketConfig := swift.Config{
1416
AuthVersion: cfg.AuthVersion,
1517
AuthUrl: cfg.AuthURL,
@@ -37,5 +39,5 @@ func NewBucketClient(cfg Config, _ string, logger log.Logger) (objstore.Bucket,
3739
}
3840
bucketConfig.HTTPConfig.Transport = cfg.Transport
3941

40-
return swift.NewContainerFromConfig(logger, &bucketConfig, false, nil)
42+
return swift.NewContainerFromConfig(logger, &bucketConfig, false, wrapper)
4143
}

0 commit comments

Comments
 (0)