Skip to content

Commit

Permalink
feat: cache metrics (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
p0mvn authored Jan 4, 2024
1 parent 8cb5f41 commit f6712ad
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 6 deletions.
36 changes: 36 additions & 0 deletions domain/url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package domain

import (
"context"
"net/url"

"github.com/labstack/echo"
)

// RequestPathKeyType is a custom type for request path key.
type RequestPathKeyType string

const (
// RequestPathCtxKey is the key used to store the request path in the request context
RequestPathCtxKey RequestPathKeyType = "request_path"
)

// ParseURLPath parses the URL path from the echo context
func ParseURLPath(c echo.Context) (string, error) {
parsedURL, err := url.Parse(c.Request().RequestURI)
if err != nil {
return "", err
}

return parsedURL.Path, nil
}

// GetURLPathFromContext returns the request path from the context
func GetURLPathFromContext(ctx context.Context) (string, error) {
// Get request path for metrics
requestPath, ok := ctx.Value(RequestPathCtxKey).(string)
if !ok || (ok && len(requestPath) == 0) {
requestPath = "unknown"
}
return requestPath, nil
}
16 changes: 11 additions & 5 deletions middleware/middleware.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package middleware

import (
"net/url"
"context"
"time"

"github.com/labstack/echo"
"github.com/prometheus/client_golang/prometheus"

"github.com/osmosis-labs/osmosis/v21/ingest/sqs/domain"
)

// GoMiddleware represent the data-struct for middleware
Expand Down Expand Up @@ -57,17 +59,21 @@ func (m *GoMiddleware) InstrumentMiddleware(next echo.HandlerFunc) echo.HandlerF
return func(c echo.Context) error {
start := time.Now()

parsedURL, err := url.Parse(c.Request().RequestURI)
requestMethod := c.Request().Method
requestPath, err := domain.ParseURLPath(c)
if err != nil {
return err
}

requestMethod := c.Request().Method
requestPath := parsedURL.Path

// Increment the request counter
requestsTotal.WithLabelValues(requestMethod, requestPath).Inc()

// Insert the request path into the context
ctx := c.Request().Context()
ctx = context.WithValue(ctx, domain.RequestPathCtxKey, requestPath)
request := c.Request().WithContext(ctx)
c.SetRequest(request)

err = next(c)

duration := time.Since(start).Seconds()
Expand Down
41 changes: 40 additions & 1 deletion router/usecase/router_usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"

"github.com/osmosis-labs/sqs/domain"
Expand Down Expand Up @@ -34,6 +35,33 @@ type routerUseCaseImpl struct {
rankedRouteCache *cache.Cache
}

const (
candidateRouteCacheLabel = "candidate_route"
rankedRouteCacheLabel = "ranked_route"
)

var (
cacheHits = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "sqs_cache_hits_total",
Help: "Total number of cache hits",
},
[]string{"route", "cache_type", "token_in", "token_out"},
)
cacheMisses = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "sqs_cache_misses_total",
Help: "Total number of cache misses",
},
[]string{"route", "cache_type", "token_in", "token_out"},
)
)

func init() {
prometheus.MustRegister(cacheHits)
prometheus.MustRegister(cacheMisses)
}

// NewRouterUsecase will create a new pools use case object
func NewRouterUsecase(timeout time.Duration, routerRepository routerredisrepo.RouterRepository, poolsUsecase mvc.PoolsUsecase, config domain.RouterConfig, logger log.Logger, rankedRouteCache *cache.Cache) mvc.RouterUsecase {
return &routerUseCaseImpl{
Expand All @@ -57,7 +85,6 @@ func NewRouterUsecase(timeout time.Duration, routerRepository routerredisrepo.Ro
// Returns error if:
// - fails to estimate direct quotes for ranked routes
// - fails to retrieve candidate routes
// -
func (r *routerUseCaseImpl) GetOptimalQuote(ctx context.Context, tokenIn sdk.Coin, tokenOutDenom string) (domain.Quote, error) {
// Get an order of magnitude for the token in amount
// This is used for caching ranked routes as these might differ depending on the amount swapped in.
Expand All @@ -73,7 +100,16 @@ func (r *routerUseCaseImpl) GetOptimalQuote(ctx context.Context, tokenIn sdk.Coi

router := r.initializeRouter()

// Get request path for metrics
requestURLPath, err := domain.GetURLPathFromContext(ctx)
if err != nil {
return nil, err
}

if hasRankedRoutesInCache {
// Increase cache hits
cacheHits.WithLabelValues(requestURLPath, rankedRouteCacheLabel, tokenIn.Denom, tokenOutDenom).Inc()

rankedCandidateRoutes, ok := rankedRoutesData.(sqsdomain.CandidateRoutes)
if !ok {
return nil, fmt.Errorf("error casting ranked routes from cache")
Expand All @@ -85,6 +121,9 @@ func (r *routerUseCaseImpl) GetOptimalQuote(ctx context.Context, tokenIn sdk.Coi
return nil, err
}
} else {
// Increase cache misses
cacheMisses.WithLabelValues(requestURLPath, rankedRouteCacheLabel, tokenIn.Denom, tokenOutDenom).Inc()

// If top routes are not present in cache, retrieve unranked candidate routes
candidateRoutes, err := r.handleCandidateRoutes(ctx, router, tokenIn.Denom, tokenOutDenom)
if err != nil {
Expand Down

0 comments on commit f6712ad

Please sign in to comment.