diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index 077d0ada55f..30998ec690a 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -4,7 +4,9 @@ import ( "context" "flag" "fmt" + "os" "path/filepath" + "strconv" "strings" "time" @@ -12,6 +14,7 @@ import ( vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/telemetry" "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/node" @@ -121,10 +124,48 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { ) } +func initTelemetry(ctx context.Context) error { + var options []telemetry.Option + + if os.Getenv("TELEM_METRICS_ENABLED") == "true" { + options = append(options, telemetry.WithOptionMetricsEnabled()) + } + if os.Getenv("TELEM_TRACES_ENABLED") == "true" { + options = append(options, telemetry.WithOptionTracesEnabled()) + } + if portString := os.Getenv("TELEM_PORT"); portString != "" { + port, err := strconv.ParseUint(portString, 10, 64) + if err != nil { + return fmt.Errorf("invalid port: %w", err) + } + + options = append(options, telemetry.WithOptionPort(port)) + } + if os.Getenv("TELEM_USE_FAKE_METRICS") == "true" { + options = append(options, telemetry.WithOptionFakeMetrics()) + } + + // The string options can be added by default. Their absence would yield the same result + // as if the option were excluded altogether. + options = append(options, telemetry.WithOptionMeterName(os.Getenv("TELEM_METER_NAME"))) + options = append(options, telemetry.WithOptionExporterEndpoint(os.Getenv("TELEM_EXPORTER_ENDPOINT"))) + options = append(options, telemetry.WithOptionServiceName(os.Getenv("TELEM_SERVICE_NAME"))) + + return telemetry.Init(ctx, options...) +} + func execStart(c startCfg, args []string) error { rootDir := c.rootDir tmcfg := &c.baseCfg.tmConfig + + // Attempt to initialize telemetry. If the enviroment variables required to initialize + // telemetry are not set, then the initialization will do nothing. + ctx := context.Background() + if err := initTelemetry(ctx); err != nil { + return fmt.Errorf("error initializing telemetry: %w", err) + } + // create priv validator first. // need it to generate genesis.json newPrivValKey := tmcfg.PrivValidatorKeyFile() diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 3585f99d7de..d6c9ed40e4a 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -131,6 +131,7 @@ func NewApp(dataRootDir string, skipFailingGenesisTxs bool, logger log.Logger, m } cfg.Logger = logger + cfg.SkipFailingGenesisTxs = skipFailingGenesisTxs return NewAppWithOptions(cfg) } diff --git a/gno.land/pkg/sdk/vm/handler.go b/gno.land/pkg/sdk/vm/handler.go index accaa70e059..1e45a242d2c 100644 --- a/gno.land/pkg/sdk/vm/handler.go +++ b/gno.land/pkg/sdk/vm/handler.go @@ -4,10 +4,13 @@ import ( "fmt" "strings" + "github.com/gnolang/gno/telemetry" + "github.com/gnolang/gno/telemetry/traces" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/std" + "go.opentelemetry.io/otel/attribute" ) type vmHandler struct { @@ -22,6 +25,17 @@ func NewHandler(vm *VMKeeper) vmHandler { } func (vh vmHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { + if telemetry.TracesEnabled() { + // This is the trace's entry point for the VM namespace, so initialize it with the context. + traces.InitNamespace(ctx.Context(), traces.NamespaceVMProcess) + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "vmHandler.Process", + attribute.String("msg.Type", msg.Type()), + ) + defer spanEnder.End() + } + switch msg := msg.(type) { case MsgAddPackage: return vh.handleMsgAddPackage(ctx, msg) @@ -35,6 +49,17 @@ func (vh vmHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { // Handle MsgAddPackage. func (vh vmHandler) handleMsgAddPackage(ctx sdk.Context, msg MsgAddPackage) sdk.Result { + if telemetry.TracesEnabled() { + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "vmHandler.handleMsgAddPackage", + attribute.String("msg.Creator", msg.Creator.String()), + attribute.String("msg.Package.Path", msg.Package.Path), + attribute.String("msg.Deposit", msg.Deposit.String()), + ) + defer spanEnder.End() + } + amount, err := std.ParseCoins("1000000ugnot") // XXX calculate if err != nil { return abciResult(err) @@ -52,6 +77,18 @@ func (vh vmHandler) handleMsgAddPackage(ctx sdk.Context, msg MsgAddPackage) sdk. // Handle MsgCall. func (vh vmHandler) handleMsgCall(ctx sdk.Context, msg MsgCall) (res sdk.Result) { + if telemetry.TracesEnabled() { + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "vmHandler.handleMsgCall", + attribute.String("msg.Caller", msg.Caller.String()), + attribute.String("msg.PkgPath", msg.PkgPath), + attribute.String("msg.Func", msg.Func), + attribute.StringSlice("msg.Args", msg.Args), + ) + defer spanEnder.End() + } + amount, err := std.ParseCoins("1000000ugnot") // XXX calculate if err != nil { return abciResult(err) @@ -91,6 +128,17 @@ const ( ) func (vh vmHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + if telemetry.TracesEnabled() { + traces.InitNamespace(ctx.Context(), traces.NamespaceVMQuery) + spanEnder := traces.StartSpan( + traces.NamespaceVMQuery, + "vmHandler.Query", + attribute.String("req.Path", req.Path), + attribute.String("req.Data", string(req.Data)), + ) + defer spanEnder.End() + } + switch secondPart(req.Path) { case QueryPackage: return vh.queryPackage(ctx, req) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 6f695e98558..6d35c7b59c0 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -9,6 +9,8 @@ import ( gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" + "github.com/gnolang/gno/telemetry" + "github.com/gnolang/gno/telemetry/traces" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" @@ -70,6 +72,16 @@ func (vm *VMKeeper) Initialize(ms store.MultiStore) { if vm.gnoStore != nil { panic("should not happen") } + + if telemetry.TracesEnabled() { + traces.InitNamespace(nil, traces.NamespaceVMInit) + spanEnder := traces.StartSpan( + traces.NamespaceVMInit, + "VMKeeper.Initialize", + ) + defer spanEnder.End() + } + alloc := gno.NewAllocator(maxAllocTx) baseSDKStore := ms.GetStore(vm.baseKey) iavlSDKStore := ms.GetStore(vm.iavlKey) @@ -97,6 +109,15 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { if vm.gnoStore == nil { panic("VMKeeper must first be initialized") } + + if telemetry.TracesEnabled() { + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "VMKeeper.getGnoStore", + ) + defer spanEnder.End() + } + switch ctx.Mode() { case sdk.RunTxModeDeliver: // swap sdk store of existing gnoStore. @@ -195,6 +216,14 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { // Calls calls a public Gno function (for delivertx). func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { + if telemetry.TracesEnabled() { + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "VMKeeper.Call", + ) + defer spanEnder.End() + } + pkgPath := msg.PkgPath // to import fnc := msg.Func store := vm.getGnoStore(ctx) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 94232e014d2..538eadb7964 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -12,8 +12,11 @@ import ( "sync" "testing" + "github.com/gnolang/gno/telemetry" + "github.com/gnolang/gno/telemetry/traces" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/std" + "go.opentelemetry.io/otel/attribute" ) //---------------------------------------- @@ -603,6 +606,14 @@ func (m *Machine) RunMain() { // Input must not have been preprocessed, that is, // it should not be the child of any parent. func (m *Machine) Eval(x Expr) []TypedValue { + if telemetry.TracesEnabled() { + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "Machine.Eval", + ) + defer spanEnder.End() + } + if debug { m.Printf("Machine.Eval(%v)\n", x) } @@ -1019,13 +1030,36 @@ const ( // main run loop. func (m *Machine) Run() { + var spanEnder *traces.SpanEnder + if telemetry.TracesEnabled() { + // Ensure that spanEnder.End() is called on panic. + defer func() { + if r := recover(); r != nil { + spanEnder.End() + panic(r) + } + }() + } + for { op := m.PopOp() + + if telemetry.TracesEnabled() { + spanEnder.End() + + spanEnder = traces.StartSpan( + traces.NamespaceVM, + "Machine.Run", + attribute.String("op", opToStringMap[op]), + ) + } + // TODO: this can be optimized manually, even into tiers. switch op { /* Control operators */ case OpHalt: m.incrCPU(OpCPUHalt) + spanEnder.End() return case OpNoop: m.incrCPU(OpCPUNoop) @@ -1345,6 +1379,9 @@ func (m *Machine) Run() { panic(fmt.Sprintf("unexpected opcode %s", op.String())) } } + + // Uncomment this if this code ever becomes reachable. + // spanEnder.End() } //---------------------------------------- diff --git a/gnovm/pkg/gnolang/misc.go b/gnovm/pkg/gnolang/misc.go index a05de8c74aa..109fd595196 100644 --- a/gnovm/pkg/gnolang/misc.go +++ b/gnovm/pkg/gnolang/misc.go @@ -167,3 +167,127 @@ func DerivePkgAddr(pkgPath string) crypto.Address { // NOTE: must not collide with pubkey addrs. return crypto.AddressFromPreimage([]byte("pkgPath:" + pkgPath)) } + +var opToStringMap = map[Op]string{ + /* Control operators */ + OpInvalid: "OpInvalid", + OpHalt: "OpHalt", + OpNoop: "OpNoop", + OpExec: "OpExec", + OpPrecall: "OpPrecall", + OpCall: "OpCall", + OpCallNativeBody: "OpCallNativeBody", + OpReturn: "OpReturn", + OpReturnFromBlock: "OpReturnFromBlock", + OpReturnToBlock: "OpReturnToBlock", + OpDefer: "OpDefer", + OpCallDeferNativeBody: "OpCallDeferNativeBody", + OpGo: "OpGo", + OpSelect: "OpSelect", + OpSwitchClause: "OpSwitchClause", + OpSwitchClauseCase: "OpSwitchClauseCase", + OpTypeSwitch: "OpTypeSwitch", + OpIfCond: "OpIfCond", + OpPopValue: "OpPopValue", + OpPopResults: "OpPopResults", + OpPopBlock: "OpPopBlock", + OpPopFrameAndReset: "OpPopFrameAndReset", + OpPanic1: "OpPanic1", + OpPanic2: "OpPanic2", + + /* Unary & binary operators */ + OpUpos: "OpUpos", + OpUneg: "OpUneg", + OpUnot: "OpUnot", + OpUxor: "OpUxor", + OpUrecv: "OpUrecv", + OpLor: "OpLor", + OpLand: "OpLand", + OpEql: "OpEql", + OpNeq: "OpNeq", + OpLss: "OpLss", + OpLeq: "OpLeq", + OpGtr: "OpGtr", + OpGeq: "OpGeq", + OpAdd: "OpAdd", + OpSub: "OpSub", + OpBor: "OpBor", + OpXor: "OpXor", + OpMul: "OpMul", + OpQuo: "OpQuo", + OpRem: "OpRem", + OpShl: "OpShl", + OpShr: "OpShr", + OpBand: "OpBand", + OpBandn: "OpBandn", + + /* Other expression operators */ + OpEval: "OpEval", + OpBinary1: "OpBinary1", + OpIndex1: "OpIndex1", + OpIndex2: "OpIndex2", + OpSelector: "OpSelector", + OpSlice: "OpSlice", + OpStar: "OpStar", + OpRef: "OpRef", + OpTypeAssert1: "OpTypeAssert1", + OpTypeAssert2: "OpTypeAssert2", + OpStaticTypeOf: "OpStaticTypeOf", + OpCompositeLit: "OpCompositeLit", + OpArrayLit: "OpArrayLit", + OpSliceLit: "OpSliceLit", + OpSliceLit2: "OpSliceLit2", + OpMapLit: "OpMapLit", + OpStructLit: "OpStructLit", + OpFuncLit: "OpFuncLit", + OpConvert: "OpConvert", + + /* Native operators */ + OpArrayLitGoNative: "OpArrayLitGoNative", + OpSliceLitGoNative: "OpSliceLitGoNative", + OpStructLitGoNative: "OpStructLitGoNative", + OpCallGoNative: "OpCallGoNative", + + /* Type operators */ + OpFieldType: "OpFieldType", + OpArrayType: "OpArrayType", + OpSliceType: "OpSliceType", + OpPointerType: "OpPointerType", + OpInterfaceType: "OpInterfaceType", + OpChanType: "OpChanType", + OpFuncType: "OpFuncType", + OpMapType: "OpMapType", + OpStructType: "OpStructType", + OpMaybeNativeType: "OpMaybeNativeType", + + /* Statement operators */ + OpAssign: "OpAssign", + OpAddAssign: "OpAddAssign", + OpSubAssign: "OpSubAssign", + OpMulAssign: "OpMulAssign", + OpQuoAssign: "OpQuoAssign", + OpRemAssign: "OpRemAssign", + OpBandAssign: "OpBandAssign", + OpBandnAssign: "OpBandnAssign", + OpBorAssign: "OpBorAssign", + OpXorAssign: "OpXorAssign", + OpShlAssign: "OpShlAssign", + OpShrAssign: "OpShrAssign", + OpDefine: "OpDefine", + OpInc: "OpInc", + OpDec: "OpDec", + + /* Decl operators */ + OpValueDecl: "OpValueDecl", + OpTypeDecl: "OpTypeDecl", + + /* Loop (sticky) operators (>= 0xD0) */ + OpSticky: "OpSticky", + OpBody: "OpBody", + OpForLoop: "OpForLoop", + OpRangeIter: "OpRangeIter", + OpRangeIterString: "OpRangeIterString", + OpRangeIterMap: "OpRangeIterMap", + OpRangeIterArrayPtr: "OpRangeIterArrayPtr", + OpReturnCallDefers: "OpReturnCallDefers", +} diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e02a158fcf1..30493a9e1c9 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -5,7 +5,10 @@ import ( "math/big" "reflect" + "github.com/gnolang/gno/telemetry" + "github.com/gnolang/gno/telemetry/traces" "github.com/gnolang/gno/tm2/pkg/errors" + "go.opentelemetry.io/otel/attribute" ) // In the case of a *FileSet, some declaration steps have to happen @@ -126,6 +129,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { }() } + if telemetry.TracesEnabled() { + spanEnder := traces.StartSpan( + traces.NamespaceVM, + "Preprocess", + attribute.Int("preprocessing", preprocessing), + ) + defer spanEnder.End() + } + if ctx == nil { // Generally a ctx is required, but if not, it's ok to pass in nil. // panic("Preprocess requires context") diff --git a/go.mod b/go.mod index 06329b2f02d..9eb8ed807d5 100644 --- a/go.mod +++ b/go.mod @@ -31,42 +31,56 @@ require ( github.com/stretchr/testify v1.8.4 github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c go.etcd.io/bbolt v1.3.7 + go.opentelemetry.io/otel v1.22.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.45.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 + go.opentelemetry.io/otel/metric v1.22.0 + go.opentelemetry.io/otel/sdk v1.22.0 + go.opentelemetry.io/otel/sdk/metric v1.22.0 + go.opentelemetry.io/otel/trace v1.22.0 go.uber.org/multierr v1.9.0 - golang.org/x/crypto v0.13.0 + golang.org/x/crypto v0.14.0 golang.org/x/mod v0.12.0 - golang.org/x/net v0.15.0 - golang.org/x/term v0.12.0 + golang.org/x/net v0.17.0 + golang.org/x/term v0.13.0 golang.org/x/tools v0.6.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) require ( + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect github.com/gdamore/encoding v1.0.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/klauspost/compress v1.12.3 // indirect - github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/lucasb-eyer/go-colorful v1.0.3 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect go.opencensus.io v0.22.5 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.13.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect ) diff --git a/go.sum b/go.sum index 77c72cfab69..8abe2364632 100644 --- a/go.sum +++ b/go.sum @@ -18,10 +18,13 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +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/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= @@ -29,7 +32,6 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -61,10 +63,16 @@ github.com/gnolang/goleveldb v0.0.9 h1:Q7rGko9oXMKtQA+Apeeed5a3sjba/mcDhzJGoTVLC github.com/gnolang/goleveldb v0.0.9/go.mod h1:Dz6p9bmpy/FBESTgduiThZt5mToVDipcHGzj/zUOo8E= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= +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/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -80,8 +88,8 @@ github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6 github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= @@ -95,6 +103,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gotuna/gotuna v0.6.0 h1:N1lQKXEi/lwRp8u3sccTYLhzOffA4QasExz/1M5Riws= github.com/gotuna/gotuna v0.6.0/go.mod h1:F/ecRt29ChB6Ycy1AFIBpBiMNK0j7Heq+gFbLWquhjc= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -110,12 +120,10 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= @@ -179,8 +187,27 @@ go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.45.0 h1:tfil6di0PoNV7FZdsCS7A5izZoVVQ7AuXtyekbOpG/I= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.45.0/go.mod h1:AKFZIEPOnqB00P63bTjOiah4ZTaRzl1TKwUWpZdYUHI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/sdk/metric v1.22.0 h1:ARrRetm1HCVxq0cbnaZQlfwODYJHo3gFL8Z3tSmHBcI= +go.opentelemetry.io/otel/sdk/metric v1.22.0/go.mod h1:KjQGeMIDlBNEOo6HvjhxIec1p/69/kULDcp4gr0oLQQ= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -189,8 +216,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -208,8 +235,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -227,10 +254,10 @@ golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +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/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= @@ -253,16 +280,22 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/telemetry/exporter/error.go b/telemetry/exporter/error.go new file mode 100644 index 00000000000..5df14f0dba3 --- /dev/null +++ b/telemetry/exporter/error.go @@ -0,0 +1,5 @@ +package exporter + +import "errors" + +var ErrEndpointNotSet = errors.New("telemetry exporter endpoint not set") diff --git a/telemetry/init.go b/telemetry/init.go new file mode 100644 index 00000000000..6b54dc3a99a --- /dev/null +++ b/telemetry/init.go @@ -0,0 +1,57 @@ +package telemetry + +// Inspired by the example here: +// https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go + +import ( + "context" + + "github.com/gnolang/gno/telemetry/metrics" + "github.com/gnolang/gno/telemetry/options" + "github.com/gnolang/gno/telemetry/traces" +) + +const ( + defaultMeterName = "gno.land" + defaultServiceName = "gno.land" + defaultPort uint64 = 4591 +) + +var config options.Config + +// MetricsEnabled returns true if metrics have been initialized. +func MetricsEnabled() bool { + return config.MetricsEnabled +} + +// TracesEnabled returns true if traces have been initialized. +func TracesEnabled() bool { + return config.TracesEnabled +} + +// Init can indicate both, either, or none of metrics and tracing depending on the options provided. +func Init(ctx context.Context, options ...Option) error { + + config.Port = defaultPort + config.MeterName = defaultMeterName + config.ServiceName = defaultServiceName + for _, opt := range options { + opt(&config) + } + + // Initialize metrics to be collected. + if config.MetricsEnabled { + if err := metrics.Init(ctx, config); err != nil { + return err + } + } + + // Tracing initialization. + if config.TracesEnabled { + if err := traces.Init(config); err != nil { + return err + } + } + + return nil +} diff --git a/telemetry/metrics/init.go b/telemetry/metrics/init.go new file mode 100644 index 00000000000..e812f480a8e --- /dev/null +++ b/telemetry/metrics/init.go @@ -0,0 +1,113 @@ +package metrics + +import ( + "context" + "math/rand" + + "github.com/gnolang/gno/telemetry/exporter" + "github.com/gnolang/gno/telemetry/options" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/metric" + sdkMetric "go.opentelemetry.io/otel/sdk/metric" +) + +var ( + ctx context.Context + + // Metrics. + BroadcastTxTimer Int64Collector + BuildBlockTimer Int64Collector +) + +func Init(setCtx context.Context, config options.Config) error { + if config.ExporterEndpoint == "" { + return exporter.ErrEndpointNotSet + } + + ctx = setCtx + + // Use oltp metric exporter + exporter, err := otlpmetricgrpc.New( + ctx, + otlpmetricgrpc.WithEndpoint(config.ExporterEndpoint), + otlpmetricgrpc.WithInsecure(), + ) + if err != nil { + return err + } + + provider := sdkMetric.NewMeterProvider(sdkMetric.WithReader(sdkMetric.NewPeriodicReader(exporter))) + otel.SetMeterProvider(provider) + meter := provider.Meter(config.MeterName) + + broadcastTxTimer, err := meter.Int64Histogram( + "broadcast_tx_hist", + metric.WithDescription("broadcast tx duration"), + // metric.WithExplicitBucketBoundaries(0, 16, 32, 64, 128, 256, 512), + metric.WithUnit("ms"), + ) + if err != nil { + return err + } + BroadcastTxTimer = Int64Histogram{ + Int64Histogram: broadcastTxTimer, + useFakeMetrics: config.UseFakeMetrics, + fakeRangeStart: 5, + fakeRangeEnd: 250, + } + + buildBlockTimer, err := meter.Int64Histogram( + "build_block_hist", + metric.WithDescription("block build duration"), + // metric.WithExplicitBucketBoundaries(0, 16, 32, 64, 128, 256, 512), + metric.WithUnit("ms"), + ) + if err != nil { + return err + } + BuildBlockTimer = Int64Histogram{ + Int64Histogram: buildBlockTimer, + useFakeMetrics: config.UseFakeMetrics, + fakeRangeStart: 0, + fakeRangeEnd: 150, + } + + return nil +} + +type Int64Collector interface { + Collect(int64) +} + +type Int64Histogram struct { + metric.Int64Histogram + + useFakeMetrics bool + fakeRangeStart int64 + fakeRangeEnd int64 +} + +func (h Int64Histogram) Collect(value int64) { + if h.useFakeMetrics { + value = rand.Int63n(h.fakeRangeEnd) + h.fakeRangeStart + } + + h.Int64Histogram.Record(ctx, value) +} + +type Int64Counter struct { + metric.Int64Counter + + useFakeMetrics bool + fakeRangeStart int64 + fakeRangeEnd int64 +} + +func (c Int64Counter) Collect(value int64) { + if c.useFakeMetrics { + value = rand.Int63n(c.fakeRangeEnd) + c.fakeRangeStart + } + + c.Int64Counter.Add(ctx, value) +} diff --git a/telemetry/options.go b/telemetry/options.go new file mode 100644 index 00000000000..fe3b7672dfa --- /dev/null +++ b/telemetry/options.go @@ -0,0 +1,55 @@ +package telemetry + +import "github.com/gnolang/gno/telemetry/options" + +type Option func(*options.Config) + +func WithOptionMetricsEnabled() Option { + return func(c *options.Config) { + c.MetricsEnabled = true + } +} + +func WithOptionTracesEnabled() Option { + return func(c *options.Config) { + c.TracesEnabled = true + } +} + +func WithOptionPort(port uint64) Option { + return func(c *options.Config) { + if c.Port != 0 { + c.Port = port + } + } +} + +func WithOptionMeterName(meterName string) Option { + return func(c *options.Config) { + if c.MeterName != "" { + c.MeterName = meterName + } + } +} + +func WithOptionExporterEndpoint(exporterEndpoint string) Option { + return func(c *options.Config) { + if c.ExporterEndpoint != "" { + c.ExporterEndpoint = exporterEndpoint + } + } +} + +func WithOptionFakeMetrics() Option { + return func(c *options.Config) { + c.UseFakeMetrics = true + } +} + +func WithOptionServiceName(serviceName string) Option { + return func(c *options.Config) { + if c.ServiceName != "" { + c.ServiceName = serviceName + } + } +} diff --git a/telemetry/options/config.go b/telemetry/options/config.go new file mode 100644 index 00000000000..d8e45909450 --- /dev/null +++ b/telemetry/options/config.go @@ -0,0 +1,11 @@ +package options + +type Config struct { + MetricsEnabled bool + TracesEnabled bool + UseFakeMetrics bool + Port uint64 + MeterName string + ServiceName string + ExporterEndpoint string +} diff --git a/telemetry/traces/init.go b/telemetry/traces/init.go new file mode 100644 index 00000000000..3fa7d1093f5 --- /dev/null +++ b/telemetry/traces/init.go @@ -0,0 +1,64 @@ +package traces + +import ( + "context" + "log" + + "github.com/gnolang/gno/telemetry/exporter" + "github.com/gnolang/gno/telemetry/options" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "google.golang.org/grpc/credentials" + + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +func Init(config options.Config) error { + + if config.ExporterEndpoint == "" { + return exporter.ErrEndpointNotSet + } + + // TODO: support secure + var secure bool + secureOption := otlptracegrpc.WithInsecure() + + if secure { + secureOption = otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, "")) + } + + exporter, err := otlptrace.New( + context.Background(), + otlptracegrpc.NewClient( + secureOption, + otlptracegrpc.WithEndpoint(config.ExporterEndpoint), + ), + ) + if err != nil { + log.Fatalf("Failed to create exporter: %v", err) + } + + resources, err := resource.New( + context.Background(), + resource.WithAttributes( + attribute.String("service.name", config.ServiceName), + attribute.String("library.language", "go"), + ), + ) + if err != nil { + return err + } + + otel.SetTracerProvider( + sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(resources), + ), + ) + + return nil +} diff --git a/telemetry/traces/namespace.go b/telemetry/traces/namespace.go new file mode 100644 index 00000000000..e0ba7a67d07 --- /dev/null +++ b/telemetry/traces/namespace.go @@ -0,0 +1,47 @@ +package traces + +import ( + "context" + "fmt" + "runtime" + "strconv" + "strings" +) + +type namespace string + +type namespaceContext struct { + namespace namespace + ctx context.Context +} + +const ( + NamespaceVMInit namespace = "vmInit" + NamespaceVMProcess namespace = "vmProcess" + NamespaceVMQuery namespace = "vmQuery" + + // deprecated -- need to remove references + NamespaceVM namespace = "vm" +) + +// Maps goroutine number to namespace and context. +var namespaces = make(map[int]namespaceContext) + +func InitNamespace(ctx context.Context, ns namespace) { + if ctx == nil { + ctx = context.Background() + } + + namespaces[goroutineID()] = namespaceContext{namespace: ns, ctx: ctx} +} + +func goroutineID() int { + var buf [64]byte + n := runtime.Stack(buf[:], false) + idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0] + id, err := strconv.Atoi(idField) + if err != nil { + panic(fmt.Sprintf("cannot get goroutine id: %v", err)) + } + return id +} diff --git a/telemetry/traces/span.go b/telemetry/traces/span.go new file mode 100644 index 00000000000..6597bab5f3e --- /dev/null +++ b/telemetry/traces/span.go @@ -0,0 +1,47 @@ +package traces + +import ( + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +type SpanEnder struct { + goroutineID int + parentNamespaceCtx namespaceContext + span trace.Span +} + +func (s *SpanEnder) End() { + if s == nil { + return + } + + namespaces[s.goroutineID] = s.parentNamespaceCtx + s.span.End() +} + +func StartSpan( + _ namespace, + name string, + attributes ...attribute.KeyValue, +) *SpanEnder { + id := goroutineID() + parentNamespaceCtx := namespaces[id] + + spanCtx, span := otel.GetTracerProvider().Tracer("gno.land").Start( + parentNamespaceCtx.ctx, + name, + trace.WithAttributes(attribute.String("component", string(parentNamespaceCtx.namespace))), + trace.WithAttributes(attributes...), + ) + + spanEnder := &SpanEnder{ + goroutineID: id, + parentNamespaceCtx: parentNamespaceCtx, + span: span, + } + + namespaces[id] = namespaceContext{namespace: parentNamespaceCtx.namespace, ctx: spanCtx} + return spanEnder +} diff --git a/tm2/pkg/bft/consensus/state.go b/tm2/pkg/bft/consensus/state.go index 988a455f117..f790089e46c 100644 --- a/tm2/pkg/bft/consensus/state.go +++ b/tm2/pkg/bft/consensus/state.go @@ -9,6 +9,8 @@ import ( "sync" "time" + "github.com/gnolang/gno/telemetry" + "github.com/gnolang/gno/telemetry/metrics" "github.com/gnolang/gno/tm2/pkg/amino" cnscfg "github.com/gnolang/gno/tm2/pkg/bft/consensus/config" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" @@ -985,6 +987,13 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts return } + if telemetry.MetricsEnabled() { + startTime := time.Now() + defer func(t time.Time) { + metrics.BuildBlockTimer.Collect(time.Since(t).Milliseconds()) + }(startTime) + } + proposerAddr := cs.privValidator.GetPubKey().Address() return cs.blockExec.CreateProposalBlock(cs.Height, cs.state, commit, proposerAddr) } diff --git a/tm2/pkg/p2p/switch.go b/tm2/pkg/p2p/switch.go index 1f693544d5a..85ded2cb880 100644 --- a/tm2/pkg/p2p/switch.go +++ b/tm2/pkg/p2p/switch.go @@ -6,6 +6,8 @@ import ( "sync" "time" + "github.com/gnolang/gno/telemetry" + "github.com/gnolang/gno/telemetry/metrics" "github.com/gnolang/gno/tm2/pkg/cmap" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/p2p/config" @@ -242,6 +244,7 @@ func (sw *Switch) OnStop() { // // NOTE: Broadcast uses goroutines, so order of broadcast may not be preserved. func (sw *Switch) Broadcast(chID byte, msgBytes []byte) chan bool { + startTime := time.Now() sw.Logger.Debug("Broadcast", "channel", chID, "msgBytes", fmt.Sprintf("%X", msgBytes)) peers := sw.peers.List() @@ -260,6 +263,9 @@ func (sw *Switch) Broadcast(chID byte, msgBytes []byte) chan bool { go func() { wg.Wait() close(successChan) + if telemetry.MetricsEnabled() { + metrics.BroadcastTxTimer.Collect(time.Since(startTime).Milliseconds()) + } }() return successChan