From 845c131d52e8f1433774cdc34be8a19828b5019f Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Tue, 31 Oct 2023 17:43:42 +0100 Subject: [PATCH 01/14] Add repository fields to BuildInfo metric Fixes AM-41 --- otel/autometrics/otel.go | 20 +++++++++++++ pkg/autometrics/global_state.go | 43 +++++++++++++++++++++++---- pkg/autometrics/main.go | 6 +++- prometheus/autometrics/instrument.go | 20 ------------- prometheus/autometrics/prometheus.go | 44 ++++++++++++++++++---------- 5 files changed, 90 insertions(+), 43 deletions(-) diff --git a/otel/autometrics/otel.go b/otel/autometrics/otel.go index 4fcd437..3d1a231 100644 --- a/otel/autometrics/otel.go +++ b/otel/autometrics/otel.go @@ -84,6 +84,13 @@ const ( // BranchLabel is the openTelemetry attribute that describes the branch of the build of the monitored codebase. BranchLabel = "branch" + // RepositoryURLLabel is the openTelemetry attribute that describes the URL at which the repository containing + // the monitored service can be found + RepositoryURLLabel = "repository.url" + // RepositoryProviderLabel is the openTelemetry attribute that describes the service provider for the monitored + // service repository url + RepositoryProviderLabel = "repository.provider" + // ServiceNameLabel is the openTelemetry attribute that describes the name of the Service being monitored. ServiceNameLabel = "service.name" @@ -190,6 +197,17 @@ func Init(meterName string, histogramBuckets []float64, buildInformation BuildIn autometrics.SetService(buildInformation.Service) } + if repoURL, ok := os.LookupEnv(autometrics.AutometricsRepoURLEnv); ok { + autometrics.SetRepositoryURL(repoURL) + } else if buildInformation.RepositoryURL != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryURL) + } + if repoProvider, ok := os.LookupEnv(autometrics.AutometricsRepoProviderEnv); ok { + autometrics.SetRepositoryURL(repoProvider) + } else if buildInformation.RepositoryProvider != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryProvider) + } + provider, err := initProvider(pushExporter, pushConfiguration, meterName, histogramBuckets) if err != nil { return nil, err @@ -223,6 +241,8 @@ func Init(meterName string, histogramBuckets []float64, buildInformation BuildIn attribute.Key(VersionLabel).String(buildInformation.Version), attribute.Key(BranchLabel).String(buildInformation.Branch), attribute.Key(ServiceNameLabel).String(autometrics.GetService()), + attribute.Key(RepositoryProviderLabel).String(autometrics.GetRepositoryProvider()), + attribute.Key(RepositoryURLLabel).String(autometrics.GetRepositoryURL()), attribute.Key(JobNameLabel).String(autometrics.GetPushJobName()), }...)) diff --git a/pkg/autometrics/global_state.go b/pkg/autometrics/global_state.go index 0c6220a..8656ca1 100644 --- a/pkg/autometrics/global_state.go +++ b/pkg/autometrics/global_state.go @@ -12,15 +12,25 @@ const ( // the service to use as a label. This environment variable has precedence over variables hardcoded // in the [BuildInfo] struct in the Init call. OTelServiceNameEnv = "OTEL_SERVICE_NAME" + // AutometricsRepoURLEnv is the name of the environment variable to declare to give the URL of + // the repository for the service to use as a label. This environment variable has precedence over + // over hardcoding the variable directly in [BuildInfo] struct in the Init call. + AutometricsRepoURLEnv = "AUTOMETRICS_REPOSITORY_URL" + // AutometricsRepoProviderEnv is the name of the environment variable to declare to give the name of + // the repository provider to use as a label. This environment variable has precedence over + // over hardcoding the variable directly in [BuildInfo] struct in the Init call. + AutometricsRepoProviderEnv = "AUTOMETRICS_REPOSITORY_PROVIDER" ) var ( - version string - commit string - branch string - service string - pushJobName string - pushJobURL string + version string + commit string + branch string + service string + repoURL string + repoProvider string + pushJobName string + pushJobURL string ) // GetVersion returns the version of the codebase being instrumented. @@ -63,6 +73,27 @@ func SetService(newService string) { service = newService } +// GetRepositoryURL returns the URL of the repo of the codebase being instrumented. +func GetRepositoryURL() string { + return repoURL +} + +// SetRepositoryURL sets the URL of the repo of the codebase being instrumented. +func SetRepositoryURL(newRepositoryURL string) { + repoURL = newRepositoryURL + +} + +// GetRepositoryProvider returns the service provider of the repo for the codebase being instrumented. +func GetRepositoryProvider() string { + return repoProvider +} + +// SetRepositoryProvider sets the service provider of the repo for the codebase being instrumented. +func SetRepositoryProvider(newRepositoryProvider string) { + repoProvider = newRepositoryProvider +} + // GetPushJobName returns the job name to use when the codebase being instrumented is pushing metrics to an OTEL Collector. func GetPushJobName() string { return pushJobName diff --git a/pkg/autometrics/main.go b/pkg/autometrics/main.go index 1d15db7..0dd0f81 100644 --- a/pkg/autometrics/main.go +++ b/pkg/autometrics/main.go @@ -51,8 +51,12 @@ type BuildInfo struct { Version string // Branch is the branch of the build of the codebase. Branch string - // ServiceName is the name of the service + // Service is the name of the service Service string + // RepositoryURL is the URL of the repository containing the code + RepositoryURL string + // RepositoryProvider is the service provider for the repository containing the code + RepositoryProvider string } // PushConfiguration holds the information necessary to push metrics to an OTEL Collector. diff --git a/prometheus/autometrics/instrument.go b/prometheus/autometrics/instrument.go index fac3cd1..82f19fa 100644 --- a/prometheus/autometrics/instrument.go +++ b/prometheus/autometrics/instrument.go @@ -62,11 +62,6 @@ func Instrument(ctx context.Context, err *error) { CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).(prometheus.ExemplarAdder).AddWithExemplar(1, info) functionCallsDuration.With(prometheus.Labels{ @@ -81,11 +76,6 @@ func Instrument(ctx context.Context, err *error) { CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).(prometheus.ExemplarObserver).ObserveWithExemplar(time.Since(am.GetStartTime(ctx)).Seconds(), info) if am.GetTrackConcurrentCalls(ctx) { @@ -98,11 +88,6 @@ func Instrument(ctx context.Context, err *error) { CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).Add(-1) } @@ -153,11 +138,6 @@ func PreInstrument(ctx context.Context) context.Context { CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).Add(1) } diff --git a/prometheus/autometrics/prometheus.go b/prometheus/autometrics/prometheus.go index 437073e..27442e0 100644 --- a/prometheus/autometrics/prometheus.go +++ b/prometheus/autometrics/prometheus.go @@ -76,16 +76,16 @@ const ( // BranchLabel is the prometheus label that describes the branch of the build of the monitored codebase. BranchLabel = "branch" + // RepositoryURLLabel is the prometheus label that describes the URL at which the repository containing + // the monitored service can be found + RepositoryURLLabel = "repository_url" + // RepositoryProviderLabel is the prometheus label that describes the service provider for the monitored + // service repository url + RepositoryProviderLabel = "repository_provider" + // ServiceNameLabel is the prometheus label that describes the name of the service being monitored ServiceNameLabel = "service_name" - // ClearModeLabel is the label used by Prometheus Gravel Gateway to deal with aggregation. - ClearModeLabel = "clearmode" - - ClearModeFamily = "family" - ClearModeAggregate = "aggregate" - ClearModeReplace = "replace" - traceIdExemplar = "trace_id" spanIdExemplar = "span_id" parentSpanIdExemplar = "parent_id" @@ -160,22 +160,33 @@ func Init(reg *prometheus.Registry, histogramBuckets []float64, buildInformation autometrics.SetService(buildInformation.Service) } + if repoURL, ok := os.LookupEnv(autometrics.AutometricsRepoURLEnv); ok { + autometrics.SetRepositoryURL(repoURL) + } else if buildInformation.RepositoryURL != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryURL) + } + if repoProvider, ok := os.LookupEnv(autometrics.AutometricsRepoProviderEnv); ok { + autometrics.SetRepositoryURL(repoProvider) + } else if buildInformation.RepositoryProvider != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryProvider) + } + functionCallsCount = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: FunctionCallsCountName, - }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, ResultLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, ResultLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel}) functionCallsDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: FunctionCallsDurationName, Buckets: histogramBuckets, - }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, TargetLatencyLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, TargetLatencyLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel}) functionCallsConcurrent = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: FunctionCallsConcurrentName, - }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel}) buildInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: BuildInfoName, - }, []string{CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, RepositoryURLLabel, RepositoryProviderLabel}) if reg != nil { reg.MustRegister(functionCallsCount) @@ -190,11 +201,12 @@ func Init(reg *prometheus.Registry, histogramBuckets []float64, buildInformation } buildInfo.With(prometheus.Labels{ - CommitLabel: buildInformation.Commit, - VersionLabel: buildInformation.Version, - BranchLabel: buildInformation.Branch, - ServiceNameLabel: autometrics.GetService(), - ClearModeLabel: ClearModeFamily, + CommitLabel: buildInformation.Commit, + VersionLabel: buildInformation.Version, + BranchLabel: buildInformation.Branch, + ServiceNameLabel: autometrics.GetService(), + RepositoryURLLabel: autometrics.GetRepositoryURL(), + RepositoryProviderLabel: autometrics.GetRepositoryProvider(), }).Set(1) if pusher != nil { From ef8084f673e0bee20a3adfdac392cdbfbbbce5fd Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Thu, 2 Nov 2023 16:03:21 +0100 Subject: [PATCH 02/14] Add system to track only Autometricized parents The parent tracking is span-based (using `(TraceID, SpanId)` as keys) It falls back to the previous method (`runtime.Callers()` analysis) if the function id for a given span is missing from the global state. To prevent the global state from ballooning memory usage, the entries in the span-to-functionIDs table are deleted as part of the cleanup code in `Instrument` (that is why some goroutines outliving their callers with weird scheduling might miss the function id in the global state.) This solution deals well with functions spawning multiple goroutines, but the caller info will be "enhanced" (i.e. with Autometrics annotated functions in the parent field) only if the context created by autometrics.PreInstrument is properly passed to callees, which is a task followed in #78 Fixes: AM-42 --- otel/autometrics/instrument.go | 43 ++++++++++--------- pkg/autometrics/ctx.go | 60 +++++++++++++++++++++++++- pkg/autometrics/global_state.go | 43 +++++++++++++++---- pkg/autometrics/instrument.go | 63 +++++++++++++++------------- pkg/autometrics/main.go | 26 ++++++++---- prometheus/autometrics/instrument.go | 42 ++++++++++--------- 6 files changed, 193 insertions(+), 84 deletions(-) diff --git a/otel/autometrics/instrument.go b/otel/autometrics/instrument.go index 38edd56..c1c0a05 100644 --- a/otel/autometrics/instrument.go +++ b/otel/autometrics/instrument.go @@ -47,10 +47,10 @@ func Instrument(ctx context.Context, err *error) { functionCallsCount.Add(ctx, 1, metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(ResultLabel).String(result), attribute.Key(TargetSuccessRateLabel).String(successObjective), attribute.Key(SloNameLabel).String(sloName), @@ -62,10 +62,10 @@ func Instrument(ctx context.Context, err *error) { }...)) functionCallsDuration.Record(ctx, time.Since(am.GetStartTime(ctx)).Seconds(), metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(TargetLatencyLabel).String(latencyTarget), attribute.Key(TargetSuccessRateLabel).String(latencyObjective), attribute.Key(SloNameLabel).String(sloName), @@ -79,10 +79,10 @@ func Instrument(ctx context.Context, err *error) { if am.GetTrackConcurrentCalls(ctx) { functionCallsConcurrent.Add(ctx, -1, metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(CommitLabel).String(buildInfo.Commit), attribute.Key(VersionLabel).String(buildInfo.Version), attribute.Key(BranchLabel).String(buildInfo.Branch), @@ -90,6 +90,11 @@ func Instrument(ctx context.Context, err *error) { attribute.Key(JobNameLabel).String(am.GetPushJobName()), }...)) } + + // NOTE: This call means that goroutines that outlive this function as the caller will not have access to parent + // caller information, but hopefully by that point we got all the necessary accesses done. + // If not, it is a convenience we accept to give up to prevent memory usage from exploding + am.PopFunctionName(ctx) } // PreInstrument runs the "before wrappee" part of instrumentation. @@ -101,19 +106,19 @@ func PreInstrument(ctx context.Context) context.Context { return nil } - callInfo := am.CallerInfo() - ctx = am.SetCallInfo(ctx, callInfo) + ctx = am.FillTracingAndCallerInfo(ctx) ctx = am.FillBuildInfo(ctx) - ctx = am.FillTracingInfo(ctx) + + callInfo := am.GetCallInfo(ctx) if am.GetTrackConcurrentCalls(ctx) { buildInfo := am.GetBuildInfo(ctx) functionCallsConcurrent.Add(ctx, 1, metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(CommitLabel).String(buildInfo.Commit), attribute.Key(VersionLabel).String(buildInfo.Version), attribute.Key(BranchLabel).String(buildInfo.Branch), diff --git a/pkg/autometrics/ctx.go b/pkg/autometrics/ctx.go index 2988bb6..c5458a4 100644 --- a/pkg/autometrics/ctx.go +++ b/pkg/autometrics/ctx.go @@ -2,6 +2,7 @@ package autometrics // import "github.com/autometrics-dev/autometrics-go/pkg/aut import ( "context" + "errors" "log" "math/rand" "time" @@ -229,12 +230,12 @@ func GetParentSpanID(c context.Context) (SpanID, bool) { return sid, ok } -// FillTracingInfo ensures the context has a traceID and a spanID. +// FillTracingAndCallerInfo ensures the context has a traceID and a spanID, and looks for relevant caller information to add in the context as well. // If they do not have this information, this method adds randomly // generated IDs in the context to be used later for exemplars // // The random generator is a PRNG, seeded with the timestamp of the first time new IDs are needed. -func FillTracingInfo(ctx context.Context) context.Context { +func FillTracingAndCallerInfo(ctx context.Context) context.Context { // We are using a PRNG because FillTracingInfo is expected to be called in PreInstrument. // Therefore it can have a noticeable impact on the performance of instrumented code. // Pseudo randomness should be enough for our use cases, true randomness might introduce too much latency. @@ -258,6 +259,18 @@ func FillTracingInfo(ctx context.Context) context.Context { ctx = SetTraceID(ctx, tid) } + callInfo := callerInfo(ctx) + ctx = SetCallInfo(ctx, callInfo) + + // Adds an entry in the global map from current (traceID, spanID) to the function ID + // NOTE: this will "leak" memory if PopFunctionName is never called for the matching (TraceId, SpanId) pair. + // Calling the cleanup function is the responsibility of the otel.Instrument() and prometheus.Instrument() + // functions as the closers. + // NOTE: This also means that goroutines that outlive their as the caller will not have access to parent + // caller information, but hopefully by that point we got all the necessary accesses done. + // If not, it is a convenience we accept to give up to prevent memory usage from exploding. + PushFunctionName(ctx, callInfo.Current) + return ctx } @@ -336,3 +349,46 @@ func GetValidHttpCodeRanges(c context.Context) []InclusiveIntRange { return ranges } + +func ParentFunctionName(ctx context.Context) (FunctionID, error) { + tid, ok := GetTraceID(ctx) + if !ok { + return FunctionID{}, errors.New("context does not have any trace ID to follow.") + } + pSpanID, ok := GetParentSpanID(ctx) + if !ok { + return FunctionID{}, errors.New("context does not have any parent span ID to follow.") + } + + return fetchFunctionName(tid, pSpanID) +} + +func PopFunctionName(ctx context.Context) error { + tid, ok := GetTraceID(ctx) + if !ok { + return errors.New("context does not have any trace ID to follow.") + } + sid, ok := GetSpanID(ctx) + if !ok { + return errors.New("context does not have any current span ID to follow.") + } + + popFunctionName(tid, sid) + + return nil +} + +func PushFunctionName(ctx context.Context, functionID FunctionID) error { + tid, ok := GetTraceID(ctx) + if !ok { + return errors.New("context does not have any trace ID to follow.") + } + sid, ok := GetSpanID(ctx) + if !ok { + return errors.New("context does not have any current span ID to follow.") + } + + pushFunctionName(tid, sid, functionID) + + return nil +} diff --git a/pkg/autometrics/global_state.go b/pkg/autometrics/global_state.go index 8656ca1..88f5c71 100644 --- a/pkg/autometrics/global_state.go +++ b/pkg/autometrics/global_state.go @@ -1,5 +1,9 @@ package autometrics // import "github.com/autometrics-dev/autometrics-go/pkg/autometrics" +import ( + "fmt" +) + // These variables are describing the state of the application being autometricized, // _not_ the build information of the binary @@ -23,16 +27,22 @@ const ( ) var ( - version string - commit string - branch string - service string - repoURL string - repoProvider string - pushJobName string - pushJobURL string + version string + commit string + branch string + service string + repoURL string + repoProvider string + pushJobName string + pushJobURL string + instrumentedSpans map[spanKey]FunctionID = make(map[spanKey]FunctionID) ) +type spanKey struct { + tid TraceID + sid SpanID +} + // GetVersion returns the version of the codebase being instrumented. func GetVersion() string { return version @@ -113,3 +123,20 @@ func GetPushJobURL() string { func SetPushJobURL(newPushJobURL string) { pushJobURL = newPushJobURL } + +func fetchFunctionName(traceID TraceID, spanID SpanID) (FunctionID, error) { + fid, ok := instrumentedSpans[spanKey{tid: traceID, sid: spanID}] + if !ok { + return FunctionID{}, fmt.Errorf("%v,%v is not a known traceID/spanID pair now", traceID, spanID) + } + + return fid, nil +} + +func popFunctionName(traceID TraceID, spanID SpanID) { + delete(instrumentedSpans, spanKey{tid: traceID, sid: spanID}) +} + +func pushFunctionName(traceID TraceID, spanID SpanID, functionID FunctionID) { + instrumentedSpans[spanKey{tid: traceID, sid: spanID}] = functionID +} diff --git a/pkg/autometrics/instrument.go b/pkg/autometrics/instrument.go index 5bc6db7..dac0cec 100644 --- a/pkg/autometrics/instrument.go +++ b/pkg/autometrics/instrument.go @@ -1,6 +1,7 @@ package autometrics import ( + "context" "reflect" "runtime" "strings" @@ -8,7 +9,7 @@ import ( // CallerInfo returns the (method name, module name) of the function that called the function that called this function. // -// It also returns the information about its grandparent. +// It also returns the information about its autometricized grandparent. // // The module name and the parent module names are cropped to their last part, because the generator we use // only has access to the last "package" name in `GOPACKAGE` environment variable. @@ -17,7 +18,7 @@ import ( // then we can lift this artificial limitation here and use the full "module name" from the caller information. // Currently this compromise is the only way to have the documentation links generator creating correct // queries. -func CallerInfo() (callInfo CallInfo) { +func callerInfo(ctx context.Context) (callInfo CallInfo) { programCounters := make([]uintptr, 15) // skip 3 frames to start with: @@ -33,40 +34,46 @@ func CallerInfo() (callInfo CallInfo) { index := strings.LastIndex(functionName, ".") if index == -1 { - callInfo.FuncName = functionName + callInfo.Current.Function = functionName } else { - callInfo.ModuleName = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( + callInfo.Current.Module = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( functionName[:index], "(", ""), ")", ""), "*", "") - callInfo.FuncName = functionName[index+1:] + callInfo.Current.Function = functionName[index+1:] } - if !hasParent { - return - } + parent, err := ParentFunctionName(ctx) - // Do the same with the parent - parentFrame, _ := frames.Next() + if err != nil { + // We try to fallback to the parent in the call stack if we don't have the info + if !hasParent { + return + } - parentFunctionName := parentFrame.Function - index = strings.LastIndex(parentFunctionName, ".") + parentFrame, _ := frames.Next() + parentFrameFunctionName := parentFrame.Function + index = strings.LastIndex(parentFrameFunctionName, ".") - if index == -1 { - callInfo.ParentFuncName = parentFunctionName - } else { - moduleIndex := strings.LastIndex(parentFunctionName[:index], ".") - if moduleIndex == -1 { - callInfo.ParentModuleName = parentFunctionName[:index] + if index == -1 { + callInfo.Parent.Function = parentFrameFunctionName } else { - callInfo.ParentModuleName = parentFunctionName[moduleIndex+1 : index] + callInfo.Parent.Module = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( + parentFrameFunctionName[:index], + "(", ""), + ")", ""), + "*", "") + + callInfo.Parent.Function = functionName[index+1:] } - callInfo.ParentFuncName = parentFunctionName[index+1:] + return } + callInfo.Parent = parent + return } @@ -80,15 +87,15 @@ func ReflectFunctionModuleName(f interface{}) (callInfo CallInfo) { index := strings.LastIndex(functionName, ".") if index == -1 { - callInfo.FuncName = functionName + callInfo.Current.Function = functionName } else { - moduleIndex := strings.LastIndex(functionName[:index], ".") - if moduleIndex == -1 { - callInfo.ModuleName = functionName[:index] - } else { - callInfo.ModuleName = functionName[moduleIndex+1 : index] - } - callInfo.FuncName = functionName[index+1:] + callInfo.Current.Module = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( + functionName[:index], + "(", ""), + ")", ""), + "*", "") + + callInfo.Current.Function = functionName[index+1:] } return callInfo diff --git a/pkg/autometrics/main.go b/pkg/autometrics/main.go index 0dd0f81..a2df5b4 100644 --- a/pkg/autometrics/main.go +++ b/pkg/autometrics/main.go @@ -31,16 +31,26 @@ const ( MiddlewareTraceIDKey = "autometricsTraceID" ) +// FunctionID is a unique identifier for a function (on a per-codebase basis) +type FunctionID struct { + // Function is the name of the function being tracked + Function string + // Module is the name of the module containing the function being tracked, up to (and including) the class name + Module string +} + // CallInfo holds the information about the current function call and its parent names. type CallInfo struct { - // FuncName is name of the function being tracked. - FuncName string - // ModuleName is name of the module of the function being tracked. - ModuleName string - // ParentFuncName is name of the caller of the function being tracked. - ParentFuncName string - // ParentModuleName is name of the module of the caller of the function being tracked. - ParentModuleName string + // Current is the identifier of the function being tracked + Current FunctionID + // Parent is the identifirs of the caller of the function being tracked. + // + // The parent information is only included for autometricized functions. This + // means: + // - if A calls B calls C, + // - only A and C have autometrics annotations, + // then the Caller information when working with C is going to be A, _not_ B + Parent FunctionID } // BuildInfo holds the information about the current build of the instrumented code. diff --git a/prometheus/autometrics/instrument.go b/prometheus/autometrics/instrument.go index 82f19fa..dfb7226 100644 --- a/prometheus/autometrics/instrument.go +++ b/prometheus/autometrics/instrument.go @@ -51,10 +51,10 @@ func Instrument(ctx context.Context, err *error) { info := exemplars(ctx) functionCallsCount.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, ResultLabel: result, TargetSuccessRateLabel: successObjective, SloNameLabel: sloName, @@ -65,10 +65,10 @@ func Instrument(ctx context.Context, err *error) { }).(prometheus.ExemplarAdder).AddWithExemplar(1, info) functionCallsDuration.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, TargetLatencyLabel: latencyTarget, TargetSuccessRateLabel: latencyObjective, SloNameLabel: sloName, @@ -80,10 +80,10 @@ func Instrument(ctx context.Context, err *error) { if am.GetTrackConcurrentCalls(ctx) { functionCallsConcurrent.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, BranchLabel: buildInfo.Branch, CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, @@ -111,6 +111,11 @@ func Instrument(ctx context.Context, err *error) { } }(amCtx) } + + // NOTE: This call means that goroutines that outlive this function as the caller will not have access to parent + // caller information, but hopefully by that point we got all the necessary accesses done. + // If not, it is a convenience we accept to give up to prevent memory usage from exploding + am.PopFunctionName(ctx) } // PreInstrument runs the "before wrappee" part of instrumentation. @@ -122,18 +127,17 @@ func PreInstrument(ctx context.Context) context.Context { return nil } - callInfo := am.CallerInfo() - ctx = am.SetCallInfo(ctx, callInfo) + ctx = am.FillTracingAndCallerInfo(ctx) ctx = am.FillBuildInfo(ctx) - ctx = am.FillTracingInfo(ctx) buildInfo := am.GetBuildInfo(ctx) + callInfo := am.GetCallInfo(ctx) if am.GetTrackConcurrentCalls(ctx) { functionCallsConcurrent.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, BranchLabel: buildInfo.Branch, CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, From b3f7dda3120e59f94366ab42a1efc6ca7dfdc659 Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Thu, 2 Nov 2023 16:12:01 +0100 Subject: [PATCH 03/14] Update dependencies --- examples/otel/go.mod | 44 +++---- examples/otel/go.sum | 94 +++++++------ examples/web/go.mod | 13 +- examples/web/go.sum | 29 ++-- go.mod | 53 ++++---- go.sum | 57 ++++++++ go.work.sum | 308 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 478 insertions(+), 120 deletions(-) diff --git a/examples/otel/go.mod b/examples/otel/go.mod index a04829c..7d2b832 100644 --- a/examples/otel/go.mod +++ b/examples/otel/go.mod @@ -4,38 +4,38 @@ go 1.20 require ( github.com/autometrics-dev/autometrics-go v0.0.0-20230222105517-4997cc8aa1e4 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect - go.opentelemetry.io/otel v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 // indirect - go.opentelemetry.io/otel/metric v1.17.0 // indirect - go.opentelemetry.io/otel/sdk v1.17.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.40.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/otel v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.57.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/examples/otel/go.sum b/examples/otel/go.sum index 1e9ccc7..4a2e426 100644 --- a/examples/otel/go.sum +++ b/examples/otel/go.sum @@ -6,69 +6,67 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/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/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -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/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 h1:MZbjiZeMmn5wFMORhozpouGKDxj9POHTuU5UA8msBQk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0/go.mod h1:C7tOYVCJmrDTCwxNny0MuUtnDIR3032vFHYke0F2ZrU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 h1:q3FNPi8FLQVjLlmV+WWHQfH9ZCCtQIS0O/+dn1+4cJ4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0/go.mod h1:rmx4n0uSIAkKBeQYkygcv9dENAlL2/tv3OSq68h1JAo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 h1:SZaSbubADNhH2Gxm+1GaZ/cFsGiYefZoodMMX79AOd4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0/go.mod h1:N65FzQDfQH7NY7umgb0U+7ypGKVYKwwE24L6KXT4OA8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= 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= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 h1:HJMDndgxest5n2y77fnErkM62iUsptE/H8p0dC2Huo4= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405/go.mod h1:oT32Z4o8Zv2xPQTg0pbVaPr0MPOH6f14RgXt7zfIpwg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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= diff --git a/examples/web/go.mod b/examples/web/go.mod index 06b0876..a635b09 100644 --- a/examples/web/go.mod +++ b/examples/web/go.mod @@ -4,19 +4,18 @@ go 1.20 require ( github.com/autometrics-dev/autometrics-go v0.0.0-20230222105517-4997cc8aa1e4 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect - golang.org/x/sys v0.12.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/examples/web/go.sum b/examples/web/go.sum index 43a8652..245c067 100644 --- a/examples/web/go.sum +++ b/examples/web/go.sum @@ -3,30 +3,25 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r 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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -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/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= diff --git a/go.mod b/go.mod index 02c3710..71b3914 100644 --- a/go.mod +++ b/go.mod @@ -2,54 +2,55 @@ module github.com/autometrics-dev/autometrics-go go 1.18 -require github.com/prometheus/client_golang v1.16.0 +require github.com/prometheus/client_golang v1.17.0 require ( github.com/alexflint/go-arg v1.4.3 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/oklog/ulid/v2 v2.1.0 - go.opentelemetry.io/otel v1.17.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 - go.opentelemetry.io/otel/metric v1.17.0 - go.opentelemetry.io/otel/sdk v1.17.0 - go.opentelemetry.io/otel/sdk/metric v0.40.0 - golang.org/x/exp v0.0.0-20230223210539-50820d90acfd + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/sdk v1.19.0 + go.opentelemetry.io/otel/sdk/metric v1.19.0 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d ) require ( - github.com/alexflint/go-scalar v1.1.0 // indirect + github.com/alexflint/go-scalar v1.2.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.57.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/dave/dst v0.27.2 + github.com/dave/dst v0.27.3 github.com/dave/jennifer v1.6.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 + github.com/prometheus/procfs v0.12.0 // indirect github.com/stretchr/testify v1.8.4 - golang.org/x/mod v0.8.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9b7195e..834caeb 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/u github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA= github.com/alexflint/go-scalar v1.1.0 h1:aaAouLLzI9TChcPXotr6gUhq+Scr8rl0P9P4PnltbhM= github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= +github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= +github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= 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/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= @@ -10,6 +12,8 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/dave/dst v0.27.2 h1:4Y5VFTkhGLC1oddtNwuxxe36pnyLxMFXT51FOzH8Ekc= github.com/dave/dst v0.27.2/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= +github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= +github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= github.com/dave/jennifer v1.6.0 h1:MQ/6emI2xM7wt0tJzJzyUik2Q3Tcn2eE0vtYgh4GPVI= github.com/dave/jennifer v1.6.0/go.mod h1:AxTG893FiZKqxy3FP1kL80VMshSMuz2G+EgvszgGRnk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -18,9 +22,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/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/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -31,10 +38,14 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= 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/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= @@ -42,12 +53,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -57,46 +76,84 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 h1:MZbjiZeMmn5wFMORhozpouGKDxj9POHTuU5UA8msBQk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0/go.mod h1:C7tOYVCJmrDTCwxNny0MuUtnDIR3032vFHYke0F2ZrU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 h1:q3FNPi8FLQVjLlmV+WWHQfH9ZCCtQIS0O/+dn1+4cJ4= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0/go.mod h1:rmx4n0uSIAkKBeQYkygcv9dENAlL2/tv3OSq68h1JAo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 h1:SZaSbubADNhH2Gxm+1GaZ/cFsGiYefZoodMMX79AOd4= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0/go.mod h1:N65FzQDfQH7NY7umgb0U+7ypGKVYKwwE24L6KXT4OA8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= 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= golang.org/x/exp v0.0.0-20230223210539-50820d90acfd h1:wtFuj4DoOcAdb82Zh2PI90xiaqgp7maYA7KxjQXVtkY= golang.org/x/exp v0.0.0-20230223210539-50820d90acfd/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 h1:HJMDndgxest5n2y77fnErkM62iUsptE/H8p0dC2Huo4= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405/go.mod h1:oT32Z4o8Zv2xPQTg0pbVaPr0MPOH6f14RgXt7zfIpwg= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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= diff --git a/go.work.sum b/go.work.sum index f5a8d42..cf32a8a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,137 +1,269 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accessapproval v1.7.2/go.mod h1:/gShiq9/kK/h8T/eEn1BTzalDvk0mZxJlhfw0p+Xuc0= cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/accesscontextmanager v1.8.2/go.mod h1:E6/SCRM30elQJ2PKtFMs2YhfJpZSNcJyejhuzoId4Zk= cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/aiplatform v1.51.1/go.mod h1:kY3nIMAVQOK2XDqDPHaOuD9e+FdMA6OOpfBjsvaFSOo= cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/analytics v0.21.4/go.mod h1:zZgNCxLCy8b2rKKVfC1YkC2vTrpfZmeRCySM3aUbskA= cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigateway v1.6.2/go.mod h1:CwMC90nnZElorCW63P2pAYm25AtQrHfuOkbRSHj0bT8= cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeconnect v1.6.2/go.mod h1:s6O0CgXT9RgAxlq3DLXvG8riw8PYYbU/v25jqP3Dy18= cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apigeeregistry v0.7.2/go.mod h1:9CA2B2+TGsPKtfi3F7/1ncCCsL62NXBRfM6iPoGSM+8= cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/appengine v1.8.2/go.mod h1:WMeJV9oZ51pvclqFN2PqHoGnys7rK0rz6s3Mp6yMvDo= cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/area120 v0.8.2/go.mod h1:a5qfo+x77SRLXnCynFWPUZhnZGeSgvQ+Y0v1kSItkh4= cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/artifactregistry v1.14.3/go.mod h1:A2/E9GXnsyXl7GUvQ/2CjHA+mVRoWAXC0brg2os+kNI= cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/asset v1.15.1/go.mod h1:yX/amTvFWRpp5rcFq6XbCxzKT8RJUam1UoboE179jU4= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/assuredworkloads v1.11.2/go.mod h1:O1dfr+oZJMlE6mw0Bp0P1KZSlj5SghMBvTpZqIcUAW4= cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/automl v1.13.2/go.mod h1:gNY/fUmDEN40sP8amAX3MaXkxcqPIn7F1UIIPZpy4Mg= cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/baremetalsolution v1.2.1/go.mod h1:3qKpKIw12RPXStwQXcbhfxVj1dqQGEvcmA+SX/mUR88= cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/batch v1.5.1/go.mod h1:RpBuIYLkQu8+CWDk3dFD/t/jOCGuUpkpX+Y0n1Xccs8= cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/beyondcorp v1.0.1/go.mod h1:zl/rWWAFVeV+kx+X2Javly7o1EIQThU4WlkynffL/lk= cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/bigquery v1.56.0/go.mod h1:KDcsploXTEY7XT3fDQzMUZlpQLHzE4itubHrnmhUrZA= cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/billing v1.17.2/go.mod h1:u/AdV/3wr3xoRBk5xvUzYMS1IawOAPwQMuHgHMdljDg= cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/binaryauthorization v1.7.1/go.mod h1:GTAyfRWYgcbsP3NJogpV3yeunbUIjx2T9xVeYovtURE= cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/certificatemanager v1.7.2/go.mod h1:15SYTDQMd00kdoW0+XY5d9e+JbOPjp24AvF48D8BbcQ= cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/channel v1.17.1/go.mod h1:xqfzcOZAcP4b/hUDH0GkGg1Sd5to6di1HOJn/pi5uBQ= cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/cloudbuild v1.14.1/go.mod h1:K7wGc/3zfvmYWOWwYTgF/d/UVJhS4pu+HAy7PL7mCsU= cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/clouddms v1.7.1/go.mod h1:o4SR8U95+P7gZ/TX+YbJxehOCsM+fe6/brlrFquiszk= cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/cloudtasks v1.12.2/go.mod h1:A7nYkjNlW2gUoROg1kvJrQGhJP/38UaWwsnuBDOBVUk= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/contactcenterinsights v1.11.1/go.mod h1:FeNP3Kg8iteKM80lMwSk3zZZKVxr+PGnAId6soKuXwE= cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/container v1.26.1/go.mod h1:5smONjPRUxeEpDG7bMKWfDL4sauswqEtnBK1/KKpR04= cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/containeranalysis v0.11.1/go.mod h1:rYlUOM7nem1OJMKwE1SadufX0JP3wnXj844EtZAwWLY= cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/datacatalog v1.18.1/go.mod h1:TzAWaz+ON1tkNr4MOcak8EBHX7wIRX/gZKM+yTVsv+A= cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataflow v0.9.2/go.mod h1:vBfdBZ/ejlTaYIGB3zB4T08UshH70vbtZeMD+urnUSo= cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/dataform v0.8.2/go.mod h1:X9RIqDs6NbGPLR80tnYoPNiO1w0wenKTb8PxxlhTMKM= cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datafusion v1.7.2/go.mod h1:62K2NEC6DRlpNmI43WHMWf9Vg/YvN6QVi8EVwifElI0= cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/datalabeling v0.8.2/go.mod h1:cyDvGHuJWu9U/cLDA7d8sb9a0tWLEletStu2sTmg3BE= cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataplex v1.10.1/go.mod h1:1MzmBv8FvjYfc7vDdxhnLFNskikkB+3vl475/XdCDhs= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataproc/v2 v2.2.1/go.mod h1:QdAJLaBjh+l4PVlVZcmrmhGccosY/omC1qwfQ61Zv/o= cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/dataqna v0.8.2/go.mod h1:KNEqgx8TTmUipnQsScOoDpq/VlXVptUqVMZnt30WAPs= cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/datastream v1.10.1/go.mod h1:7ngSYwnw95YFyTd5tOGBxHlOZiL+OtpjheqU7t2/s/c= cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/deploy v1.13.1/go.mod h1:8jeadyLkH9qu9xgO3hVWw8jVr29N1mnW42gRJT8GY6g= cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dialogflow v1.44.1/go.mod h1:n/h+/N2ouKOO+rbe/ZnI186xImpqvCVj2DdsWS/0EAk= cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/dlp v1.10.2/go.mod h1:ZbdKIhcnyhILgccwVDzkwqybthh7+MplGC3kZVZsIOQ= cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/documentai v1.23.2/go.mod h1:Q/wcRT+qnuXOpjAkvOV4A+IeQl04q2/ReT7SSbytLSo= cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/domains v0.9.2/go.mod h1:3YvXGYzZG1Temjbk7EyGCuGGiXHJwVNmwIf+E/cUp5I= cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/edgecontainer v1.1.2/go.mod h1:wQRjIzqxEs9e9wrtle4hQPSR1Y51kqN75dgF7UllZZ4= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/essentialcontacts v1.6.3/go.mod h1:yiPCD7f2TkP82oJEFXFTou8Jl8L6LBRPeBEkTaO0Ggo= cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/eventarc v1.13.1/go.mod h1:EqBxmGHFrruIara4FUQ3RHlgfCn7yo1HYsu2Hpt/C3Y= cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/filestore v1.7.2/go.mod h1:TYOlyJs25f/omgj+vY7/tIG/E7BX369triSPzE4LdgE= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8= cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/functions v1.15.2/go.mod h1:CHAjtcR6OU4XF2HuiVeriEdELNcnvRZSk1Q8RMqy4lE= cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkebackup v1.3.2/go.mod h1:OMZbXzEJloyXMC7gqdSB+EOEQ1AKcpGYvO3s1ec5ixk= cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkeconnect v0.8.2/go.mod h1:6nAVhwchBJYgQCXD2pHBFQNiJNyAd/wyxljpaa6ZPrY= cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkehub v0.14.2/go.mod h1:iyjYH23XzAxSdhrbmfoQdePnlMj2EWcvnR+tHdBQsCY= cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/gkemulticloud v1.0.1/go.mod h1:AcrGoin6VLKT/fwZEYuqvVominLriQBCKmbjtnbMjG8= cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/gsuiteaddons v1.6.2/go.mod h1:K65m9XSgs8hTF3X9nNTPi8IQueljSdYo9F+Mi+s4MyU= cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/iap v1.9.1/go.mod h1:SIAkY7cGMLohLSdBR25BuIxO+I4fXJiL06IBL7cy/5Q= cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/ids v1.4.2/go.mod h1:3vw8DX6YddRu9BncxuzMyWn0g8+ooUjI2gslJ7FH3vk= cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/iot v1.7.2/go.mod h1:q+0P5zr1wRFpw7/MOgDXrG/HVA+l+cSwdObffkrpnSg= cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/kms v1.15.3/go.mod h1:AJdXqHxS2GlPyduM99s9iGqi2nwbviBbhV/hdmt4iOQ= cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/language v1.11.1/go.mod h1:Xyid9MG9WOX3utvDbpX7j3tXDmmDooMyMDqgUVpH17U= cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/lifesciences v0.9.2/go.mod h1:QHEOO4tDzcSAzeJg7s2qwnLM2ji8IRpQl4p6m5Z9yTA= cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= +cloud.google.com/go/longrunning v0.5.2/go.mod h1:nqo6DQbNV2pXhGDbDMoN2bWz68MjZUzqv2YttZiveCs= cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/managedidentities v1.6.2/go.mod h1:5c2VG66eCa0WIq6IylRk3TBW83l161zkFvCj28X7jn8= cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/maps v1.4.1/go.mod h1:BxSa0BnW1g2U2gNdbq5zikLlHUuHW0GFWh7sgML2kIY= cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/mediatranslation v0.8.2/go.mod h1:c9pUaDRLkgHRx3irYE5ZC8tfXGrMYwNZdmDqKMSfFp8= cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/memcache v1.10.2/go.mod h1:f9ZzJHLBrmd4BkguIAa/l/Vle6uTHzHokdnzSWOdQ6A= cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/metastore v1.13.1/go.mod h1:IbF62JLxuZmhItCppcIfzBBfUFq0DIB9HPDoLgWrVOU= cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/monitoring v1.16.1/go.mod h1:6HsxddR+3y9j+o/cMJH6q/KJ/CBTvM/38L/1m7bTRJ4= cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkconnectivity v1.14.1/go.mod h1:LyGPXR742uQcDxZ/wv4EI0Vu5N6NKJ77ZYVnDe69Zug= cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networkmanagement v1.9.1/go.mod h1:CCSYgrQQvW73EJawO2QamemYcOb57LvrDdDU51F0mcI= cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/networksecurity v0.9.2/go.mod h1:jG0SeAttWzPMUILEHDUvFYdQTl8L/E/KC8iZDj85lEI= cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/notebooks v1.10.1/go.mod h1:5PdJc2SgAybE76kFQCWrTfJolCOUQXF97e+gteUUA6A= cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/optimization v1.5.1/go.mod h1:NC0gnUD5MWVAF7XLdoYVPmYYVth93Q6BUzqAq3ZwtV8= cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orchestration v1.8.2/go.mod h1:T1cP+6WyTmh6LSZzeUhvGf0uZVmJyTx7t8z7Vg87+A0= cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/orgpolicy v1.11.2/go.mod h1:biRDpNwfyytYnmCRWZWxrKF22Nkz9eNVj9zyaBdpm1o= cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/osconfig v1.12.2/go.mod h1:eh9GPaMZpI6mEJEuhEjUJmaxvQ3gav+fFEJon1Y8Iw0= cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/oslogin v1.11.1/go.mod h1:OhD2icArCVNUxKqtK0mcSmKL7lgr0LVlQz+v9s1ujTg= cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/phishingprotection v0.8.2/go.mod h1:LhJ91uyVHEYKSKcMGhOa14zMMWfbEdxG032oT6ECbC8= cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/policytroubleshooter v1.9.1/go.mod h1:MYI8i0bCrL8cW+VHN1PoiBTyNZTstCg2WUw2eVC4c4U= cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/privatecatalog v0.9.2/go.mod h1:RMA4ATa8IXfzvjrhhK8J6H4wwcztab+oZph3c6WmtFc= cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recaptchaenterprise/v2 v2.8.1/go.mod h1:JZYZJOeZjgSSTGP4uz7NlQ4/d1w5hGmksVgM0lbEij0= cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommendationengine v0.8.2/go.mod h1:QIybYHPK58qir9CV2ix/re/M//Ty10OxjnnhWdaKS1Y= cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/recommender v1.11.1/go.mod h1:sGwFFAyI57v2Hc5LbIj+lTwXipGu9NW015rkaEM5B18= cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/redis v1.13.2/go.mod h1:0Hg7pCMXS9uz02q+LoEVl5dNHUkIQv+C/3L76fandSA= cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcemanager v1.9.2/go.mod h1:OujkBg1UZg5lX2yIyMo5Vz9O5hf7XQOSV7WxqxxMtQE= cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/resourcesettings v1.6.2/go.mod h1:mJIEDd9MobzunWMeniaMp6tzg4I2GvD3TTmPkc8vBXk= cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/retail v1.14.2/go.mod h1:W7rrNRChAEChX336QF7bnMxbsjugcOCPU44i5kbLiL8= cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/run v1.3.1/go.mod h1:cymddtZOzdwLIAsmS6s+Asl4JoXIDm/K1cpZTxV4Q5s= cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/scheduler v1.10.2/go.mod h1:O3jX6HRH5eKCA3FutMw375XHZJudNIKVonSCHv7ropY= cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/secretmanager v1.11.2/go.mod h1:MQm4t3deoSub7+WNwiC4/tRYgDBHJgJPvswqQVB1Vss= cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/security v1.15.2/go.mod h1:2GVE/v1oixIRHDaClVbHuPcZwAqFM28mXuAKCfMgYIg= cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/securitycenter v1.23.1/go.mod h1:w2HV3Mv/yKhbXKwOCu2i8bCuLtNP1IMHuiYQn4HJq5s= cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicedirectory v1.11.1/go.mod h1:tJywXimEWzNzw9FvtNjsQxxJ3/41jseeILgwU/QLrGI= cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/shell v1.7.2/go.mod h1:KqRPKwBV0UyLickMn0+BY1qIyE98kKyI216sH/TuHmc= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/spanner v1.50.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM= cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/speech v1.19.1/go.mod h1:WcuaWz/3hOlzPFOVo9DUsblMIHwxP589y6ZMtaG+iAA= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/storagetransfer v1.10.1/go.mod h1:rS7Sy0BtPviWYTTJVWCSV4QrbBitgPeuK4/FKa4IdLs= cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/talent v1.6.3/go.mod h1:xoDO97Qd4AK43rGjJvyBHMskiEf3KulgYzcH6YWOVoo= cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/texttospeech v1.7.2/go.mod h1:VYPT6aTOEl3herQjFHYErTlSZJ4vB00Q2ZTmuVgluD4= cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/tpu v1.6.2/go.mod h1:NXh3NDwt71TsPZdtGWgAG5ThDfGd32X1mJ2cMaRlVgU= cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/trace v1.10.2/go.mod h1:NPXemMi6MToRFcSxRl2uDnu/qAlAQ3oULUphcHGh1vA= cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.9.1/go.mod h1:TWIgDZknq2+JD4iRcojgeDtqGEp154HN/uL6hMvylS8= cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.20.1/go.mod h1:3gJS+iDprnj8SY6pe0SwLeC5BUW80NjhwX7INWEuWGU= cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/videointelligence v1.11.2/go.mod h1:ocfIGYtIVmIcWk1DsSGOoDiXca4vaZQII1C85qtoplc= cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vision/v2 v2.7.3/go.mod h1:V0IcLCY7W+hpMKXK1JYE0LV5llEqVmj+UJChjvA1WsM= cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmmigration v1.7.2/go.mod h1:iA2hVj22sm2LLYXGPT1pB63mXHhrH1m/ruux9TwWLd8= cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vmwareengine v1.0.1/go.mod h1:aT3Xsm5sNx0QShk1Jc1B8OddrxAScYLwzVoaiXfdzzk= cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/vpcaccess v1.7.2/go.mod h1:mmg/MnRHv+3e8FJUjeSibVFvQF1cCy2MsFaFqxeY1HU= cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/webrisk v1.9.2/go.mod h1:pY9kfDgAqxUpDBOrG4w8deLfhvJmejKB0qd/5uQIPBc= cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/websecurityscanner v1.6.2/go.mod h1:7YgjuU5tun7Eg2kpKgGnDuEOXWIrh8x8lWrJT4zfmas= cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +cloud.google.com/go/workflows v1.12.1/go.mod h1:5A95OhD/edtOhQd/O741NSfIMezNTbCwLM1P1tBRGHM= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -149,23 +281,69 @@ github.com/dave/patsy v0.0.0-20210517141501-957256f50cba h1:1o36L4EKbZzazMk8iGC4 github.com/dave/patsy v0.0.0-20210517141501-957256f50cba/go.mod h1:qfR88CgEGLoiqDaE+xxDCi5QA5v4vUoW0UCX2Nd5Tlc= github.com/dave/rebecca v0.9.1 h1:jxVfdOxRirbXL28vXMvUvJ1in3djwkVKXCq339qhBL0= github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -174,7 +352,10 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +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= @@ -184,6 +365,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 h1:BHT1/DKsYDGkUgQ2jmMaozVcdk+sVfz0+1ZJq4zkWgw= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= @@ -195,6 +378,9 @@ github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -205,48 +391,170 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.17.0 h1:eU0ffpYuEY7eQ75K+nKr9CI5KcY8h+GPk/9DDlEO1NI= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.17.0/go.mod h1:9P5RK5JS2sjKepuCkqFwPp3etwV/57E0eigLw18Mn1k= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +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= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +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= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +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.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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +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= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +google.golang.org/api v0.139.0/go.mod h1:CVagp6Eekz9CjGZ718Z+sloknzkDJE7Vc1Ckj9+viBk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +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-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From f540e68a6a26e639b5f4d1e76234c8d91cb0153e Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Thu, 2 Nov 2023 17:06:53 +0100 Subject: [PATCH 04/14] Please linter God --- otel/autometrics/instrument.go | 2 +- prometheus/autometrics/instrument.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/otel/autometrics/instrument.go b/otel/autometrics/instrument.go index c1c0a05..955d11d 100644 --- a/otel/autometrics/instrument.go +++ b/otel/autometrics/instrument.go @@ -94,7 +94,7 @@ func Instrument(ctx context.Context, err *error) { // NOTE: This call means that goroutines that outlive this function as the caller will not have access to parent // caller information, but hopefully by that point we got all the necessary accesses done. // If not, it is a convenience we accept to give up to prevent memory usage from exploding - am.PopFunctionName(ctx) + _ = am.PopFunctionName(ctx) } // PreInstrument runs the "before wrappee" part of instrumentation. diff --git a/prometheus/autometrics/instrument.go b/prometheus/autometrics/instrument.go index dfb7226..9db0e76 100644 --- a/prometheus/autometrics/instrument.go +++ b/prometheus/autometrics/instrument.go @@ -115,7 +115,7 @@ func Instrument(ctx context.Context, err *error) { // NOTE: This call means that goroutines that outlive this function as the caller will not have access to parent // caller information, but hopefully by that point we got all the necessary accesses done. // If not, it is a convenience we accept to give up to prevent memory usage from exploding - am.PopFunctionName(ctx) + _ = am.PopFunctionName(ctx) } // PreInstrument runs the "before wrappee" part of instrumentation. From a6a75d95c5898a5cecff40f13619a07edcd28237 Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Thu, 2 Nov 2023 17:22:31 +0100 Subject: [PATCH 05/14] Please linter more --- pkg/autometrics/ctx.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/autometrics/ctx.go b/pkg/autometrics/ctx.go index c5458a4..73cb129 100644 --- a/pkg/autometrics/ctx.go +++ b/pkg/autometrics/ctx.go @@ -269,7 +269,8 @@ func FillTracingAndCallerInfo(ctx context.Context) context.Context { // NOTE: This also means that goroutines that outlive their as the caller will not have access to parent // caller information, but hopefully by that point we got all the necessary accesses done. // If not, it is a convenience we accept to give up to prevent memory usage from exploding. - PushFunctionName(ctx, callInfo.Current) + // TODO: once settled on a login library, log the error instead of ignoring it + _ = PushFunctionName(ctx, callInfo.Current) return ctx } From daa9f852eea32b85efaf70b563d5cadf3a3cc37f Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Fri, 3 Nov 2023 15:12:00 +0100 Subject: [PATCH 06/14] Split context generation from defer statement This allow library users to reuse the context augmented with Autometrics, so the tracing and caller information can be a lot more precise Fixes: #78 --- examples/otel/cmd/main.go | 10 +- examples/web/cmd/main.go | 17 +- internal/generate/context.go | 363 +++++++++++++++++++++++++++++ internal/generate/defer.go | 326 +++----------------------- internal/generate/defer_test.go | 75 +++--- internal/generate/generate.go | 15 +- internal/generate/generate_test.go | 62 +++-- 7 files changed, 511 insertions(+), 357 deletions(-) create mode 100644 internal/generate/context.go diff --git a/examples/otel/cmd/main.go b/examples/otel/cmd/main.go index 8e56a1e..d15c939 100644 --- a/examples/otel/cmd/main.go +++ b/examples/otel/cmd/main.go @@ -98,13 +98,14 @@ func main() { // //autometrics:doc --slo "API" --latency-target 99 --latency-ms 5 func indexHandler(w http.ResponseWriter, r *http.Request) error { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + r.Context() = autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(5000000*time.Nanosecond, 99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(r.Context(), nil) //autometrics:defer msSleep := rand.Intn(200) time.Sleep(time.Duration(msSleep) * time.Millisecond) @@ -148,13 +149,14 @@ var handlerError = errors.New("failed to handle request") // //autometrics:doc --slo "API" --success-target 90 func randomErrorHandler(w http.ResponseWriter, r *http.Request) (err error) { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + r.Context() = autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertSuccess(90), - )), &err) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(r.Context(), &err) //autometrics:defer isOk := rand.Intn(10) == 0 diff --git a/examples/web/cmd/main.go b/examples/web/cmd/main.go index f420007..8a3868b 100644 --- a/examples/web/cmd/main.go +++ b/examples/web/cmd/main.go @@ -98,22 +98,23 @@ func main() { // // autometrics:doc-end Generated documentation by Autometrics. // -// [Request Rate]: http://localhost:9090/graph?g0.expr=%23+Rate+of+calls+to+the+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 -// [Error Ratio]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+calls+to+the+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bfunction%3D%22indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 -// [Latency (95th and 99th percentiles)]: http://localhost:9090/graph?g0.expr=%23+95th+and+99th+percentile+latencies+%28in+seconds%29+for+the+%60indexHandler%60+function%0A%0Alabel_replace%28histogram_quantile%280.99%2C+sum+by+%28le%2C+function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_duration_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C+%22percentile_latency%22%2C+%2299%22%2C+%22%22%2C+%22%22%29+or+label_replace%28histogram_quantile%280.95%2C+sum+by+%28le%2C+function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_duration_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C%22percentile_latency%22%2C+%2295%22%2C+%22%22%2C+%22%22%29&g0.tab=0 -// [Concurrent Calls]: http://localhost:9090/graph?g0.expr=%23+Concurrent+calls+to+the+%60indexHandler%60+function%0A%0Asum+by+%28function%2C+module%2C+version%2C+commit%29+%28function_calls_concurrent%7Bfunction%3D%22indexHandler%22%7D+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 -// [Request Rate Callee]: http://localhost:9090/graph?g0.expr=%23+Rate+of+function+calls+emanating+from+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bcaller%3D%22main.indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 -// [Error Ratio Callee]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+function+emanating+from+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bcaller%3D%22main.indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bcaller%3D%22main.indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 +// [Request Rate]: http://localhost:9090/graph?g0.expr=%23+Rate+of+calls+to+the+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 +// [Error Ratio]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+calls+to+the+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bfunction%3D%22indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 +// [Latency (95th and 99th percentiles)]: http://localhost:9090/graph?g0.expr=%23+95th+and+99th+percentile+latencies+%28in+seconds%29+for+the+%60indexHandler%60+function%0A%0Alabel_replace%28histogram_quantile%280.99%2C+sum+by+%28le%2C+function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_duration_seconds_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C+%22percentile_latency%22%2C+%2299%22%2C+%22%22%2C+%22%22%29+or+label_replace%28histogram_quantile%280.95%2C+sum+by+%28le%2C+function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_duration_seconds_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C%22percentile_latency%22%2C+%2295%22%2C+%22%22%2C+%22%22%29&g0.tab=0 +// [Concurrent Calls]: http://localhost:9090/graph?g0.expr=%23+Concurrent+calls+to+the+%60indexHandler%60+function%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28function_calls_concurrent%7Bfunction%3D%22indexHandler%22%7D+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 +// [Request Rate Callee]: http://localhost:9090/graph?g0.expr=%23+Rate+of+function+calls+emanating+from+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 +// [Error Ratio Callee]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+function+emanating+from+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 // //autometrics:inst --slo "API" --latency-target 99 --latency-ms 5 func indexHandler(w http.ResponseWriter, r *http.Request) error { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + r.Context() = autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(5000000*time.Nanosecond, 99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(r.Context(), nil) //autometrics:defer msSleep := rand.Intn(200) time.Sleep(time.Duration(msSleep) * time.Millisecond) diff --git a/internal/generate/context.go b/internal/generate/context.go new file mode 100644 index 0000000..c3b9dd0 --- /dev/null +++ b/internal/generate/context.go @@ -0,0 +1,363 @@ +package generate // import "github.com/autometrics-dev/autometrics-go/internal/generate" + +import ( + "fmt" + "go/token" + "log" + "reflect" + "strings" + + "golang.org/x/exp/slices" + + internal "github.com/autometrics-dev/autometrics-go/internal/autometrics" + am "github.com/autometrics-dev/autometrics-go/pkg/autometrics" + + "github.com/dave/dst" + "github.com/dave/dst/decorator" +) + +const ( + vanillaContext = "context" + gin = "github.com/gin-gonic/gin" + buffalo = "github.com/gobuffalo/buffalo" + echoV4 = "github.com/labstack/echo/v4" + netHttp = "net/http" + amDefaultContextName = "amCtx" + contextDecoration = "//autometrics:shadow-ctx" +) + +// injectContextStatement add all the necessary information into context to produce the correct context shadowing statement. +func injectContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) (identName string, err error) { + err = detectContext(ctx, funcDeclaration) + if err != nil { + return "", fmt.Errorf("failed to get context for tracing: %w", err) + } + + autometricsContextStatement, err := buildAutometricsContextStatement(ctx) + if err != nil { + return "", fmt.Errorf("failed to build the defer statement for instrumentation: %w", err) + } + + funcDeclaration.Body.List = append([]dst.Stmt{&autometricsContextStatement}, funcDeclaration.Body.List...) + + // The hard cast is okay here because we just built ourselves the statement. + return autometricsContextStatement.Lhs[0].(*dst.Ident).Name, nil +} + +// removeContextStatement removes, if detected, a previously injected context shadowing statement. +func removeContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { + for index, statement := range funcDeclaration.Body.List { + if assignStatement, ok := statement.(*dst.AssignStmt); ok { + decorations := assignStatement.Decorations().End + if slices.Contains(decorations.All(), contextDecoration) { + funcDeclaration.Body.List = append(funcDeclaration.Body.List[:index], funcDeclaration.Body.List[index+1:]...) + return nil + } + } + } + return nil +} + +// findContextStatement finds a previously injected context shadowing statement. +// It also updates the passed context so that the ContextVariableName is accurate. +func findContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) (index int, found bool) { + for index, statement := range funcDeclaration.Body.List { + if assignStatement, ok := statement.(*dst.AssignStmt); ok { + decorations := assignStatement.Decorations().End + if slices.Contains(decorations.All(), contextDecoration) { + ctx.RuntimeCtx.ContextVariableName = assignStatement.Lhs[0].(*dst.Ident).Name + return index, true + } + } + } + return 0, false +} + +// buildAutometricsContextStatement builds the AST node for the context shadowing instrumentation statement to be inserted. +func buildAutometricsContextStatement(ctx *internal.GeneratorContext) (dst.AssignStmt, error) { + preInstrumentArg, contextShadowName, err := buildAutometricsContextNode(ctx) + if err != nil { + return dst.AssignStmt{}, fmt.Errorf("could not generate the runtime context value: %w", err) + } + + // Crude detection of "should the assignment be `:=` or `=`" + assignmentToken := token.ASSIGN + if contextShadowName == amDefaultContextName { + assignmentToken = token.DEFINE + } + + // TODO: deal with cases where the context variable name does not exist. + statement := dst.AssignStmt{ + Lhs: []dst.Expr{ + dst.NewIdent(contextShadowName), + }, + Tok: assignmentToken, + Rhs: []dst.Expr{ + &dst.CallExpr{ + Fun: dst.NewIdent(fmt.Sprintf("%vPreInstrument", autometricsNamespacePrefix(ctx))), + Args: []dst.Expr{ + preInstrumentArg, + }, + }, + }, + } + + statement.Decs.Before = dst.NewLine + statement.Decs.End = []string{contextDecoration} + statement.Decs.After = dst.NewLine + + return statement, nil +} + +// buildAutometricsContextNode creates an AST node representing the runtime context to inject in the instrumented code. +// +// This AST node is later used to create the defer statement responsible for instrumenting the code. +func buildAutometricsContextNode(agc *internal.GeneratorContext) (newContextCall *dst.CallExpr, contextShadowName string, err error) { + // Using https://github.com/dave/dst/issues/73 workaround + + var options []string + + if agc.RuntimeCtx.TraceIDGetter != "" { + options = append(options, fmt.Sprintf("%vWithTraceID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TraceIDGetter)) + } + if agc.RuntimeCtx.SpanIDGetter != "" { + options = append(options, fmt.Sprintf("%vWithSpanID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.SpanIDGetter)) + } + + options = append(options, + fmt.Sprintf("%vWithConcurrentCalls(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackConcurrentCalls), + fmt.Sprintf("%vWithCallerName(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackCallerName), + ) + + if agc.RuntimeCtx.AlertConf != nil { + options = append(options, fmt.Sprintf("%vWithSloName(%#v)", + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.AlertConf.ServiceName, + )) + if agc.RuntimeCtx.AlertConf.Latency != nil { + options = append(options, fmt.Sprintf("%vWithAlertLatency(%#v * time.Nanosecond, %#v)", + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.AlertConf.Latency.Target, + agc.RuntimeCtx.AlertConf.Latency.Objective, + )) + } + if agc.RuntimeCtx.AlertConf.Success != nil { + options = append(options, fmt.Sprintf("%vWithAlertSuccess(%#v)", + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.AlertConf.Success.Objective)) + } + } + + contextShadowName = agc.RuntimeCtx.ContextVariableName + if contextShadowName == "nil" { + contextShadowName = amDefaultContextName + } + + var buf strings.Builder + _, err = fmt.Fprintf( + &buf, + ` +package main + +var dummy = %vNewContext( + %s, +`, + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.ContextVariableName, + ) + if err != nil { + return nil, contextShadowName, fmt.Errorf("could not write string builder to build dummy source code: %w", err) + } + + for _, o := range options { + _, err = fmt.Fprintf(&buf, "\t%s,\n", o) + if err != nil { + return nil, contextShadowName, fmt.Errorf("could not write string builder to build dummy source code: %w", err) + } + } + + _, err = fmt.Fprint(&buf, ")\n") + if err != nil { + return nil, contextShadowName, fmt.Errorf("could not write string builder to build dummy source code: %w", err) + } + + sourceCode := buf.String() + sourceAst, err := decorator.Parse(sourceCode) + if err != nil { + return nil, contextShadowName, fmt.Errorf( + "could not parse dummy code\n%s\n: %w", + sourceCode, + err, + ) + } + + genDeclNode, ok := sourceAst.Decls[0].(*dst.GenDecl) + if !ok { + return nil, contextShadowName, fmt.Errorf("unexpected node in the dummy code (expected dst.GenDecl): %w", err) + } + + specNode, ok := genDeclNode.Specs[0].(*dst.ValueSpec) + if !ok { + return nil, contextShadowName, fmt.Errorf("unexpected node in the dummy code (expected dst.ValueSpec): %w", err) + } + + callExpr, ok := specNode.Values[0].(*dst.CallExpr) + if !ok { + return nil, contextShadowName, fmt.Errorf("unexpected node in the dummy code (expected dst.CallExpr): %w", err) + } + + return callExpr, contextShadowName, nil +} + +// detectContextIdentImpl is a Context detection logic helper for arguments whose type is an identifier +// +// The function returns true when it found enough information to ask for iteration to stop. +func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, ident *dst.Ident) (bool, error) { + typeName := ident.Name + // If argType is just a dst.Ident when parsing, that means + // it is a single identifier ('Context', _not_ 'context.Context'). + // Therefore we can solely check imports that got imported as '.' + for alias, canonical := range ctx.ImportsMap { + if alias != "." { + continue + } + + if canonical == vanillaContext && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == netHttp && typeName == "Request" { + if argName == "_" { + log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") + ctx.RuntimeCtx.ContextVariableName = "nil" + } else { + ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) + } + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == gin && typeName == "Context" { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + + // Buffalo context embeds a context.Context so it can work like vanilla + if canonical == buffalo && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == echoV4 && typeName == "Context" { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + } + + return false, nil +} + +// detectContextIdentImpl is a Context detection logic helper for arguments whose type is a selector expression. +// +// The function returns true when it found enough information to ask for iteration to stop. +func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, selector *dst.SelectorExpr) (bool, error) { + typeName := selector.Sel.Name + if parent, p_ok := selector.X.(*dst.Ident); p_ok { + parentName := parent.Name + for alias, canonical := range ctx.ImportsMap { + if canonical == vanillaContext && parentName == alias && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == netHttp && parentName == alias && typeName == "Request" { + ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) + if argName == "_" { + log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") + ctx.RuntimeCtx.ContextVariableName = "nil" + } else { + ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) + } + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == gin && parentName == alias && typeName == "Context" { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + + // Buffalo context embeds a context.Context so it can work like vanilla + if canonical == buffalo && parentName == alias && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == echoV4 && typeName == "Context" && (parentName == alias || parentName == "echo") { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + } + } else { + // TODO: log that autometrics cannot detect multi-nested contexts instead of errorring + // continue + return true, fmt.Errorf("expecting parent to be an identifier, got %s instead", reflect.TypeOf(selector.X).String()) + } + return false, nil +} + +// detectContext modifies a RuntimeCtxInfo to inject context when detected in the function signature. +func detectContext(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { + arguments := funcDeclaration.Type.Params.List + for _, argGroup := range arguments { + if len(argGroup.Names) > 1 { + continue + } + argName := argGroup.Names[0].Name + if argGroup.Type == nil { + continue + } + + if argType, ok := argGroup.Type.(*dst.Ident); ok { + if found, err := detectContextIdentImpl(ctx, argName, argType); found { + return err + } + } else if argType, ok := argGroup.Type.(*dst.SelectorExpr); ok { + if found, err := detectContextSelectorImpl(ctx, argName, argType); found { + return err + } + } else if argType, ok := argGroup.Type.(*dst.StarExpr); ok { + if ident, ok := argType.X.(*dst.Ident); ok { + if found, err := detectContextIdentImpl(ctx, argName, ident); found { + return err + } + } else if selector, ok := argType.X.(*dst.SelectorExpr); ok { + if found, err := detectContextSelectorImpl(ctx, argName, selector); found { + return err + } + } else { + return fmt.Errorf("expecting the type being pointed to to be an identifier, got %s instead", reflect.TypeOf(argType.X).String()) + } + } else { + return fmt.Errorf("expecting the type of argGroup to be an identifier, got %s instead", reflect.TypeOf(argGroup.Type).String()) + } + } + + ctx.RuntimeCtx.ContextVariableName = "nil" + return nil +} diff --git a/internal/generate/defer.go b/internal/generate/defer.go index 1559f82..0be3302 100644 --- a/internal/generate/defer.go +++ b/internal/generate/defer.go @@ -2,34 +2,28 @@ package generate // import "github.com/autometrics-dev/autometrics-go/internal/g import ( "fmt" - "log" - "reflect" - "strings" "golang.org/x/exp/slices" internal "github.com/autometrics-dev/autometrics-go/internal/autometrics" - am "github.com/autometrics-dev/autometrics-go/pkg/autometrics" "github.com/dave/dst" - "github.com/dave/dst/decorator" ) const ( - vanillaContext = "context" - gin = "github.com/gin-gonic/gin" - buffalo = "github.com/gobuffalo/buffalo" - echoV4 = "github.com/labstack/echo/v4" - netHttp = "net/http" + deferDecoration = "//autometrics:defer" ) // injectDeferStatement add all the necessary information into context to produce the correct defer instrumentation statement. +// +// injectDeferStatement is _always_ meant to be called after injectContextStatement, so the injection will always try to happen after the +// statemtent marked with the shadowing marker func injectDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { - err := detectContext(ctx, funcDeclaration) - if err != nil { - return fmt.Errorf("failed to get context for tracing: %w", err) + contextAssignmentIndex, found := findContextStatement(ctx, funcDeclaration) + if !found { + return fmt.Errorf("failed to get context: the %v statement is missing", contextDecoration) } - firstStatement := funcDeclaration.Body.List[0] + variable, err := errorReturnValueName(funcDeclaration) if err != nil { return fmt.Errorf("failed to get error return value name: %w", err) @@ -46,31 +40,38 @@ func injectDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.F return fmt.Errorf("failed to build the defer statement for instrumentation: %w", err) } - if deferStatement, ok := firstStatement.(*dst.DeferStmt); ok { - decorations := deferStatement.Decorations().End + funcDeclaration.Body.List = insertStatements(funcDeclaration.Body.List, contextAssignmentIndex+1, []dst.Stmt{&autometricsDeferStatement}) + return nil +} - if slices.Contains(decorations.All(), "//autometrics:defer") { - funcDeclaration.Body.List[0] = &autometricsDeferStatement - } else { - funcDeclaration.Body.List = append([]dst.Stmt{&autometricsDeferStatement}, funcDeclaration.Body.List...) - } - } else { - funcDeclaration.Body.List = append([]dst.Stmt{&autometricsDeferStatement}, funcDeclaration.Body.List...) +func insertStatements(inputArray []dst.Stmt, index int, values []dst.Stmt) []dst.Stmt { + if len(inputArray) == index { // nil or empty slice or after last element + return append(inputArray, values...) } - return nil + + beginning := inputArray[:index] + // Maybe the deep copy is not necessary, wasn't able to + // specify the semantics properly here. + end := make([]dst.Stmt, len(inputArray[index:])) + copy(end, inputArray[index:]) + + inputArray = append(beginning, values...) + inputArray = append(inputArray, end...) + + return inputArray } // removeDeferStatement removes, if detected, a previously injected defer statement. func removeDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { - firstStatement := funcDeclaration.Body.List[0] - - if deferStatement, ok := firstStatement.(*dst.DeferStmt); ok { - decorations := deferStatement.Decorations().End - if slices.Contains(decorations.All(), "//autometrics:defer") { - funcDeclaration.Body.List = funcDeclaration.Body.List[1:] + for index, statement := range funcDeclaration.Body.List { + if deferStatement, ok := statement.(*dst.DeferStmt); ok { + decorations := deferStatement.Decorations().End + if slices.Contains(decorations.All(), deferDecoration) { + funcDeclaration.Body.List = append(funcDeclaration.Body.List[:index], funcDeclaration.Body.List[index+1:]...) + return nil + } } } - return nil } @@ -99,104 +100,9 @@ func errorReturnValueName(funcNode *dst.FuncDecl) (string, error) { return "", nil } -// buildAutometricsContextNode creates an AST node representing the runtime context to inject in the instrumented code. -// -// This AST node is later used to create the defer statement responsible for instrumenting the code. -func buildAutometricsContextNode(agc *internal.GeneratorContext) (*dst.CallExpr, error) { - // Using https://github.com/dave/dst/issues/73 workaround - - var options []string - - if agc.RuntimeCtx.TraceIDGetter != "" { - options = append(options, fmt.Sprintf("%vWithTraceID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TraceIDGetter)) - } - if agc.RuntimeCtx.SpanIDGetter != "" { - options = append(options, fmt.Sprintf("%vWithSpanID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.SpanIDGetter)) - } - - options = append(options, - fmt.Sprintf("%vWithConcurrentCalls(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackConcurrentCalls), - fmt.Sprintf("%vWithCallerName(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackCallerName), - ) - - if agc.RuntimeCtx.AlertConf != nil { - options = append(options, fmt.Sprintf("%vWithSloName(%#v)", - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.AlertConf.ServiceName, - )) - if agc.RuntimeCtx.AlertConf.Latency != nil { - options = append(options, fmt.Sprintf("%vWithAlertLatency(%#v * time.Nanosecond, %#v)", - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.AlertConf.Latency.Target, - agc.RuntimeCtx.AlertConf.Latency.Objective, - )) - } - if agc.RuntimeCtx.AlertConf.Success != nil { - options = append(options, fmt.Sprintf("%vWithAlertSuccess(%#v)", - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.AlertConf.Success.Objective)) - } - } - - var buf strings.Builder - _, err := fmt.Fprintf( - &buf, - ` -package main - -var dummy = %vNewContext( - %s, -`, - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.ContextVariableName, - ) - if err != nil { - return nil, fmt.Errorf("could not write string builder to build dummy source code: %w", err) - } - - for _, o := range options { - _, err = fmt.Fprintf(&buf, "\t%s,\n", o) - if err != nil { - return nil, fmt.Errorf("could not write string builder to build dummy source code: %w", err) - } - } - - _, err = fmt.Fprint(&buf, ")\n") - if err != nil { - return nil, fmt.Errorf("could not write string builder to build dummy source code: %w", err) - } - - sourceCode := buf.String() - sourceAst, err := decorator.Parse(sourceCode) - if err != nil { - return nil, fmt.Errorf( - "could not parse dummy code\n%s\n: %w", - sourceCode, - err, - ) - } - - genDeclNode, ok := sourceAst.Decls[0].(*dst.GenDecl) - if !ok { - return nil, fmt.Errorf("unexpected node in the dummy code (expected dst.GenDecl): %w", err) - } - - specNode, ok := genDeclNode.Specs[0].(*dst.ValueSpec) - if !ok { - return nil, fmt.Errorf("unexpected node in the dummy code (expected dst.ValueSpec): %w", err) - } - - callExpr, ok := specNode.Values[0].(*dst.CallExpr) - if !ok { - return nil, fmt.Errorf("unexpected node in the dummy code (expected dst.CallExpr): %w", err) - } - - return callExpr, nil -} - // buildAutometricsDeferStatement builds the AST node for the defer instrumentation statement to be inserted. -func buildAutometricsDeferStatement(ctx *internal.GeneratorContext, secondVar string) (dst.DeferStmt, error) { - preInstrumentArg, err := buildAutometricsContextNode(ctx) +func buildAutometricsDeferStatement(ctx *internal.GeneratorContext, errorPointerVariable string) (dst.DeferStmt, error) { + _, contextName, err := buildAutometricsContextNode(ctx) if err != nil { return dst.DeferStmt{}, fmt.Errorf("could not generate the runtime context value: %w", err) } @@ -204,19 +110,14 @@ func buildAutometricsDeferStatement(ctx *internal.GeneratorContext, secondVar st Call: &dst.CallExpr{ Fun: dst.NewIdent(fmt.Sprintf("%vInstrument", autometricsNamespacePrefix(ctx))), Args: []dst.Expr{ - &dst.CallExpr{ - Fun: dst.NewIdent(fmt.Sprintf("%vPreInstrument", autometricsNamespacePrefix(ctx))), - Args: []dst.Expr{ - preInstrumentArg, - }, - }, - dst.NewIdent(secondVar), + dst.NewIdent(contextName), + dst.NewIdent(errorPointerVariable), }, }, } statement.Decs.Before = dst.NewLine - statement.Decs.End = []string{"//autometrics:defer"} + statement.Decs.End = []string{deferDecoration} statement.Decs.After = dst.EmptyLine return statement, nil @@ -229,156 +130,3 @@ func autometricsNamespacePrefix(ctx *internal.GeneratorContext) string { return fmt.Sprintf("%v.", ctx.FuncCtx.ImplImportName) } } - -// detectContextIdentImpl is a Context detection logic helper for arguments whose type is an identifier -// -// The function returns true when it found enough information to ask for iteration to stop. -func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, ident *dst.Ident) (bool, error) { - typeName := ident.Name - // If argType is just a dst.Ident when parsing, that means - // it is a single identifier ('Context', _not_ 'context.Context'). - // Therefore we can solely check imports that got imported as '.' - for alias, canonical := range ctx.ImportsMap { - if alias != "." { - continue - } - - if canonical == vanillaContext && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == netHttp && typeName == "Request" { - if argName == "_" { - log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") - ctx.RuntimeCtx.ContextVariableName = "nil" - } else { - ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) - } - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == gin && typeName == "Context" { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - - // Buffalo context embeds a context.Context so it can work like vanilla - if canonical == buffalo && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == echoV4 && typeName == "Context" { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - } - - return false, nil -} - -// detectContextIdentImpl is a Context detection logic helper for arguments whose type is a selector expression. -// -// The function returns true when it found enough information to ask for iteration to stop. -func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, selector *dst.SelectorExpr) (bool, error) { - typeName := selector.Sel.Name - if parent, p_ok := selector.X.(*dst.Ident); p_ok { - parentName := parent.Name - for alias, canonical := range ctx.ImportsMap { - if canonical == vanillaContext && parentName == alias && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == netHttp && parentName == alias && typeName == "Request" { - ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) - if argName == "_" { - log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") - ctx.RuntimeCtx.ContextVariableName = "nil" - } else { - ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) - } - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == gin && parentName == alias && typeName == "Context" { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - - // Buffalo context embeds a context.Context so it can work like vanilla - if canonical == buffalo && parentName == alias && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == echoV4 && typeName == "Context" && (parentName == alias || parentName == "echo") { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - } - } else { - // TODO: log that autometrics cannot detect multi-nested contexts instead of errorring - // continue - return true, fmt.Errorf("expecting parent to be an identifier, got %s instead", reflect.TypeOf(selector.X).String()) - } - return false, nil -} - -// detectContext modifies a RuntimeCtxInfo to inject context when detected in the function signature. -func detectContext(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { - arguments := funcDeclaration.Type.Params.List - for _, argGroup := range arguments { - if len(argGroup.Names) > 1 { - continue - } - argName := argGroup.Names[0].Name - if argGroup.Type == nil { - continue - } - - if argType, ok := argGroup.Type.(*dst.Ident); ok { - if found, err := detectContextIdentImpl(ctx, argName, argType); found { - return err - } - } else if argType, ok := argGroup.Type.(*dst.SelectorExpr); ok { - if found, err := detectContextSelectorImpl(ctx, argName, argType); found { - return err - } - } else if argType, ok := argGroup.Type.(*dst.StarExpr); ok { - if ident, ok := argType.X.(*dst.Ident); ok { - if found, err := detectContextIdentImpl(ctx, argName, ident); found { - return err - } - } else if selector, ok := argType.X.(*dst.SelectorExpr); ok { - if found, err := detectContextSelectorImpl(ctx, argName, selector); found { - return err - } - } else { - return fmt.Errorf("expecting the type being pointed to to be an identifier, got %s instead", reflect.TypeOf(argType.X).String()) - } - } else { - return fmt.Errorf("expecting the type of argGroup to be an identifier, got %s instead", reflect.TypeOf(argGroup.Type).String()) - } - } - - ctx.RuntimeCtx.ContextVariableName = "nil" - return nil -} diff --git a/internal/generate/defer_test.go b/internal/generate/defer_test.go index 4f8ee6c..6f7d1fa 100644 --- a/internal/generate/defer_test.go +++ b/internal/generate/defer_test.go @@ -42,13 +42,14 @@ func main(thisIsAContext context.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext context.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -99,13 +100,14 @@ func main(thisIsAContext vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -156,13 +158,14 @@ func main(thisIsAContext Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -213,13 +216,14 @@ func main(w http.ResponseWriter, req *http.Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w http.ResponseWriter, req *http.Request) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\treq.Context() = prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(req.Context(), nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -270,13 +274,14 @@ func main(w vanilla.ResponseWriter, req *vanilla.Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w vanilla.ResponseWriter, req *vanilla.Request) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\treq.Context() = prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(req.Context(), nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -327,13 +332,14 @@ func main(w ResponseWriter, req *Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w ResponseWriter, req *Request) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\treq.Context() = prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(req.Context(), nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -384,13 +390,14 @@ func main(thisIsAContext buffalo.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext buffalo.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -441,13 +448,14 @@ func main(thisIsAContext vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -498,13 +506,14 @@ func main(thisIsAContext Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -555,7 +564,7 @@ func main(thisIsAContext echo.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext echo.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.Get(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.Get(\"autometricsSpanID\"))),\n" + @@ -563,7 +572,8 @@ func main(thisIsAContext echo.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -614,7 +624,7 @@ func main(thisIsAContext vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.Get(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.Get(\"autometricsSpanID\"))),\n" + @@ -622,7 +632,8 @@ func main(thisIsAContext vanilla.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -673,7 +684,7 @@ func main(thisIsAContext Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.Get(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.Get(\"autometricsSpanID\"))),\n" + @@ -681,7 +692,8 @@ func main(thisIsAContext Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -732,7 +744,7 @@ func main(thisIsAContext *gin.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext *gin.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.GetString(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.GetString(\"autometricsSpanID\"))),\n" + @@ -740,7 +752,8 @@ func main(thisIsAContext *gin.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -791,7 +804,7 @@ func main(thisIsAContext *vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext *vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.GetString(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.GetString(\"autometricsSpanID\"))),\n" + @@ -799,7 +812,8 @@ func main(thisIsAContext *vanilla.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -850,7 +864,7 @@ func main(thisIsAContext *Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext *Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.GetString(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.GetString(\"autometricsSpanID\"))),\n" + @@ -858,7 +872,8 @@ func main(thisIsAContext *Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" diff --git a/internal/generate/generate.go b/internal/generate/generate.go index 5f61d06..c565daa 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -154,6 +154,13 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu funcDeclaration.Name.Name, err) } + err = removeContextStatement(ctx, funcDeclaration) + if err != nil { + return fmt.Errorf( + "error removing an older autometrics context statement in %v: %w", + funcDeclaration.Name.Name, + err) + } // Early exit if we wanted to remove everything if ctx.RemoveEverything { @@ -192,8 +199,14 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu funcDeclaration.Decorations().Start.Replace(docComments...) } + // context statement + _, err := injectContextStatement(ctx, funcDeclaration) + if err != nil { + return fmt.Errorf("failed to inject context statement: %w", err) + } + // defer statement - err := injectDeferStatement(ctx, funcDeclaration) + err = injectDeferStatement(ctx, funcDeclaration) if err != nil { return fmt.Errorf("failed to inject defer statement: %w", err) } diff --git a/internal/generate/generate_test.go b/internal/generate/generate_test.go index 431c88c..d95a602 100644 --- a/internal/generate/generate_test.go +++ b/internal/generate/generate_test.go @@ -69,13 +69,14 @@ import ( // //autometrics:inst --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -148,13 +149,14 @@ import ( // //autometrics:inst --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -199,13 +201,14 @@ import ( // //autometrics:inst --no-doc --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -271,11 +274,12 @@ import ( // [Request Rate Callee]: http://localhost:9090/graph?g0.expr=%23+Rate+of+function+calls+emanating+from+%60main%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22main%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 // [Error Ratio Callee]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+function+emanating+from+%60main%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22main%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22main%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -315,11 +319,12 @@ import ( ) func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -361,13 +366,14 @@ import ( //autometrics:inst --no-doc --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -525,13 +531,14 @@ import ( // //autometrics:inst --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("API"), prom.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -573,13 +580,14 @@ import "github.com/autometrics-dev/autometrics-go/prometheus/autometrics" // //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( nil, autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -630,13 +638,14 @@ import ( // //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( nil, autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -687,13 +696,14 @@ import "github.com/autometrics-dev/autometrics-go/prometheus/autometrics" // This comment is associated with the main function. //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( nil, autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -751,13 +761,14 @@ import ( // //autometrics:inst --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("API"), prom.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -1388,7 +1399,7 @@ func implementContextCodeGenTest(t *testing.T, contextToSerialize internal.Runti }, } - node, err := buildAutometricsContextNode(&sourceContext) + node, _, err := buildAutometricsContextNode(&sourceContext) if err != nil { t.Fatalf("error building the context node: %s", err) } @@ -1526,13 +1537,14 @@ import _ "github.com/autometrics-dev/autometrics-go/prometheus/autometrics" // //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer Instrument(PreInstrument(NewContext( + amCtx := PreInstrument(NewContext( nil, WithConcurrentCalls(true), WithCallerName(true), WithSloName("API"), WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } From c3fb7ddd85f00e9e3bfbf5f94a2c84a671f8a6dd Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 10:15:16 +0100 Subject: [PATCH 07/14] Update changelog --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 671268e..aebcd76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,33 @@ versioning](https://go.dev/doc/modules/version-numbers). ## [Unreleased](https://github.com/autometrics-dev/autometrics-go/compare/v0.8.2...main) +The main goal of this release is to reach compatibility with 1.0.0 version of Autometrics +specification. + ### Added +- [All] `autometrics` now also optionnally adds the repository where the code comes from + in the `build_info` metric. `repository.url` and `repository.provider` can be either + set in the `BuildInformation` structure when calling `autometrics.Init`, or by setting + environment variables `AUTOMETRICS_REPOSITORY_URL` and `AUTOMETRICS_REPOSITORY_PROVIDER`, + respectively. + ### Changed +- [All] `autometrics` now inserts 2 statements in each function it instruments. The context + created to track the function execution is now put in a variable, so that callees in the + function body can optionnally use the context to help with better trace/span/call graph + tracking. If `autometrics` detects a `context.Context` it can use, it will shadow the + context with the autometrics augmented one to reduce the changes to make in the code. + Currently, `autometrics` can detect arguments of specific types in the function signatures + to replace contexts: + + `context.Context` + + `http.Request` + + `buffalo.Request` +- [Generator] The generator now tries to keep going with instrumentation even if some instrumentation + fails. All files will stay modified, and the generator will exit with an error code and output + all the collected errors. + ### Deprecated ### Removed @@ -20,6 +43,10 @@ versioning](https://go.dev/doc/modules/version-numbers). ### Security +- Update all dependencies to reduce dependabot alerts in + + `google.golang.org/grpc` + + `golang.org/x/net` + ## [0.8.2](https://github.com/autometrics-dev/autometrics-go/releases/tag/v0.8.2) 2023-10-20 ### Added From ffdd04c36ecffeadb26802a14ac93f5f8453c6af Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 10:49:35 +0100 Subject: [PATCH 08/14] Keep going through a file even if a function errors --- internal/generate/generate.go | 97 +++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 27 deletions(-) diff --git a/internal/generate/generate.go b/internal/generate/generate.go index c565daa..7618c5b 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -28,6 +28,23 @@ const ( AmOtelPackage = "\"github.com/autometrics-dev/autometrics-go/otel/autometrics\"" ) +type GenerateError struct { + FunctionName string + Detail error +} + +type GenerateErrors []GenerateError + +func (errs GenerateErrors) Error() string { + var sb strings.Builder + + for _, err := range errs { + sb.WriteString(fmt.Sprintf("in %v: %v\n", err.FunctionName, err.Detail.Error())) + } + + return sb.String() +} + // TransformFile takes a file path and generates the documentation // for the `//autometrics:inst` functions. // @@ -53,7 +70,7 @@ func TransformFile(ctx internal.GeneratorContext, path, moduleName string) error sourceCode := string(sourceBytes) transformedSource, err := GenerateDocumentationAndInstrumentation(ctx, sourceCode, moduleName) if err != nil { - return fmt.Errorf("error generating documentation: %w", err) + return fmt.Errorf("errors generating instrumentation and documentation: %w", err) } err = os.WriteFile(path, []byte(transformedSource), permissions) @@ -74,7 +91,7 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour return "", fmt.Errorf("error parsing source code: %w", err) } - var inspectErr error + var inspectErr GenerateErrors var foundAmImport bool for _, importSpec := range fileTree.Imports { @@ -97,11 +114,10 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour fileWalk := func(node dst.Node) bool { if funcDeclaration, ok := node.(*dst.FuncDecl); ok { - inspectErr = walkFuncDeclaration(&ctx, funcDeclaration, moduleName) - } - - if inspectErr != nil { - return false + individualError := walkFuncDeclaration(&ctx, funcDeclaration, moduleName) + if individualError != nil { + inspectErr = append(inspectErr, *individualError) + } } return true @@ -110,7 +126,7 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour dst.Inspect(fileTree, fileWalk) if inspectErr != nil { - return "", fmt.Errorf("error while transforming file in %v: %w", moduleName, inspectErr) + return "", fmt.Errorf("errors while transforming file in %v: %w", moduleName, inspectErr) } var buf strings.Builder @@ -124,14 +140,23 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour } // walkFuncDeclaration uses the context to generate documentation and code if necessary for a function declaration in a file. -func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl, moduleName string) error { +func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl, moduleName string) *GenerateError { if !ctx.RemoveEverything && ctx.FuncCtx.ImplImportName == "" { if ctx.Implementation == autometrics.PROMETHEUS { - return fmt.Errorf("the source file is missing a %v import", AmPromPackage) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("the source file is missing a %v import", AmPromPackage), + } } else if ctx.Implementation == autometrics.OTEL { - return fmt.Errorf("the source file is missing a %v import", AmOtelPackage) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("the source file is missing a %v import", AmOtelPackage), + } } else { - return fmt.Errorf("unknown implementation of metrics has been queried") + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("unknown implementation of metrics has been queried"), + } } } @@ -144,22 +169,31 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu // Clean up old autometrics comments docComments, err := cleanUpAutometricsComments(*ctx, funcDeclaration) if err != nil { - return fmt.Errorf("error trying to remove autometrics comment from former pass: %w", err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("error trying to remove autometrics comment from former pass: %w", err), + } } err = removeDeferStatement(ctx, funcDeclaration) if err != nil { - return fmt.Errorf( - "error removing an older autometrics defer statement in %v: %w", - funcDeclaration.Name.Name, - err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf( + "error removing an older autometrics defer statement in %v: %w", + funcDeclaration.Name.Name, + err), + } } err = removeContextStatement(ctx, funcDeclaration) if err != nil { - return fmt.Errorf( - "error removing an older autometrics context statement in %v: %w", - funcDeclaration.Name.Name, - err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf( + "error removing an older autometrics context statement in %v: %w", + funcDeclaration.Name.Name, + err), + } } // Early exit if we wanted to remove everything @@ -171,10 +205,13 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu // Detect autometrics directive err = parseAutometricsFnContext(ctx, docComments) if err != nil { - return fmt.Errorf( - "failed to parse //autometrics directive for %v: %w", - funcDeclaration.Name.Name, - err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf( + "failed to parse //autometrics directive for %v: %w", + funcDeclaration.Name.Name, + err), + } } // This block only runs on functions that still have the autometrics directive @@ -202,13 +239,19 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu // context statement _, err := injectContextStatement(ctx, funcDeclaration) if err != nil { - return fmt.Errorf("failed to inject context statement: %w", err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("failed to inject context statement: %w", err), + } } // defer statement err = injectDeferStatement(ctx, funcDeclaration) if err != nil { - return fmt.Errorf("failed to inject defer statement: %w", err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("failed to inject defer statement: %w", err), + } } } return nil From 2900728decca3a3e5cdea6adc1466c9b7707878d Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 11:16:22 +0100 Subject: [PATCH 09/14] Better, shorter error messages --- internal/autometrics/ctx.go | 2 +- internal/generate/context.go | 4 ++-- internal/generate/defer.go | 6 +++--- internal/generate/generate.go | 30 ++++++++++++++-------------- prometheus/autometrics/prometheus.go | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/internal/autometrics/ctx.go b/internal/autometrics/ctx.go index d157c82..77db792 100644 --- a/internal/autometrics/ctx.go +++ b/internal/autometrics/ctx.go @@ -164,7 +164,7 @@ func NewGeneratorContext(implementation autometrics.Implementation, prometheusUr if prometheusUrl != "" { promUrl, err := url.Parse(prometheusUrl) if err != nil { - return ctx, fmt.Errorf("failed to parse prometheus URL: %w", err) + return ctx, fmt.Errorf("parsing prometheus URL: %w", err) } ctx.DocumentationGenerator = NewPrometheusDoc(*promUrl) diff --git a/internal/generate/context.go b/internal/generate/context.go index c3b9dd0..9eff01d 100644 --- a/internal/generate/context.go +++ b/internal/generate/context.go @@ -30,12 +30,12 @@ const ( func injectContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) (identName string, err error) { err = detectContext(ctx, funcDeclaration) if err != nil { - return "", fmt.Errorf("failed to get context for tracing: %w", err) + return "", fmt.Errorf("getting context for tracing: %w", err) } autometricsContextStatement, err := buildAutometricsContextStatement(ctx) if err != nil { - return "", fmt.Errorf("failed to build the defer statement for instrumentation: %w", err) + return "", fmt.Errorf("building the defer statement for instrumentation: %w", err) } funcDeclaration.Body.List = append([]dst.Stmt{&autometricsContextStatement}, funcDeclaration.Body.List...) diff --git a/internal/generate/defer.go b/internal/generate/defer.go index 0be3302..7f71d17 100644 --- a/internal/generate/defer.go +++ b/internal/generate/defer.go @@ -21,12 +21,12 @@ const ( func injectDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { contextAssignmentIndex, found := findContextStatement(ctx, funcDeclaration) if !found { - return fmt.Errorf("failed to get context: the %v statement is missing", contextDecoration) + return fmt.Errorf("getting context: the %v statement is missing", contextDecoration) } variable, err := errorReturnValueName(funcDeclaration) if err != nil { - return fmt.Errorf("failed to get error return value name: %w", err) + return fmt.Errorf("getting error return value name: %w", err) } if len(variable) == 0 { @@ -37,7 +37,7 @@ func injectDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.F autometricsDeferStatement, err := buildAutometricsDeferStatement(ctx, variable) if err != nil { - return fmt.Errorf("failed to build the defer statement for instrumentation: %w", err) + return fmt.Errorf("building the defer statement for instrumentation: %w", err) } funcDeclaration.Body.List = insertStatements(funcDeclaration.Body.List, contextAssignmentIndex+1, []dst.Stmt{&autometricsDeferStatement}) diff --git a/internal/generate/generate.go b/internal/generate/generate.go index 7618c5b..4bb8d72 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -88,7 +88,7 @@ func TransformFile(ctx internal.GeneratorContext, path, moduleName string) error func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sourceCode, moduleName string) (string, error) { fileTree, err := decorator.Parse(sourceCode) if err != nil { - return "", fmt.Errorf("error parsing source code: %w", err) + return "", fmt.Errorf("parsing source code: %w", err) } var inspectErr GenerateErrors @@ -104,7 +104,7 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour if !ctx.RemoveEverything && !foundAmImport { err = addAutometricsImport(&ctx, fileTree) if err != nil { - return "", fmt.Errorf("error adding the autometrics import: %w", err) + return "", fmt.Errorf("adding the autometrics import: %w", err) } } @@ -126,14 +126,14 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour dst.Inspect(fileTree, fileWalk) if inspectErr != nil { - return "", fmt.Errorf("errors while transforming file in %v: %w", moduleName, inspectErr) + return "", fmt.Errorf("transforming file in %v: %w", moduleName, inspectErr) } var buf strings.Builder err = decorator.Fprint(&buf, fileTree) if err != nil { - return "", fmt.Errorf("error writing the AST to buffer: %w", err) + return "", fmt.Errorf("writing the AST to buffer: %w", err) } return buf.String(), nil @@ -171,7 +171,7 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu if err != nil { return &GenerateError{ FunctionName: funcDeclaration.Name.Name, - Detail: fmt.Errorf("error trying to remove autometrics comment from former pass: %w", err), + Detail: fmt.Errorf("removing autometrics comment from former pass: %w", err), } } @@ -180,7 +180,7 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu return &GenerateError{ FunctionName: funcDeclaration.Name.Name, Detail: fmt.Errorf( - "error removing an older autometrics defer statement in %v: %w", + "removing an older autometrics defer statement in %v: %w", funcDeclaration.Name.Name, err), } @@ -190,7 +190,7 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu return &GenerateError{ FunctionName: funcDeclaration.Name.Name, Detail: fmt.Errorf( - "error removing an older autometrics context statement in %v: %w", + "removing an older autometrics context statement in %v: %w", funcDeclaration.Name.Name, err), } @@ -208,7 +208,7 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu return &GenerateError{ FunctionName: funcDeclaration.Name.Name, Detail: fmt.Errorf( - "failed to parse //autometrics directive for %v: %w", + "parsing //autometrics directive for %v: %w", funcDeclaration.Name.Name, err), } @@ -241,7 +241,7 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu if err != nil { return &GenerateError{ FunctionName: funcDeclaration.Name.Name, - Detail: fmt.Errorf("failed to inject context statement: %w", err), + Detail: fmt.Errorf("injecting context statement: %w", err), } } @@ -250,7 +250,7 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu if err != nil { return &GenerateError{ FunctionName: funcDeclaration.Name.Name, - Detail: fmt.Errorf("failed to inject defer statement: %w", err), + Detail: fmt.Errorf("injecting defer statement: %w", err), } } } @@ -269,7 +269,7 @@ func parseAutometricsFnContext(ctx *internal.GeneratorContext, commentGroup []st tokens, err := shlex.Split(args) if err != nil { - return fmt.Errorf("could not parse the directive arguments: %w", err) + return fmt.Errorf("parsing the directive arguments: %w", err) } tokenIndex := 0 for tokenIndex < len(tokens) { @@ -278,22 +278,22 @@ func parseAutometricsFnContext(ctx *internal.GeneratorContext, commentGroup []st case token == SloNameArgument: tokenIndex, err = parseSloName(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", SloNameArgument, err) + return fmt.Errorf("parsing %v argument: %w", SloNameArgument, err) } case token == SuccessObjArgument: tokenIndex, err = parseSuccessObjective(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", SuccessObjArgument, err) + return fmt.Errorf("parsing %v argument: %w", SuccessObjArgument, err) } case token == LatencyMsArgument: tokenIndex, err = parseLatencyMs(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", LatencyMsArgument, err) + return fmt.Errorf("parsing %v argument: %w", LatencyMsArgument, err) } case token == LatencyObjArgument: tokenIndex, err = parseLatencyObjective(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", LatencyObjArgument, err) + return fmt.Errorf("parsing %v argument: %w", LatencyObjArgument, err) } case token == NoDocArgument: ctx.FuncCtx.DisableDocGeneration = true diff --git a/prometheus/autometrics/prometheus.go b/prometheus/autometrics/prometheus.go index 27442e0..d77a04d 100644 --- a/prometheus/autometrics/prometheus.go +++ b/prometheus/autometrics/prometheus.go @@ -246,7 +246,7 @@ func ForceFlush() error { Collector(functionCallsConcurrent) if err := localPusher. AddContext(ctx); err != nil { - return fmt.Errorf("failed to push metrics to gateway: %w", err) + return fmt.Errorf("pushing metrics to gateway: %w", err) } } } From 92f8dd86362dc6115c1d85de25c9eaffec96532b Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 11:17:33 +0100 Subject: [PATCH 10/14] Accept more function signatures in instrument Instead of erroring out when some arguments cannot be inspected for context inspection, we log the information. --- internal/generate/context.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/generate/context.go b/internal/generate/context.go index 9eff01d..e21ede4 100644 --- a/internal/generate/context.go +++ b/internal/generate/context.go @@ -351,10 +351,20 @@ func detectContext(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl return err } } else { - return fmt.Errorf("expecting the type being pointed to to be an identifier, got %s instead", reflect.TypeOf(argType.X).String()) + log.Printf("the type being pointed to by argument %s in %s is %s, skipping...", + argName, + funcDeclaration.Name.Name, + reflect.TypeOf(argType.X).String(), + ) + continue } } else { - return fmt.Errorf("expecting the type of argGroup to be an identifier, got %s instead", reflect.TypeOf(argGroup.Type).String()) + log.Printf("the type of argument %s in %s is %s, skipping...", + argName, + funcDeclaration.Name.Name, + reflect.TypeOf(argGroup.Type).String(), + ) + continue } } From aa3aeec1004ab1653a431fb0b412f01cf0e6a12d Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 11:20:53 +0100 Subject: [PATCH 11/14] Update changelog --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aebcd76..2692501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,8 +32,8 @@ specification. + `http.Request` + `buffalo.Request` - [Generator] The generator now tries to keep going with instrumentation even if some instrumentation - fails. All files will stay modified, and the generator will exit with an error code and output - all the collected errors. + fails. On error, still _No file will be modified_, and the generator will exit with an error code + and output all the collected errors instead of only the first one. ### Deprecated @@ -41,6 +41,8 @@ specification. ### Fixed +- [Generator] Fix a few generator crashes when instrumented functions have specific argument types. + ### Security - Update all dependencies to reduce dependabot alerts in From 2204339dbf6515812c7bd0a7398f057f15450e8d Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 11:44:35 +0100 Subject: [PATCH 12/14] Add more build information in binaries This will fix the builds that are downloaded, but not the ones from go install --- .github/workflows/release.yml | 1 + cmd/autometrics/main.go | 6 +++++- internal/build/build.go | 6 ++++++ scripts/build_generator | 6 +++++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2172de9..4b43b3d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,7 @@ jobs: with: # We need all tags fetch-depth: 0 + fetch-tags: true - name: Set up Go uses: actions/setup-go@v4 with: diff --git a/cmd/autometrics/main.go b/cmd/autometrics/main.go index 181aa40..6020879 100644 --- a/cmd/autometrics/main.go +++ b/cmd/autometrics/main.go @@ -31,7 +31,11 @@ type args struct { func (args) Version() string { var buf strings.Builder - fmt.Fprintf(&buf, "Autometrics %s", build.Version) + fmt.Fprintf(&buf, "Autometrics %s (built by %s on %s)", + build.Version, + build.User, + build.Time, + ) return buf.String() } diff --git a/internal/build/build.go b/internal/build/build.go index 3600686..6170b83 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -2,3 +2,9 @@ package build // import "github.com/autometrics-dev/autometrics-go/internal/buil // Version is the version string of the build, when made available through ldflags. var Version = "development" + +// User is the user who triggered this build, when made available through ldflags. +var User = "n/a" + +// Time is the timestamp string of the build, when made available through ldflags. +var Time = "n/a" diff --git a/scripts/build_generator b/scripts/build_generator index 8dd5121..652c777 100755 --- a/scripts/build_generator +++ b/scripts/build_generator @@ -4,6 +4,10 @@ set -euo pipefail BUILD_PACK="github.com/autometrics-dev/autometrics-go/internal/build" VERSION=`git describe --tags` +USER=`id -u -n` +DATE=`date -u` SCRIPT_DIR="$( dirname -- "$( readlink -f -- "$0"; )"; )" -go build -v -ldflags="-X '${BUILD_PACK}.Version=${VERSION}'" ${SCRIPT_DIR}/../cmd/autometrics/main.go +echo "Building version ${VERSION} (${USER} @ ${DATE})" + +go build -v -a -ldflags="-X '${BUILD_PACK}.Version=${VERSION}' -X '${BUILD_PACK}.User=${USER}' -X '${BUILD_PACK}.Time=${DATE}'" ${SCRIPT_DIR}/../cmd/autometrics/main.go From 71c2fd0110d0df07e3af7acdbb439b0fa3c88f35 Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 6 Nov 2023 12:03:23 +0100 Subject: [PATCH 13/14] Fix context replacement for http.Request The context of a HTTP request is not assignable, so we need to read from the existing context and create a new one --- CHANGELOG.md | 9 +++++---- examples/otel/cmd/main.go | 8 ++++---- examples/web/cmd/main.go | 4 ++-- internal/autometrics/ctx.go | 12 ++++++++---- internal/generate/context.go | 10 ++++++++-- internal/generate/defer_test.go | 12 ++++++------ 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2692501..d5fe324 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,10 +27,11 @@ specification. tracking. If `autometrics` detects a `context.Context` it can use, it will shadow the context with the autometrics augmented one to reduce the changes to make in the code. Currently, `autometrics` can detect arguments of specific types in the function signatures - to replace contexts: - + `context.Context` - + `http.Request` - + `buffalo.Request` + to read from and replace contexts: + + `context.Context` (read and replace) + + `http.Request` (read only) + + `buffalo.Request` (read and replace) + + `gin.Context` (read only; _very_ experimental) - [Generator] The generator now tries to keep going with instrumentation even if some instrumentation fails. On error, still _No file will be modified_, and the generator will exit with an error code and output all the collected errors instead of only the first one. diff --git a/examples/otel/cmd/main.go b/examples/otel/cmd/main.go index d15c939..60a63ed 100644 --- a/examples/otel/cmd/main.go +++ b/examples/otel/cmd/main.go @@ -98,14 +98,14 @@ func main() { // //autometrics:doc --slo "API" --latency-target 99 --latency-ms 5 func indexHandler(w http.ResponseWriter, r *http.Request) error { - r.Context() = autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(5000000*time.Nanosecond, 99), )) //autometrics:shadow-ctx - defer autometrics.Instrument(r.Context(), nil) //autometrics:defer + defer autometrics.Instrument(amCtx, nil) //autometrics:defer msSleep := rand.Intn(200) time.Sleep(time.Duration(msSleep) * time.Millisecond) @@ -149,14 +149,14 @@ var handlerError = errors.New("failed to handle request") // //autometrics:doc --slo "API" --success-target 90 func randomErrorHandler(w http.ResponseWriter, r *http.Request) (err error) { - r.Context() = autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertSuccess(90), )) //autometrics:shadow-ctx - defer autometrics.Instrument(r.Context(), &err) //autometrics:defer + defer autometrics.Instrument(amCtx, &err) //autometrics:defer isOk := rand.Intn(10) == 0 diff --git a/examples/web/cmd/main.go b/examples/web/cmd/main.go index 8a3868b..99e0485 100644 --- a/examples/web/cmd/main.go +++ b/examples/web/cmd/main.go @@ -107,14 +107,14 @@ func main() { // //autometrics:inst --slo "API" --latency-target 99 --latency-ms 5 func indexHandler(w http.ResponseWriter, r *http.Request) error { - r.Context() = autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(5000000*time.Nanosecond, 99), )) //autometrics:shadow-ctx - defer autometrics.Instrument(r.Context(), nil) //autometrics:defer + defer autometrics.Instrument(amCtx, nil) //autometrics:defer msSleep := rand.Intn(200) time.Sleep(time.Duration(msSleep) * time.Millisecond) diff --git a/internal/autometrics/ctx.go b/internal/autometrics/ctx.go index 77db792..1b50b88 100644 --- a/internal/autometrics/ctx.go +++ b/internal/autometrics/ctx.go @@ -47,8 +47,11 @@ type GeneratorContext struct { // only statically-known information is useful at this point. type RuntimeCtxInfo struct { // Name of the variable to use as context.Context when building the autometrics.Context. - // The string will be empty if and only if 'nil' must be used as autometrics.NewContext() argument. + // The string will be empty if 'nil' must be used as autometrics.NewContext() argument. ContextVariableName string + // Name of the variable to assign to the context returned by autometrics.PreInstrument + // The string will be empty if a new variable must be used as autometrics.PreInstrument() return value assignment. + NewContextVariableName string // Verbatim code to use to fetch the TraceID. // For example, if the instrumented function is detected to use Gin, like // `func ginHandler(ginVarName *gin.Context)` @@ -65,9 +68,10 @@ type RuntimeCtxInfo struct { func DefaultRuntimeCtxInfo() RuntimeCtxInfo { return RuntimeCtxInfo{ - TrackConcurrentCalls: true, - TrackCallerName: true, - ContextVariableName: "nil", + TrackConcurrentCalls: true, + TrackCallerName: true, + ContextVariableName: "nil", + NewContextVariableName: "", } } diff --git a/internal/generate/context.go b/internal/generate/context.go index e21ede4..1d220be 100644 --- a/internal/generate/context.go +++ b/internal/generate/context.go @@ -148,8 +148,8 @@ func buildAutometricsContextNode(agc *internal.GeneratorContext) (newContextCall } } - contextShadowName = agc.RuntimeCtx.ContextVariableName - if contextShadowName == "nil" { + contextShadowName = agc.RuntimeCtx.NewContextVariableName + if contextShadowName == "nil" || contextShadowName == "" { contextShadowName = amDefaultContextName } @@ -224,6 +224,7 @@ func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, iden if canonical == vanillaContext && typeName == "Context" { ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName ctx.RuntimeCtx.SpanIDGetter = "" ctx.RuntimeCtx.TraceIDGetter = "" return true, nil @@ -236,6 +237,7 @@ func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, iden } else { ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) } + ctx.RuntimeCtx.NewContextVariableName = "" ctx.RuntimeCtx.SpanIDGetter = "" ctx.RuntimeCtx.TraceIDGetter = "" return true, nil @@ -250,6 +252,7 @@ func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, iden // Buffalo context embeds a context.Context so it can work like vanilla if canonical == buffalo && typeName == "Context" { ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName ctx.RuntimeCtx.SpanIDGetter = "" ctx.RuntimeCtx.TraceIDGetter = "" return true, nil @@ -275,6 +278,7 @@ func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, s for alias, canonical := range ctx.ImportsMap { if canonical == vanillaContext && parentName == alias && typeName == "Context" { ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName ctx.RuntimeCtx.SpanIDGetter = "" ctx.RuntimeCtx.TraceIDGetter = "" return true, nil @@ -288,6 +292,7 @@ func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, s } else { ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) } + ctx.RuntimeCtx.NewContextVariableName = "" ctx.RuntimeCtx.SpanIDGetter = "" ctx.RuntimeCtx.TraceIDGetter = "" return true, nil @@ -302,6 +307,7 @@ func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, s // Buffalo context embeds a context.Context so it can work like vanilla if canonical == buffalo && parentName == alias && typeName == "Context" { ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName ctx.RuntimeCtx.SpanIDGetter = "" ctx.RuntimeCtx.TraceIDGetter = "" return true, nil diff --git a/internal/generate/defer_test.go b/internal/generate/defer_test.go index 6f7d1fa..ff787ec 100644 --- a/internal/generate/defer_test.go +++ b/internal/generate/defer_test.go @@ -216,14 +216,14 @@ func main(w http.ResponseWriter, req *http.Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w http.ResponseWriter, req *http.Request) {\n" + - "\treq.Context() = prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + "\t)) //autometrics:shadow-ctx\n" + - "\tdefer prom.Instrument(req.Context(), nil) //autometrics:defer\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -274,14 +274,14 @@ func main(w vanilla.ResponseWriter, req *vanilla.Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w vanilla.ResponseWriter, req *vanilla.Request) {\n" + - "\treq.Context() = prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + "\t)) //autometrics:shadow-ctx\n" + - "\tdefer prom.Instrument(req.Context(), nil) //autometrics:defer\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -332,14 +332,14 @@ func main(w ResponseWriter, req *Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w ResponseWriter, req *Request) {\n" + - "\treq.Context() = prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + "\t)) //autometrics:shadow-ctx\n" + - "\tdefer prom.Instrument(req.Context(), nil) //autometrics:defer\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" From 2808891450b543e1c267ad64564d5684f5cdf6da Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Mon, 13 Nov 2023 12:31:19 +0100 Subject: [PATCH 14/14] Add autometrics.version to build_info metric --- otel/autometrics/otel.go | 9 +++++++++ prometheus/autometrics/prometheus.go | 11 ++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/otel/autometrics/otel.go b/otel/autometrics/otel.go index 3d1a231..dea2f4d 100644 --- a/otel/autometrics/otel.go +++ b/otel/autometrics/otel.go @@ -35,6 +35,10 @@ var ( ) const ( + // AutometricsSpecVersion is the version of the specification the library follows + // The specifications can be found in https://github.com/autometrics-dev/autometrics-shared/tree/main/specs + AutometricsSpecVersion = "1.0.0" + // FunctionCallsCountName is the name of the openTelemetry metric for the counter of calls to specific functions. FunctionCallsCountName = "function.calls" // FunctionCallsDurationName is the name of the openTelemetry metric for the duration histogram of calls to specific functions. @@ -91,6 +95,10 @@ const ( // service repository url RepositoryProviderLabel = "repository.provider" + // AutometricsVersionLabel is the openTelemetry attribute that describes the version of the Autometrics specification + // the library follows + AutometricsVersionLabel = "autometrics.version" + // ServiceNameLabel is the openTelemetry attribute that describes the name of the Service being monitored. ServiceNameLabel = "service.name" @@ -244,6 +252,7 @@ func Init(meterName string, histogramBuckets []float64, buildInformation BuildIn attribute.Key(RepositoryProviderLabel).String(autometrics.GetRepositoryProvider()), attribute.Key(RepositoryURLLabel).String(autometrics.GetRepositoryURL()), attribute.Key(JobNameLabel).String(autometrics.GetPushJobName()), + attribute.Key(AutometricsVersionLabel).String(AutometricsSpecVersion), }...)) return cancelFunc, nil diff --git a/prometheus/autometrics/prometheus.go b/prometheus/autometrics/prometheus.go index d77a04d..73414d6 100644 --- a/prometheus/autometrics/prometheus.go +++ b/prometheus/autometrics/prometheus.go @@ -27,6 +27,10 @@ var ( ) const ( + // AutometricsSpecVersion is the version of the specification the library follows + // The specifications can be found in https://github.com/autometrics-dev/autometrics-shared/tree/main/specs + AutometricsSpecVersion = "1.0.0" + // FunctionCallsCountName is the name of the prometheus metric for the counter of calls to specific functions. FunctionCallsCountName = "function_calls_total" // FunctionCallsDurationName is the name of the prometheus metric for the duration histogram of calls to specific functions. @@ -83,6 +87,10 @@ const ( // service repository url RepositoryProviderLabel = "repository_provider" + // AutometricsVersionLabel is the prometheus label that describes the version of the Autometrics specification + // the library follows + AutometricsVersionLabel = "autometrics_version" + // ServiceNameLabel is the prometheus label that describes the name of the service being monitored ServiceNameLabel = "service_name" @@ -186,7 +194,7 @@ func Init(reg *prometheus.Registry, histogramBuckets []float64, buildInformation buildInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: BuildInfoName, - }, []string{CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, RepositoryURLLabel, RepositoryProviderLabel}) + }, []string{CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, RepositoryURLLabel, RepositoryProviderLabel, AutometricsVersionLabel}) if reg != nil { reg.MustRegister(functionCallsCount) @@ -207,6 +215,7 @@ func Init(reg *prometheus.Registry, histogramBuckets []float64, buildInformation ServiceNameLabel: autometrics.GetService(), RepositoryURLLabel: autometrics.GetRepositoryURL(), RepositoryProviderLabel: autometrics.GetRepositoryProvider(), + AutometricsVersionLabel: AutometricsSpecVersion, }).Set(1) if pusher != nil {