From cd467ae20d8d573d85dd91808881a92736228770 Mon Sep 17 00:00:00 2001 From: dmathieu <42@dmathieu.com> Date: Thu, 19 Sep 2024 11:07:05 +0200 Subject: [PATCH] setup collector receiver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Rühsen --- collector/factory.go | 45 ++++++ collector/factory_test.go | 50 +++++++ collector/internal/config.go | 95 ++++++++++++ collector/internal/controller.go | 244 +++++++++++++++++++++++++++++++ collector/internal/helpers.go | 236 ++++++++++++++++++++++++++++++ go.mod | 46 ++++-- go.sum | 132 ++++++++++++++--- 7 files changed, 821 insertions(+), 27 deletions(-) create mode 100644 collector/factory.go create mode 100644 collector/factory_test.go create mode 100644 collector/internal/config.go create mode 100644 collector/internal/controller.go create mode 100644 collector/internal/helpers.go diff --git a/collector/factory.go b/collector/factory.go new file mode 100644 index 00000000..6fac7a43 --- /dev/null +++ b/collector/factory.go @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package collector + +import ( + "context" + "errors" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer/consumerprofiles" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receiverprofiles" + + "github.com/open-telemetry/opentelemetry-ebpf-profiler/collector/internal" +) + +var ( + typeStr = component.MustNewType("otelreceiver") + + errInvalidConfig = errors.New("invalid config") +) + +// NewFactory creates a factory for the receiver. +func NewFactory() receiver.Factory { + return receiver.NewFactory( + typeStr, + internal.CreateDefaultConfig, + receiverprofiles.WithProfiles(createProfilesReceiver, component.StabilityLevelAlpha)) +} + +func createProfilesReceiver( + _ context.Context, + params receiver.Settings, // nolint:gocritic // we must respect the collector API + baseCfg component.Config, + nextConsumer consumerprofiles.Profiles) (receiverprofiles.Profiles, error) { + logger := params.Logger + cfg, ok := baseCfg.(*internal.Config) + if !ok { + return nil, errInvalidConfig + } + + rcvr := internal.NewController(logger, nextConsumer, cfg) + return rcvr, nil +} diff --git a/collector/factory_test.go b/collector/factory_test.go new file mode 100644 index 00000000..6212d9d2 --- /dev/null +++ b/collector/factory_test.go @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package collector + +import ( + "context" + "testing" + + "github.com/open-telemetry/opentelemetry-ebpf-profiler/collector/internal" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestNewFactory(t *testing.T) { + f := NewFactory() + require.NotNil(t, f) +} + +func TestCreateProfilesReceiver(t *testing.T) { + for _, tt := range []struct { + name string + config component.Config + + wantError error + }{ + { + name: "Default config", + config: internal.CreateDefaultConfig(), + }, + { + name: "Nil config", + wantError: errInvalidConfig, + }, + } { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + _, err := createProfilesReceiver( + context.Background(), + receivertest.NewNopSettings(), + tt.config, + consumertest.NewNop(), + ) + require.ErrorIs(t, err, tt.wantError) + }) + } +} diff --git a/collector/internal/config.go b/collector/internal/config.go new file mode 100644 index 00000000..18f17b9e --- /dev/null +++ b/collector/internal/config.go @@ -0,0 +1,95 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "errors" + "fmt" + "time" + + log "github.com/sirupsen/logrus" + "github.com/tklauser/numcpus" + "go.opentelemetry.io/collector/component" + + tracertypes "github.com/open-telemetry/opentelemetry-ebpf-profiler/tracer/types" +) + +const ( + defaultProjectID = "1" + defaultHostID = 0x1234 +) + +// Config represents the receiver config settings within the collector's config.yaml +type Config struct { + ProjectID string `mapstructure:"project-id"` + HostID uint64 `mapstructure:"host-id"` + SecretToken string `mapstructure:"secret-token"` + CollectionAgent string `mapstructure:"collection-agent"` + Tracers string `mapstructure:"tracers"` + Tags string `mapstructure:"tags"` + BpfVerifierLogSize int `mapstructure:"bpf-log-size"` + BpfVerifierLogLevel uint `mapstructure:"bpf-log-level"` + MapScaleFactor uint8 `mapstructure:"map-scale-factor"` + Verbose bool `mapstructure:"verbose"` + DisableTLS bool `mapstructure:"disable-tls"` + NoKernelVersionCheck bool `mapstructure:"no-kernel-version-check"` + ProbabilisticThreshold uint `mapstructure:"probabilistic-threshold"` + ProbabilisticInterval time.Duration `mapstructure:"probabilistic-interval"` + EnvironmentType string `mapstructure:"environment-type"` + ReporterInterval time.Duration `mapstructure:"reporter-interval"` + MonitorInterval time.Duration `mapstructure:"monitor-interval"` + SamplesPerSecond int `mapstructure:"samples-per-second"` + SendErrorFrames bool `mapstructure:"send-error-frames"` + + // Written in CreateDefaultConfig() + PresentCPUCores int +} + +// Validate checks if the receiver configuration is valid. +func (cfg *Config) Validate() error { + if cfg.ReporterInterval.Seconds() < 1 { + return errors.New("the interval has to be set to at least 1 second (1s)") + } + + if cfg.ProjectID == "" { + return errors.New("projectid must be set") + } + + if cfg.PresentCPUCores <= 0 { + return errors.New("failed to determine number of CPUs") + } + + if cfg.SamplesPerSecond <= 0 { + return errors.New("samples per second must be > 0") + } + + if _, err := tracertypes.Parse(cfg.Tracers); err != nil { + return fmt.Errorf("failed to parse tracers '%s': %v", cfg.Tracers, err) + } + + // todo: Add more validation + + return nil +} + +func CreateDefaultConfig() component.Config { + presentCores, err := numcpus.GetPresent() + if err != nil { + log.Errorf("Failed to read CPU file: %v", err) + } + + // todo: export default values (currently in main.go) + return &Config{ + ProjectID: defaultProjectID, + HostID: defaultHostID, + ReporterInterval: 5 * time.Second, + MonitorInterval: 5 * time.Second, + SamplesPerSecond: 20, + ProbabilisticInterval: 1 * time.Minute, + ProbabilisticThreshold: 100, + CollectionAgent: "127.0.0.1:11000", // devfiler + Tracers: "all", + PresentCPUCores: presentCores, + } +} diff --git a/collector/internal/controller.go b/collector/internal/controller.go new file mode 100644 index 00000000..db7e7dc0 --- /dev/null +++ b/collector/internal/controller.go @@ -0,0 +1,244 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "context" + "fmt" + "os" + "time" + + "github.com/sirupsen/logrus" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer/consumerprofiles" + "go.uber.org/zap" + + hostinfo "github.com/open-telemetry/opentelemetry-ebpf-profiler/host" + "github.com/open-telemetry/opentelemetry-ebpf-profiler/reporter" + "github.com/open-telemetry/opentelemetry-ebpf-profiler/times" + "github.com/open-telemetry/opentelemetry-ebpf-profiler/tracehandler" + "github.com/open-telemetry/opentelemetry-ebpf-profiler/tracer" + tracertypes "github.com/open-telemetry/opentelemetry-ebpf-profiler/tracer/types" + "github.com/open-telemetry/opentelemetry-ebpf-profiler/util" +) + +var ( + agentShutdown = func() {} +) + +type Controller struct { + host component.Host + cancel context.CancelFunc + logger *zap.Logger + nextConsumer consumerprofiles.Profiles + config *Config +} + +func NewController(logger *zap.Logger, nextConsumer consumerprofiles.Profiles, + cfg *Config) *Controller { + return &Controller{ + logger: logger, + nextConsumer: nextConsumer, + config: cfg, + } +} + +// Start starts the receiver. +func (c *Controller) Start(ctx context.Context, host component.Host) error { + cfg := c.config + + if cfg.Verbose { + // logrus is used in the agent code, so we need to set the log level here. + // todo: make the logger configurable + logrus.SetLevel(logrus.DebugLevel) + } + + log := c.logger.Sugar() + + c.host = host + if ctx == nil { + ctx = context.Background() + } + ctx, c.cancel = context.WithCancel(ctx) + + if err := tracer.ProbeBPFSyscall(); err != nil { + return fmt.Errorf("failed to probe eBPF syscall: %v", err) + } + + if err := tracer.ProbeTracepoint(); err != nil { + return fmt.Errorf("failed to probe tracepoint: %v", err) + } + + log.Debug("Determining tracers to include") + includeTracers, err := tracertypes.Parse(cfg.Tracers) + if err != nil { + return fmt.Errorf("failed to parse the included tracers: %v", err) + } + + kernelVersion, err := getKernelVersion() + if err != nil { + return fmt.Errorf("failed to get Linux kernel version: %v", err) + } + + intervals := times.New(cfg.MonitorInterval, cfg.ReporterInterval, cfg.ProbabilisticInterval) + + traceHandlerCacheSize := + traceCacheSize(cfg.MonitorInterval, cfg.SamplesPerSecond, cfg.PresentCPUCores) + + log.Debugf("Collection agent: %s", cfg.CollectionAgent) + + // hostname and sourceIP will be populated from the root namespace. + var hostname, sourceIP string + + if err = runInRootNS(func() error { + var hostnameErr error + hostname, hostnameErr = os.Hostname() + if hostnameErr != nil { + return fmt.Errorf("failed to get hostname: %v", hostnameErr) + } + + srcIP, ipErr := getSourceIPAddress(cfg.CollectionAgent) + if ipErr != nil { + return fmt.Errorf("failed to get source IP: %v", ipErr) + } + sourceIP = srcIP.String() + return nil + }); err != nil { + log.Warnf("Failed to fetch metadata information in the root namespace: %v", err) + } + + // Connect to the collection agent and start reporting. + rep, err := reporter.Start(ctx, &reporter.Config{ + CollAgentAddr: cfg.CollectionAgent, + DisableTLS: cfg.DisableTLS, + MaxRPCMsgSize: 32 << 20, // 32 MiB + MaxGRPCRetries: 5, + GRPCOperationTimeout: intervals.GRPCOperationTimeout(), + GRPCStartupBackoffTime: intervals.GRPCStartupBackoffTime(), + GRPCConnectionTimeout: intervals.GRPCConnectionTimeout(), + ReportInterval: intervals.ReportInterval(), + CacheSize: traceHandlerCacheSize, + SamplesPerSecond: cfg.SamplesPerSecond, + HostID: cfg.HostID, + KernelVersion: kernelVersion, + HostName: hostname, + IPAddress: sourceIP, + }) + if err != nil { + return fmt.Errorf("failed to start reporting: %v", err) + } + + // Load the eBPF code and map definitions + trc, err := tracer.NewTracer(ctx, &tracer.Config{ + Reporter: rep, + Intervals: intervals, + IncludeTracers: includeTracers, + FilterErrorFrames: !cfg.SendErrorFrames, + SamplesPerSecond: cfg.SamplesPerSecond, + MapScaleFactor: int(cfg.MapScaleFactor), + KernelVersionCheck: !cfg.NoKernelVersionCheck, + BPFVerifierLogLevel: uint32(cfg.BpfVerifierLogLevel), + BPFVerifierLogSize: cfg.BpfVerifierLogSize, + ProbabilisticInterval: cfg.ProbabilisticInterval, + ProbabilisticThreshold: cfg.ProbabilisticThreshold, + }) + if err != nil { + return fmt.Errorf("failed to load eBPF tracer: %v", err) + } + log.Info("eBPF tracer loaded") + defer trc.Close() + + now := time.Now() + // Initial scan of /proc filesystem to list currently active PIDs and have them processed. + if err = trc.StartPIDEventProcessor(ctx); err != nil { + log.Errorf("Failed to list processes from /proc: %v", err) + } + log.Debugf("Completed initial PID listing after %dms", time.Since(now).Milliseconds()) + + // Attach our tracer to the perf event + if err := trc.AttachTracer(); err != nil { + return fmt.Errorf("failed to attach to perf event: %v", err) + } + log.Info("Attached tracer program") + + if cfg.ProbabilisticThreshold < tracer.ProbabilisticThresholdMax { + trc.StartProbabilisticProfiling(ctx) + log.Info("Enabled probabilistic profiling") + } else { + if err := trc.EnableProfiling(); err != nil { + return fmt.Errorf("failed to enable perf events: %v", err) + } + } + + if err := trc.AttachSchedMonitor(); err != nil { + return fmt.Errorf("failed to attach scheduler monitor: %v", err) + } + + // This log line is used in our system tests to verify if that the agent has started. + // So if you change this log line, update also the system test. + log.Info("Attached sched monitor") + log.Infof("cfg: %+v", cfg) + log.Info("intervals: ", intervals) + + if err := startTraceHandling(ctx, rep, intervals, trc, traceHandlerCacheSize); err != nil { + return fmt.Errorf("failed to start trace handling: %v", err) + } + + go func() { + // Wait until the receiver should terminate. + <-ctx.Done() + + log.Info("Stop processing ...") + rep.Stop() + + log.Info("Exiting ...") + }() + + return nil +} + +// Shutdown stops the receiver. +func (c *Controller) Shutdown(_ context.Context) error { + agentShutdown() + c.cancel() + return nil +} + +func startTraceHandling(ctx context.Context, rep reporter.TraceReporter, + intervals *times.Times, trc *tracer.Tracer, cacheSize uint32) error { + // Spawn monitors for the various result maps + traceCh := make(chan *hostinfo.Trace) + + if err := trc.StartMapMonitors(ctx, traceCh); err != nil { + return fmt.Errorf("failed to start map monitors: %v", err) + } + + _, err := tracehandler.Start(ctx, rep, trc.TraceProcessor(), traceCh, intervals, cacheSize) + return err +} + +// traceCacheSize defines the maximum number of elements for the caches in tracehandler. +// +// The caches in tracehandler have a size-"processing overhead" trade-off: Every cache miss will +// trigger additional processing for that trace in userspace (Go). For most maps, we use +// maxElementsPerInterval as a base sizing factor. For the tracehandler caches, we also multiply +// with traceCacheIntervals. For typical/small values of maxElementsPerInterval, this can lead to +// non-optimal map sizing (reduced cache_hit/cache_miss ratio and increased processing overhead). +// Simply increasing traceCacheIntervals is problematic when maxElementsPerInterval is large +// (e.g., too many CPU cores present) as we end up using too much memory. A minimum size is +// therefore used here. +func traceCacheSize(monitorInterval time.Duration, samplesPerSecond, presentCPUCores int) uint32 { + const ( + traceCacheIntervals = 6 + traceCacheMinSize = 65536 + ) + + maxElementsPerInterval := samplesPerSecond * int(monitorInterval.Seconds()) * presentCPUCores + + size := maxElementsPerInterval * traceCacheIntervals + if size < traceCacheMinSize { + size = traceCacheMinSize + } + return util.NextPowerOfTwo(uint32(size)) +} diff --git a/collector/internal/helpers.go b/collector/internal/helpers.go new file mode 100644 index 00000000..86940381 --- /dev/null +++ b/collector/internal/helpers.go @@ -0,0 +1,236 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "errors" + "fmt" + "net" + "runtime" + "sync" + "syscall" + + "github.com/open-telemetry/opentelemetry-ebpf-profiler/tracer" + log "github.com/sirupsen/logrus" + + "github.com/jsimonetti/rtnetlink" + "golang.org/x/sys/unix" +) + +func getKernelVersion() (string, error) { + major, minor, patch, err := tracer.GetCurrentKernelVersion() + if err != nil { + return "", err + } + return fmt.Sprintf("%d.%d.%d", major, minor, patch), nil +} + +func addressFamily(ip net.IP) (uint8, error) { + if ip.To4() != nil { + return unix.AF_INET, nil + } + if len(ip) == net.IPv6len { + return unix.AF_INET6, nil + } + return 0, fmt.Errorf("invalid IP address: %v", ip) +} + +func resolveDestination(domain string) ([]net.IP, error) { + dstIPs, err := net.LookupIP(domain) + if err == nil { + return dstIPs, nil + } + + // domain seems not to be a DNS value. + // Try to interpret it as IP. + host, _, err := net.SplitHostPort(domain) + if err != nil { + return []net.IP{}, err + } + return net.LookupIP(host) +} + +// getSourceIPAddress returns the source IP address for the traffic destined to the specified +// domain. +func getSourceIPAddress(domain string) (net.IP, error) { + conn, err := rtnetlink.Dial(nil) + if err != nil { + return nil, errors.New("unable to open netlink connection") + } + defer conn.Close() + + dstIPs, err := resolveDestination(domain) + if err != nil { + return nil, fmt.Errorf("unable to resolve %s: %v", domain, err) + } + if len(dstIPs) == 0 { + return nil, fmt.Errorf("unable to resolve %s: no IP address", domain) + } + + var srcIP net.IP + var lastError error + found := false + + // We might get multiple IP addresses, check all of them as some may not be routable (like an + // IPv6 address on an IPv4 network). + for _, ip := range dstIPs { + addressFamily, err := addressFamily(ip) + if err != nil { + return nil, fmt.Errorf("unable to get address family for %s: %v", ip.String(), err) + } + + req := &rtnetlink.RouteMessage{ + Family: addressFamily, + Table: unix.RT_TABLE_MAIN, + Attributes: rtnetlink.RouteAttributes{ + Dst: ip, + }, + } + + routes, err := conn.Route.Get(req) + if err != nil { + lastError = fmt.Errorf("unable to get route to %s (%s): %v", domain, ip.String(), err) + continue + } + + if len(routes) == 0 { + continue + } + if len(routes) > 1 { + // More than 1 route! + // This doesn't look like this should ever happen (even in the presence of overlapping + // routes with same metric, this will return a single route). + // May be a leaky abstraction/artifact from the way the netlink API works? + // Regardless, this seems ok to ignore, but log just in case. + log.Warnf("Found multiple (%d) routes to %v; first 2 routes: %#v and %#v", + len(routes), domain, routes[0], routes[1]) + } + + // Sanity-check the result, in case the source address is left uninitialized + if len(routes[0].Attributes.Src) == 0 { + lastError = fmt.Errorf( + "unable to get route to %s (%s): no source IP address", domain, ip.String()) + continue + } + + srcIP = routes[0].Attributes.Src + found = true + break + } + + if !found { + return nil, fmt.Errorf("no route found to %s: %v", domain, lastError) + } + + log.Debugf("Traffic to %v is routed from %v", domain, srcIP.String()) + return srcIP, nil +} + +// runInRootNS executes fetcher in the root namespace. +func runInRootNS(fetcher func() error) error { + // We need to call the `setns` syscall to extract information (network route, hostname) from + // different namespaces. + // However, `setns` doesn't know about goroutines, it operates on OS threads. + // Therefore, the below code needs to take extra steps to make sure no other code (outside of + // this function) will execute in a different namespace. + // + // To do this, we use `runtime.LockOSThread()`, which we call from a separate goroutine. + // runtime.LockOSThread() ensures that the thread executing the goroutine will be terminated + // when the goroutine exits, which makes it impossible for the entered namespaces to be used in + // a different context than the below code. + // + // It would be doable without a goroutine, by saving and restoring the namespaces before calling + // runtime.UnlockOSThread(), but error handling makes things complicated and unsafe/dangerous. + // The below implementation is always safe to run even in the presence of errors. + // + // The only downside is that calling this function comes at the cost of sacrificing an OS + // thread, which will likely force the Go runtime to launch a new thread later. This should be + // acceptable if it doesn't happen too often. + + // Error result of the below goroutine. May contain multiple combined errors. + var errResult error + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + // Before entering a different namespace, lock the current goroutine to a thread. + // Note that we do *not* call runtime.UnlockOSThread(): this ensures the current thread + // will exit after the goroutine finishes, which makes it impossible for other + // goroutines to enter a different namespace. + runtime.LockOSThread() + + // Try to enter root namespaces. If that fails, continue anyway as we might be able to + // gather some metadata. + utsFD, netFD := tryEnterRootNamespaces() + + // Any errors were already logged by the above function. + if utsFD != -1 { + defer unix.Close(utsFD) + } + if netFD != -1 { + defer unix.Close(netFD) + } + + if utsFD == -1 || netFD == -1 { + log.Warnf("Missing capabilities to enter root namespace, fetching information from " + + "current process namespaces") + } + + errResult = fetcher() + }() + + wg.Wait() + + return errResult +} + +// tryEnterRootNamespaces tries to enter PID 1's UTS and network namespaces. +// It returns the file descriptor associated to each, or -1 if the namespace cannot be entered. +func tryEnterRootNamespaces() (utsFD, netFD int) { + netFD, err := enterNamespace(1, "net") + if err != nil { + log.Errorf( + "Unable to enter root network namespace, host metadata may be incorrect: %v", err) + netFD = -1 + } + + utsFD, err = enterNamespace(1, "uts") + if err != nil { + log.Errorf("Unable to enter root UTS namespace, host metadata may be incorrect: %v", err) + utsFD = -1 + } + + return utsFD, netFD +} + +// enterNamespace enters a new namespace of the specified type, inherited from the provided PID. +// The returned file descriptor must be closed with unix.Close(). +// Note that this function affects the OS thread calling this function, which will likely impact +// more than one goroutine unless you also use runtime.LockOSThread. +func enterNamespace(pid int, nsType string) (int, error) { + var nsTypeInt int + switch nsType { + case "net": + nsTypeInt = syscall.CLONE_NEWNET + case "uts": + nsTypeInt = syscall.CLONE_NEWUTS + default: + return -1, fmt.Errorf("unsupported namespace type: %s", nsType) + } + + path := fmt.Sprintf("/proc/%d/ns/%s", pid, nsType) + fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0) + if err != nil { + return -1, err + } + + err = unix.Setns(fd, nsTypeInt) + if err != nil { + // Close namespace and return the error + return -1, errors.Join(err, unix.Close(fd)) + } + + return fd, nil +} diff --git a/go.mod b/go.mod index 1d8bd5e9..ea0c5869 100644 --- a/go.mod +++ b/go.mod @@ -19,13 +19,19 @@ require ( github.com/stretchr/testify v1.9.0 github.com/tklauser/numcpus v0.8.0 github.com/zeebo/xxh3 v1.0.2 - go.opentelemetry.io/otel v1.27.0 + go.opentelemetry.io/collector/component v0.109.0 + go.opentelemetry.io/collector/consumer/consumerprofiles v0.109.0 + go.opentelemetry.io/collector/consumer/consumertest v0.109.0 + go.opentelemetry.io/collector/receiver v0.109.0 + go.opentelemetry.io/collector/receiver/receiverprofiles v0.109.0 + go.opentelemetry.io/otel v1.29.0 go.opentelemetry.io/proto/otlp v1.3.1 + go.uber.org/zap v1.27.0 golang.org/x/arch v0.8.0 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 - golang.org/x/sync v0.7.0 - golang.org/x/sys v0.21.0 - google.golang.org/grpc v1.64.1 + golang.org/x/sync v0.8.0 + golang.org/x/sys v0.24.0 + google.golang.org/grpc v1.66.0 ) require ( @@ -45,19 +51,41 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.29.1 // indirect github.com/aws/smithy-go v1.20.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/native v1.1.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect - google.golang.org/protobuf v1.34.1 // indirect + github.com/prometheus/client_golang v1.20.2 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.57.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.109.0 // indirect + go.opentelemetry.io/collector/consumer v0.109.0 // indirect + go.opentelemetry.io/collector/pdata v1.15.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.109.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.51.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c23ccba7..00bb8ab7 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.29.1 h1:myX5CxqXE0QMZNja6FA1/FSE3Vu1 github.com/aws/aws-sdk-go-v2/service/sts v1.29.1/go.mod h1:N2mQiucsO0VwK9CYuS4/c2n6Smeh1v47Rz3dWCPFLdE= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= @@ -47,10 +49,18 @@ github.com/elastic/go-freelru v0.13.0 h1:TKKY6yCfNNNky7Pj9xZAOEpBcdNgZJfihEftOb5 github.com/elastic/go-freelru v0.13.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I= github.com/elastic/go-perf v0.0.0-20191212140718-9c656876f595 h1:q8n4QjcLa4q39Q3fqHRknTBXBtegjriHFrB42YKgXGI= github.com/elastic/go-perf v0.0.0-20191212140718-9c656876f595/go.mod h1:s09U1b4P1ZxnKx2OsqY7KlHdCesqZWIhyq0Gs/QC/Us= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/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-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= @@ -63,6 +73,10 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink v1.4.2 h1:Df9w9TZ3npHTyDn0Ev9e1uzmN2odmXd0QX+J5GTEn90= github.com/jsimonetti/rtnetlink v1.4.2/go.mod h1:92s6LJdE+1iOrw+F2/RO7LYI2Qd8pPpFNNUYW06gcoM= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +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.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= @@ -71,56 +85,138 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= +github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY= +github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/collector v0.109.0 h1:ULnMWuwcy4ix1oP5RFFRcmpEbaU5YabW6nWcLMQQRo0= +go.opentelemetry.io/collector/component v0.109.0 h1:AU6eubP1htO8Fvm86uWn66Kw0DMSFhgcRM2cZZTYfII= +go.opentelemetry.io/collector/component v0.109.0/go.mod h1:jRVFY86GY6JZ61SXvUN69n7CZoTjDTqWyNC+wJJvzOw= +go.opentelemetry.io/collector/config/configtelemetry v0.109.0 h1:ItbYw3tgFMU+TqGcDVEOqJLKbbOpfQg3AHD8b22ygl8= +go.opentelemetry.io/collector/config/configtelemetry v0.109.0/go.mod h1:R0MBUxjSMVMIhljuDHWIygzzJWQyZHXXWIgQNxcFwhc= +go.opentelemetry.io/collector/consumer v0.109.0 h1:fdXlJi5Rat/poHPiznM2mLiXjcv1gPy3fyqqeirri58= +go.opentelemetry.io/collector/consumer v0.109.0/go.mod h1:E7PZHnVe1DY9hYy37toNxr9/hnsO7+LmnsixW8akLQI= +go.opentelemetry.io/collector/consumer/consumerprofiles v0.109.0 h1:+WZ6MEWQRC6so3IRrW916XK58rI9NnrFHKW/P19jQvc= +go.opentelemetry.io/collector/consumer/consumerprofiles v0.109.0/go.mod h1:spZ9Dn1MRMPDHHThdXZA5TrFhdOL1wsl0Dw45EBVoVo= +go.opentelemetry.io/collector/consumer/consumertest v0.109.0 h1:v4w9G2MXGJ/eabCmX1DvQYmxzdysC8UqIxa/BWz7ACo= +go.opentelemetry.io/collector/consumer/consumertest v0.109.0/go.mod h1:lECt0qOrx118wLJbGijtqNz855XfvJv0xx9GSoJ8qSE= +go.opentelemetry.io/collector/pdata v1.15.0 h1:q/T1sFpRKJnjDrUsHdJ6mq4uSqViR/f92yvGwDby/gY= +go.opentelemetry.io/collector/pdata v1.15.0/go.mod h1:2wcsTIiLAJSbqBq/XUUYbi+cP+N87d0jEJzmb9nT19U= +go.opentelemetry.io/collector/pdata/pprofile v0.109.0 h1:5lobQKeHk8p4WC7KYbzL6ZqqX3eSizsdmp5vM8pQFBs= +go.opentelemetry.io/collector/pdata/pprofile v0.109.0/go.mod h1:lXIifCdtR5ewO17JAYTUsclMqRp6h6dCowoXHhGyw8Y= +go.opentelemetry.io/collector/pdata/testdata v0.109.0 h1:gvIqy6juvqFET/6zi+zUOH1KZY/vtEDZW55u7gJ/hEo= +go.opentelemetry.io/collector/pdata/testdata v0.109.0/go.mod h1:zRttU/F5QMQ6ZXBMXCoSVG3EORTZLTK+UUS0VoMoT44= +go.opentelemetry.io/collector/receiver v0.109.0 h1:DTOM7xaDl7FUGQIjvjmWZn03JUE+aG4mJzWWfb7S8zw= +go.opentelemetry.io/collector/receiver v0.109.0/go.mod h1:jeiCHaf3PE6aXoZfHF5Uexg7aztu+Vkn9LVw0YDKm6g= +go.opentelemetry.io/collector/receiver/receiverprofiles v0.109.0 h1:KKzdIixE/XJWvqdCcNWAOtsEhNKu4waLKJjawjhnPLw= +go.opentelemetry.io/collector/receiver/receiverprofiles v0.109.0/go.mod h1:FKU+RFkSLWWB3tUUB6vifapZdFp1FoqVYVQ22jpHc8w= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw= +go.opentelemetry.io/otel/exporters/prometheus v0.51.0/go.mod h1:v0mFe5Kk7woIh938mrZBJBmENYquyA0IICrlYm4Y0t4= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +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/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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=