From 8c0b9919a4d6678a18f46dcb4882fb7fb0f4156c Mon Sep 17 00:00:00 2001 From: Eduardo Bonzi Date: Sun, 24 Mar 2024 16:53:40 -0300 Subject: [PATCH 1/2] feat: add opentelemetry traces support --- README.md | 1 + TODO | 2 +- cmd/main.go | 6 ++ cmd/modules.go | 24 +++++--- cmd/options.go | 20 +++++++ cmd/telemetry.go | 68 ++++++++++++++++++++++ docs/docs/config.md | 20 ++++--- docs/docs/index.md | 1 + go.mod | 42 +++++++++++--- go.sum | 104 ++++++++++++++++++++++++++-------- pkg/app/delay.go | 4 ++ pkg/app/handler.go | 5 +- pkg/app/handler_test.go | 15 ++--- pkg/app/matcher.go | 3 +- pkg/app/matcher_test.go | 3 +- pkg/app/scenario.go | 5 +- pkg/app/scenario_test.go | 3 +- pkg/app/service.go | 22 +++++-- pkg/app/service_test.go | 3 +- {cmd => pkg/config}/config.go | 27 +++------ pkg/config/config_test.go | 16 ++++++ pkg/telemetry/telemetry.go | 16 ++++++ 22 files changed, 320 insertions(+), 90 deletions(-) create mode 100644 cmd/options.go create mode 100644 cmd/telemetry.go rename {cmd => pkg/config}/config.go (55%) create mode 100644 pkg/config/config_test.go create mode 100644 pkg/telemetry/telemetry.go diff --git a/README.md b/README.md index 3b10938..85d26cc 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ As of now, Mantis has all of the core features needed to be used in almost any s - JSON Path support - Support for a Wiremock's `Scenario`-like feature - Simulate production environments more accurately by defining delays on responses +- Opentelemetry traces support - More to come ## Running It diff --git a/TODO b/TODO index fee6f9a..06d52cc 100644 --- a/TODO +++ b/TODO @@ -6,6 +6,6 @@ Display differences when no match is found Add delay option to response (normal distribution) Remove americanas-go/log dependency Possibly remove americanas-go/config dependency -APM/Metrics (Opentelemetry integration) +Add Metrics (Opentelemetry) Performance tests Improve/refactor validation \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go index 8c0ba99..8e28d5e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,15 +5,21 @@ import ( "os" "os/signal" + amercfg "github.com/americanas-go/config" "github.com/americanas-go/log" + "github.com/dubonzi/mantis/pkg/config" "go.uber.org/fx" ) func main() { + config.SetDefaultConfig() + amercfg.Load() stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) + setupOtel() + app := fx.New( mainModule(), ) diff --git a/cmd/modules.go b/cmd/modules.go index f91b9ea..bb177ad 100644 --- a/cmd/modules.go +++ b/cmd/modules.go @@ -4,18 +4,17 @@ import ( "context" "fmt" - "github.com/americanas-go/config" + amercfg "github.com/americanas-go/config" "github.com/americanas-go/log" "github.com/americanas-go/log/contrib/go.uber.org/zap.v1" "github.com/dubonzi/mantis/pkg/app" + "github.com/gofiber/contrib/otelfiber" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/pprof" "go.uber.org/fx" ) func mainModule() fx.Option { - loadDefaultConfig() - config.Load() log.SetGlobalLogger(zap.NewLoggerWithOptions(zapOptions())) return fx.Options( @@ -43,19 +42,22 @@ func serverModule() fx.Option { srv := fiber.New( fiber.Config{ AppName: "Mantis Server", - DisableStartupMessage: config.Bool("server.disableStartupMessage"), + DisableStartupMessage: amercfg.Bool("server.disableStartupMessage"), }, ) - srv.Use("/*", fiberErrorLogger) + if amercfg.Bool("otel.enabled") { + srv.Use(otelfiber.Middleware(otelfiber.WithSpanNameFormatter(fiberOtelSpanFormatter))) + } srv.Use(pprof.New()) + srv.Use("/*", fiberErrorLogger) srv.All("/*", handler.All) lc.Append( fx.Hook{ OnStart: func(c context.Context) error { go func() { - if err := srv.Listen(":" + config.String("server.port")); err != nil { + if err := srv.Listen(":" + amercfg.String("server.port")); err != nil { panic(fmt.Errorf("error starting mantis server: %s", err)) } }() @@ -77,7 +79,7 @@ func healthModule() fx.Option { srv := fiber.New( fiber.Config{ AppName: "Mantis Health Server", - DisableStartupMessage: config.Bool("server.disableStartupMessage"), + DisableStartupMessage: amercfg.Bool("server.disableStartupMessage"), }, ) @@ -87,7 +89,7 @@ func healthModule() fx.Option { fx.Hook{ OnStart: func(c context.Context) error { go func() { - if err := srv.Listen(":" + config.String("health.port")); err != nil { + if err := srv.Listen(":" + amercfg.String("health.port")); err != nil { panic(fmt.Errorf("error starting health server: %s", err)) } }() @@ -103,7 +105,7 @@ func healthModule() fx.Option { } func fxLogger() fx.Option { - if config.Bool("fx.log.enable") { + if amercfg.Bool("fx.log.enable") { return fx.Provide() } return fx.NopLogger @@ -116,3 +118,7 @@ func fiberErrorLogger(c *fiber.Ctx) error { } return err } + +func fiberOtelSpanFormatter(ctx *fiber.Ctx) string { + return fmt.Sprintf("%s %s", ctx.Context().Method(), ctx.Request().URI().Path()) +} diff --git a/cmd/options.go b/cmd/options.go new file mode 100644 index 0000000..091d750 --- /dev/null +++ b/cmd/options.go @@ -0,0 +1,20 @@ +package main + +import ( + "github.com/americanas-go/config" + igzap "github.com/americanas-go/log/contrib/go.uber.org/zap.v1" +) + +func zapOptions() *igzap.Options { + return &igzap.Options{ + Console: struct { + Enabled bool + Level string + Formatter string + }{ + Enabled: true, + Level: config.String("log.level"), + Formatter: config.String("log.format"), + }, + } +} diff --git a/cmd/telemetry.go b/cmd/telemetry.go new file mode 100644 index 0000000..14b6386 --- /dev/null +++ b/cmd/telemetry.go @@ -0,0 +1,68 @@ +package main + +import ( + "context" + + "github.com/americanas-go/config" + "github.com/americanas-go/log" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + "go.opentelemetry.io/otel/trace/noop" +) + +const ( + protocolHTTP = "http" + protocolGRPC = "grpc" +) + +func setupOtel() { + if !config.Bool("otel.enabled") { + return + } + + exporterProtocol := config.String("otel.exporter.protocol") + var err error + var traceExporter *otlptrace.Exporter + + switch exporterProtocol { + case protocolHTTP: + opts := []otlptracehttp.Option{otlptracehttp.WithEndpoint(config.String("otel.exporter.endpoint"))} + if config.Bool("otel.exporter.insecure") { + opts = append(opts, otlptracehttp.WithInsecure()) + } + traceExporter, err = otlptracehttp.New(context.Background(), opts...) + case protocolGRPC: + opts := []otlptracegrpc.Option{otlptracegrpc.WithEndpoint(config.String("otel.exporter.endpoint"))} + if config.Bool("otel.exporter.insecure") { + opts = append(opts, otlptracegrpc.WithInsecure()) + } + traceExporter, err = otlptracegrpc.New(context.Background(), opts...) + default: + log.Warnf("opentelemetry: invalid protocol: %s", exporterProtocol) + otel.SetTracerProvider(noop.NewTracerProvider()) + return + } + if err != nil { + log.Error("error starting opentelemetry exporter", err) + return + } + + tp := trace.NewTracerProvider( + trace.WithSampler(trace.AlwaysSample()), + trace.WithBatcher(traceExporter), + trace.WithResource( + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceNameKey.String("mantis"), + )), + ) + + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) +} diff --git a/docs/docs/config.md b/docs/docs/config.md index 12ac566..703a956 100644 --- a/docs/docs/config.md +++ b/docs/docs/config.md @@ -2,11 +2,15 @@ You can configure Mantis either by envinroment variables or by passing arguments when running the executable. -| Env | Arg | Default | | -| ---------------------- | ----------------------- | ---------------- | ---------------------- | -| `SERVER_PORT` | `-server.port` | `8080` | Port Mantis runs on | -| `HEALTH_PORT` | `-health.port` | `8081` | Health check port | -| `LOADER_PATH_MAPPING` | `-loader.path.mapping` | `files/mapping` | Path to mapping files | -| `LOADER_PATH_RESPONSE` | `-loader.path.response` | `files/response` | Path to response files | -| `LOG_LEVEL` | `-log.level` | `INFO` | Log level | -| `LOG_FORMAT` | `-log.format` | `TEXT` | Log format (TEXT/JSON) | \ No newline at end of file +| Env | Arg | Default | | +| ------------------------ | ------------------------- | ---------------- | -------------------------------------------------------------------- | +| `SERVER_PORT` | `-server.port` | `8080` | Port Mantis runs on | +| `HEALTH_PORT` | `-health.port` | `8081` | Health check port | +| `LOADER_PATH_MAPPING` | `-loader.path.mapping` | `files/mapping` | Path to mapping files | +| `LOADER_PATH_RESPONSE` | `-loader.path.response` | `files/response` | Path to response files | +| `OTEL_ENABLED` | `-otel.enabled` | `true` | Enable/disable Opentelemetry support | +| `OTEL_EXPORTER_PROTOCOL` | `-otel.exporter.protocol` | `http` | Protocol used to export Opentelemetry traces and metrics (http/grpc) | +| `OTEL_EXPORTER_ENDPOINT` | `-otel.exporter.endpoint` | `localhost:4318` | Endpoint of the collecter for Opentelemetry traces and metrics | +| `OTEL_EXPORTER_INSECURE` | `-otel.exporter.insecure` | `true` | Use insecure connection for Opentelemetry exporter | +| `LOG_LEVEL` | `-log.level` | `INFO` | Log level | +| `LOG_FORMAT` | `-log.format` | `TEXT` | Log format (TEXT/JSON) | \ No newline at end of file diff --git a/docs/docs/index.md b/docs/docs/index.md index fa5d957..ed65c69 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -40,4 +40,5 @@ As of now, Mantis has all of the core features needed to be used in almost any s - JSON Path support - Support for a Wiremock's `Scenario`-like feature - Simulate production environments more accurately by defining delays on responses +- Opentelemetry traces support - More to come \ No newline at end of file diff --git a/go.mod b/go.mod index c9730d8..eebe517 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,35 @@ module github.com/dubonzi/mantis go 1.22 require ( - github.com/americanas-go/config v1.8.5 - github.com/americanas-go/log v1.8.9 - github.com/gofiber/fiber/v2 v2.52.1 + github.com/americanas-go/config v1.8.6 + github.com/americanas-go/log v1.8.10 + github.com/gofiber/contrib/otelfiber v1.0.10 + github.com/gofiber/fiber/v2 v2.52.2 github.com/google/uuid v1.6.0 github.com/ohler55/ojg v1.21.4 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.9.0 - go.uber.org/fx v1.20.1 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/fx v1.21.0 ) require ( github.com/andybalholm/brotli v1.1.0 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/gobeam/stringy v0.0.6 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/knadh/koanf v1.5.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -28,15 +41,26 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect + go.opentelemetry.io/contrib v1.24.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/dig v1.17.1 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/sys v0.16.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d8cabd6..71df5df 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,10 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/americanas-go/config v1.8.5 h1:pCzHml+SyQeEGHogtQXei92dR2woEYuRY6mVxlGb2UY= -github.com/americanas-go/config v1.8.5/go.mod h1:9b41dTBy1za6Qfv07VkGbVVTj8Vz0WY6yPcOmHAEbeE= -github.com/americanas-go/log v1.8.9 h1:cJQtjAuvFN+tu3T9CsDF6nmwhlKob7FTUgfERaI32+8= -github.com/americanas-go/log v1.8.9/go.mod h1:HIamF6kw4QGVhDEni4WuYhA1BzX1jUFBRXACAjbEShY= +github.com/americanas-go/config v1.8.6 h1:BfLOZQ9wm1dRIqd297rsr+AE+7feiXGDbpe4eMY4TQ0= +github.com/americanas-go/config v1.8.6/go.mod h1:SJAPPz2qaOAaVmo+SLZoZ5y28uDSDC7qGDTUAxgP2eg= +github.com/americanas-go/log v1.8.10 h1:sO7LSL4asszWr09Dn41FYoGhOwm2j+nwycxOKM1tQPk= +github.com/americanas-go/log v1.8.10/go.mod h1:0+6zisZjensI2p++NlagMEQETG+Oxahamx5x3lw8TLg= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -27,12 +27,12 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72H github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -64,13 +64,20 @@ github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobeam/stringy v0.0.6 h1:IboItevQArUAYUbjb7xmtGoJfN5Aqpk3/bVCd7JgWe0= github.com/gobeam/stringy v0.0.6/go.mod h1:W3620X9dJHf2FSZF5fRnWekHcHQjwmCz8ZQ2d1qloqE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofiber/fiber/v2 v2.52.1 h1:1RoU2NS+b98o1L77sdl5mboGPiW+0Ypsi5oLmcYlgHI= -github.com/gofiber/fiber/v2 v2.52.1/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/gofiber/contrib/otelfiber v1.0.10 h1:Bu28Pi4pfYmGfIc/9+sNaBbFwTHGY/zpSIK5jBxuRtM= +github.com/gofiber/contrib/otelfiber v1.0.10/go.mod h1:jN6AvS1HolDHTQHFURsV+7jSX96FpXYeKH6nmkq8AIw= +github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= +github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -89,6 +96,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -100,12 +109,16 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -154,16 +167,17 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs= github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -244,9 +258,11 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= @@ -271,8 +287,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= -github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= +github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -281,20 +297,43 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.opentelemetry.io/contrib v1.24.0 h1:Tfn7pP/482iIzeeba91tP52a1c1TEeqYc1saih+vBN8= +go.opentelemetry.io/contrib v1.24.0/go.mod h1:usW9bPlrjHiJFbK0a6yK/M5wNHs3nLmtrT3vzhoD3co= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/oteltest v1.0.0-RC3 h1:MjaeegZTaX0Bv9uB9CrdVjOFM/8slRjReoWoV9xDCpY= +go.opentelemetry.io/otel/oteltest v1.0.0-RC3/go.mod h1:xpzajI9JBRr7gX63nO6kAmImmYIAtuQblZ36Z+LfCjE= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= -go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/fx v1.21.0 h1:qqD6k7PyFHONffW5speYx403ywanuASqU4Rqdpc22XY= +go.uber.org/fx v1.21.0/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= @@ -326,6 +365,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -370,8 +411,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -379,6 +420,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -403,6 +446,12 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -411,6 +460,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -422,11 +473,14 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/pkg/app/delay.go b/pkg/app/delay.go index 6f2c41b..6efdcc9 100644 --- a/pkg/app/delay.go +++ b/pkg/app/delay.go @@ -51,3 +51,7 @@ func (d *Duration) UnmarshalJSON(data []byte) error { *d = Duration(dur) return nil } + +func (d Duration) String() string { + return time.Duration(d).String() +} diff --git a/pkg/app/handler.go b/pkg/app/handler.go index 712136d..d719a34 100644 --- a/pkg/app/handler.go +++ b/pkg/app/handler.go @@ -1,6 +1,7 @@ package app import ( + "context" "strings" "time" @@ -11,7 +12,7 @@ import ( ) type ServiceMatcher interface { - MatchRequest(Request) MatchResult + MatchRequest(context.Context, Request) MatchResult } type Request struct { @@ -50,7 +51,7 @@ func NewHandler(service ServiceMatcher) *Handler { func (h Handler) All(c *fiber.Ctx) error { req := RequestFromFiber(c.Request()) - res := h.service.MatchRequest(req) + res := h.service.MatchRequest(c.UserContext(), req) if !res.Matched { log.WithFields(log.Fields{ diff --git a/pkg/app/handler_test.go b/pkg/app/handler_test.go index 7fb00b1..56bee69 100644 --- a/pkg/app/handler_test.go +++ b/pkg/app/handler_test.go @@ -1,6 +1,7 @@ package app import ( + "context" "io" "net/http" "net/http/httptest" @@ -88,23 +89,23 @@ func TestRequest(t *testing.T) { } type mockService struct { - mockMatchFunc func(Request) MatchResult + mockMatchFunc func(context.Context, Request) MatchResult } -func (m mockService) MatchRequest(r Request) MatchResult { - return m.mockMatchFunc(r) +func (m mockService) MatchRequest(ctx context.Context, r Request) MatchResult { + return m.mockMatchFunc(ctx, r) } func TestHandleResponse(t *testing.T) { tests := []struct { name string - matchFunc func(Request) MatchResult + matchFunc func(context.Context, Request) MatchResult assertFunc func(*testing.T, *http.Response) }{ { name: "Should send not found response", - matchFunc: func(r Request) MatchResult { + matchFunc: func(ctx context.Context, r Request) MatchResult { return MatchResult{ StatusCode: http.StatusNotFound, Headers: map[string]string{"Content-type": "application/json"}, @@ -124,7 +125,7 @@ func TestHandleResponse(t *testing.T) { }, { name: "Should send non json response", - matchFunc: func(r Request) MatchResult { + matchFunc: func(ctx context.Context, r Request) MatchResult { return MatchResult{ StatusCode: http.StatusOK, Headers: map[string]string{"Content-type": "application/xml"}, @@ -141,7 +142,7 @@ func TestHandleResponse(t *testing.T) { }, { name: "Should send response without body", - matchFunc: func(r Request) MatchResult { + matchFunc: func(ctx context.Context, r Request) MatchResult { return MatchResult{ StatusCode: http.StatusCreated, Headers: map[string]string{"Location": "/users/123"}, diff --git a/pkg/app/matcher.go b/pkg/app/matcher.go index 344a62f..b8bb9d8 100644 --- a/pkg/app/matcher.go +++ b/pkg/app/matcher.go @@ -1,6 +1,7 @@ package app import ( + "context" "strings" ) @@ -16,7 +17,7 @@ func NewMatcher(r *RegexCache, j *JSONPathCache) *Matcher { } } -func (matcher *Matcher) Match(r Request, mappings Mappings, scenarioStates map[string]ScenarioState) (Mapping, bool, bool) { +func (matcher *Matcher) Match(ctx context.Context, r Request, mappings Mappings, scenarioStates map[string]ScenarioState) (Mapping, bool, bool) { methodMappings, ok := mappings[r.Method] if !ok { return Mapping{}, false, false diff --git a/pkg/app/matcher_test.go b/pkg/app/matcher_test.go index 8c4fb9e..956b522 100644 --- a/pkg/app/matcher_test.go +++ b/pkg/app/matcher_test.go @@ -1,6 +1,7 @@ package app import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -163,7 +164,7 @@ func TestMatcher(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mapping, matched, partial := matcher.Match(tt.input, mappings, nil) + mapping, matched, partial := matcher.Match(context.Background(), tt.input, mappings, nil) result := NewMatchResult(&mapping, tt.input, matched, partial) diff --git a/pkg/app/scenario.go b/pkg/app/scenario.go index a55b2c6..67b7246 100644 --- a/pkg/app/scenario.go +++ b/pkg/app/scenario.go @@ -1,6 +1,7 @@ package app import ( + "context" "fmt" "github.com/ohler55/ojg/oj" @@ -70,8 +71,8 @@ func (hand *ScenarioHandler) AddScenario(mapping Mapping) { hand.scenarioMappings.Put(mapping) } -func (hand *ScenarioHandler) MatchScenario(request Request) (Mapping, bool, bool) { - mapping, matched, partial := hand.matcher.Match(request, hand.scenarioMappings, hand.scenarios) +func (hand *ScenarioHandler) MatchScenario(ctx context.Context, request Request) (Mapping, bool, bool) { + mapping, matched, partial := hand.matcher.Match(ctx, request, hand.scenarioMappings, hand.scenarios) if !matched || partial { return Mapping{}, false, false } diff --git a/pkg/app/scenario_test.go b/pkg/app/scenario_test.go index 32387ec..84db49a 100644 --- a/pkg/app/scenario_test.go +++ b/pkg/app/scenario_test.go @@ -1,6 +1,7 @@ package app import ( + "context" "fmt" "testing" @@ -209,7 +210,7 @@ func TestScenarioMatching(t *testing.T) { for i, c := range tt.cases { t.Run(fmt.Sprintf("%d", i+1), func(t *testing.T) { - mapping, matched, partial := handler.MatchScenario(c.request) + mapping, matched, partial := handler.MatchScenario(context.Background(), c.request) got := NewMatchResult(&mapping, c.request, matched, partial) assert.Equal(t, c.expected.Matched, matched) assert.Equal(t, c.expected, got) diff --git a/pkg/app/service.go b/pkg/app/service.go index 4ddd8ae..0ec3a10 100644 --- a/pkg/app/service.go +++ b/pkg/app/service.go @@ -1,9 +1,13 @@ package app import ( + "context" "net/http" + "github.com/dubonzi/mantis/pkg/telemetry" "github.com/ohler55/ojg/oj" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) const ( @@ -78,21 +82,31 @@ func NewService(mappings Mappings, matcher *Matcher, scenarioHandler *ScenarioHa } } -func (s *Service) MatchRequest(r Request) MatchResult { +func (s *Service) MatchRequest(ctx context.Context, r Request) MatchResult { + ctx, span := telemetry.StartSpan( + ctx, + "match_request", + trace.WithSpanKind(trace.SpanKindInternal), + trace.WithAttributes(attribute.String("request_id", r.ID)), + ) + defer span.End() + var mapping Mapping var matched, partial bool - - mapping, matched, partial = s.scenarioHandler.MatchScenario(r) + mapping, matched, partial = s.scenarioHandler.MatchScenario(ctx, r) if !matched { - mapping, matched, partial = s.matcher.Match(r, s.mappings, nil) + mapping, matched, partial = s.matcher.Match(ctx, r, s.mappings, nil) } result := NewMatchResult(&mapping, r, matched, partial) if matched { s.delayer.Apply(&mapping.Response.ResponseDelay) + span.SetAttributes(attribute.String("delay", mapping.Response.ResponseDelay.Fixed.Duration.String())) } + span.SetAttributes(attribute.Bool("matched", matched)) + return result } diff --git a/pkg/app/service_test.go b/pkg/app/service_test.go index c0f1136..b67d348 100644 --- a/pkg/app/service_test.go +++ b/pkg/app/service_test.go @@ -1,6 +1,7 @@ package app import ( + "context" "testing" "time" @@ -69,7 +70,7 @@ func TestService(t *testing.T) { service := NewService(mappings, matcher, NewScenarioHandler(matcher), &delayer) t.Run(tt.name, func(t *testing.T) { - res := service.MatchRequest(tt.request) + res := service.MatchRequest(context.Background(), tt.request) assert.Equal(t, tt.wantResult, res) assert.Equal(t, tt.wantDelay, delayer.FixedCalled) }) diff --git a/cmd/config.go b/pkg/config/config.go similarity index 55% rename from cmd/config.go rename to pkg/config/config.go index a62e73f..3e2cee8 100644 --- a/cmd/config.go +++ b/pkg/config/config.go @@ -1,37 +1,26 @@ -package main +package config import ( "github.com/americanas-go/config" - igzap "github.com/americanas-go/log/contrib/go.uber.org/zap.v1" ) -func loadDefaultConfig() { +func SetDefaultConfig() { config.Add("server.port", 8080, "Server port") config.Add("server.disableStartupMessage", true, "Disable fiber startup message") config.Add("health.port", 8081, "Health endpoint port (must not be the same as the server port)") + config.Add("otel.enabled", true, "Enable/disable Opentelemetry support") + config.Add("otel.exporter.protocol", "http", "Protocol used to export Opentelemetry traces and metrics") + config.Add("otel.exporter.endpoint", "localhost:4318", "Endpoint of the collecter for Opentelemetry traces and metrics") + config.Add("otel.exporter.insecure", true, "Use insecure connection for Opentelemetry exporter") + config.Add("loader.path.mapping", "files/mapping", "Path to the folder containing the mapping files") config.Add("loader.path.response", "files/response", "Path to the folder containing the response files") - config.Add("log.level", "INFO", "Logging level") + config.Add("log.level", "DEBUG", "Logging level") config.Add("log.format", "TEXT", "Logging format") config.Add("fx.log.enable", false, "Enable/disable fx startup log") - -} - -func zapOptions() *igzap.Options { - return &igzap.Options{ - Console: struct { - Enabled bool - Level string - Formatter string - }{ - Enabled: true, - Level: config.String("log.level"), - Formatter: config.String("log.format"), - }, - } } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 0000000..6ed7c2f --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,16 @@ +package config + +import ( + "testing" + + "github.com/americanas-go/config" + "github.com/stretchr/testify/assert" +) + +func TestSetDefaultConfig(t *testing.T) { + SetDefaultConfig() + config.Load() + + assert.Equal(t, "TEXT", config.String("log.format")) + assert.Equal(t, "localhost:4318", config.String("otel.exporter.endpoint")) +} diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go new file mode 100644 index 0000000..ffea2cd --- /dev/null +++ b/pkg/telemetry/telemetry.go @@ -0,0 +1,16 @@ +package telemetry + +import ( + "context" + + "go.opentelemetry.io/otel/trace" +) + +const ( + tracerName = "github.com/dubonzi/mantis" +) + +func StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + span := trace.SpanFromContext(ctx) + return span.TracerProvider().Tracer(tracerName).Start(ctx, name, opts...) +} From e72594086495ba1f92dd5879a5cfea06d1f9f571 Mon Sep 17 00:00:00 2001 From: Eduardo Bonzi Date: Sun, 24 Mar 2024 16:55:05 -0300 Subject: [PATCH 2/2] revert log level --- pkg/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 3e2cee8..9ac9aba 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -19,7 +19,7 @@ func SetDefaultConfig() { config.Add("loader.path.mapping", "files/mapping", "Path to the folder containing the mapping files") config.Add("loader.path.response", "files/response", "Path to the folder containing the response files") - config.Add("log.level", "DEBUG", "Logging level") + config.Add("log.level", "INFO", "Logging level") config.Add("log.format", "TEXT", "Logging format") config.Add("fx.log.enable", false, "Enable/disable fx startup log")