synapsecns/sanguine

View on GitHub
core/metrics/metrics.go

Summary

Maintainability
A
0 mins
Test Coverage
package metrics

import (
    "context"
    "fmt"
    "net/http"
    "os"
    "strings"

    "github.com/gin-gonic/gin"
    "github.com/synapsecns/sanguine/core/config"
    experimentalLogger "github.com/synapsecns/sanguine/core/metrics/logger"
    "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
    "go.opentelemetry.io/otel/metric"
    "go.opentelemetry.io/otel/propagation"
    "go.opentelemetry.io/otel/trace"
    "gorm.io/gorm"
)

// Handler collects metrics.
type Handler interface {
    Start(ctx context.Context) error
    // Gin gets all gin middlewares for tracing.
    Gin() []gin.HandlerFunc
    // ConfigureHTTPClient configures tracing on an http client
    ConfigureHTTPClient(client *http.Client, opts ...otelhttp.Option)
    // AddGormCallbacks adds gorm callbacks for tracing.
    AddGormCallbacks(db *gorm.DB)
    // GetTracerProvider returns the tracer provider.
    GetTracerProvider() trace.TracerProvider
    // Tracer returns the tracer provider.
    Tracer() trace.Tracer
    // Propagator returns the propagator.
    Propagator() propagation.TextMapPropagator
    // Type returns the handler type.
    Type() HandlerType
    // Metrics returns a metric provider
    // Deprecated: Will be removed in a future version please use meter.
    Metrics() Meter
    // Meter returns a metric provider
    Meter(name string, options ...metric.MeterOption) metric.Meter
    // Handler returns the http handler for the metrics endpoint.
    // right now, this supports only a single route
    Handler() http.Handler
    // ExperimentalLogger returns an experimental logger.
    ExperimentalLogger() experimentalLogger.ExperimentalLogger
}

// HandlerType is the handler type to use
//
//go:generate go run golang.org/x/tools/cmd/stringer -type=HandlerType -linecomment
type HandlerType uint8

// AllHandlerTypes is a list of all contract types. Since we use stringer and this is a testing library, instead
// of manually copying all these out we pull the names out of stringer. In order to make sure stringer is updated, we panic on
// any method called where the index is higher than the stringer array length.
var AllHandlerTypes []HandlerType

func init() {
    for i := 0; i < len(_HandlerType_index); i++ {
        contractType := HandlerType(i)
        AllHandlerTypes = append(AllHandlerTypes, contractType)
    }
}

const (
    // OTLP is the otlp driver.
    OTLP HandlerType = iota + 1 // OTLP
    // Jaeger is the jaeger driver.
    Jaeger // Jaeger
    // Null is a null data type handler.
    Null // Null
)

// Lower gets the lowercase version of the handler type. Useful for comparison
// in switch.
func (i HandlerType) Lower() string {
    return strings.ToLower(i.String())
}

// HandlerEnv is the driver to use for metrics.
const HandlerEnv = "METRICS_HANDLER"

// NewFromEnv sets up a metrics handler from environment variable.
// this will not set the global and generally, SetupFromEnv should be used instead.
func NewFromEnv(ctx context.Context, buildInfo config.BuildInfo) (handler Handler, err error) {
    metricsHandler := strings.ToLower(os.Getenv(HandlerEnv))
    var ht HandlerType
    //nolint: gocritic
    switch metricsHandler {
    case OTLP.Lower():
        ht = OTLP
    case Jaeger.Lower():
        ht = Jaeger
    case Null.Lower():
        ht = Null
    default:
        ht = Null
    }

    return NewByType(ctx, buildInfo, ht)
}

// NewByType sets up a metrics handler by type.
func NewByType(ctx context.Context, buildInfo config.BuildInfo, ht HandlerType) (handler Handler, err error) {
    //nolint: gocritic
    switch ht {
    case OTLP:
        handler = NewOTLPMetricsHandler(buildInfo)
    case Jaeger:
        handler = NewJaegerHandler(buildInfo)
    case Null:
        handler = NewNullHandler()
    default:
        handler = NewNullHandler()
    }

    if handler != nil {
        err = handler.Start(ctx)
        if err != nil {
            return nil, fmt.Errorf("could not start handler: %w", err)
        }
    }

    return handler, nil
}