Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions pkg/uhttp/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"google.golang.org/grpc/status"

v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
"github.com/conductorone/baton-sdk/pkg/metrics"
"github.com/conductorone/baton-sdk/pkg/ratelimit"
)

Expand All @@ -33,6 +34,11 @@ const (
applicationVndApiJSON = "application/vnd.api+json"
acceptHeader = "Accept"
authorizationHeader = "Authorization"

httpCacheHitCounterName = "baton_sdk.http_cache_hit"
httpCacheMissCounterName = "baton_sdk.http_cache_miss"
httpCacheHitCounterDesc = "number of HTTP cache hits"
httpCacheMissCounterDesc = "number of HTTP cache misses"
)

type WrapperResponse struct {
Expand Down Expand Up @@ -63,6 +69,20 @@ func WithRateLimiter(rate int, per time.Duration) WrapperOption {
return rateLimiterOption{rate: rate, per: per}
}

type metricsHandlerOption struct {
handler metrics.Handler
}

func (o metricsHandlerOption) Apply(c *BaseHttpClient) {
c.metricsHandler = o.handler
}

// WithMetricsHandler returns a WrapperOption that sets the metrics handler for the http client.
// When set, cache hits and misses will be recorded as metrics.
func WithMetricsHandler(handler metrics.Handler) WrapperOption {
return metricsHandlerOption{handler: handler}
}

type WrapperOption interface {
Apply(*BaseHttpClient)
}
Expand Down Expand Up @@ -91,9 +111,10 @@ type (
NewRequest(ctx context.Context, method string, url *url.URL, options ...RequestOption) (*http.Request, error)
}
BaseHttpClient struct {
HttpClient *http.Client
rateLimiter uRateLimit.Limiter
baseHttpCache icache
HttpClient *http.Client
rateLimiter uRateLimit.Limiter
baseHttpCache icache
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make more sense to put the metrics handler on the cache itself?

metricsHandler metrics.Handler
}

DoOption func(resp *WrapperResponse) error
Expand Down Expand Up @@ -341,6 +362,22 @@ func WrapErrorsWithRateLimitInfo(preferredCode codes.Code, resp *http.Response,
return errors.Join(allErrs...)
}

func (c *BaseHttpClient) recordCacheHit(ctx context.Context) {
if c.metricsHandler == nil {
return
}
counter := c.metricsHandler.Int64Counter(httpCacheHitCounterName, httpCacheHitCounterDesc, metrics.Dimensionless)
counter.Add(ctx, 1, nil)
}

func (c *BaseHttpClient) recordCacheMiss(ctx context.Context) {
if c.metricsHandler == nil {
return
}
counter := c.metricsHandler.Int64Counter(httpCacheMissCounterName, httpCacheMissCounterDesc, metrics.Dimensionless)
counter.Add(ctx, 1, nil)
}

func (c *BaseHttpClient) Do(req *http.Request, options ...DoOption) (*http.Response, error) {
var (
err error
Expand All @@ -359,9 +396,9 @@ func (c *BaseHttpClient) Do(req *http.Request, options ...DoOption) (*http.Respo
return nil, err
}
if resp == nil {
l.Debug("http cache miss", zap.String("url", req.URL.String()))
c.recordCacheMiss(req.Context())
} else {
l.Debug("http cache hit", zap.String("url", req.URL.String()))
c.recordCacheHit(req.Context())
}
}

Expand Down
Loading