diff --git a/configuration/update.go b/configuration/update.go index 2d3ffae..3dfa4af 100644 --- a/configuration/update.go +++ b/configuration/update.go @@ -409,13 +409,13 @@ func findNativeQueryVariables(nq metadata.NativeQuery) (map[string]metadata.Nati if match[0] > 0 && nq.Query[match[0]-1] == '[' { // duration variables should be bounded by square brackets - if match[1] >= queryLength-1 || nq.Query[match[1]] != ']' { + if match[1] >= queryLength || nq.Query[match[1]] != ']' { return nil, fmt.Errorf("invalid promQL range syntax") } argumentInfo.Type = string(metadata.ScalarDuration) } else if match[0] > 0 && nq.Query[match[0]-1] == '"' { // duration variables should be bounded by double quotes - if match[1] >= queryLength-1 || nq.Query[match[1]] != '"' { + if match[1] >= queryLength || nq.Query[match[1]] != '"' { return nil, fmt.Errorf("invalid promQL string syntax") } argumentInfo.Type = string(metadata.ScalarString) diff --git a/connector/client/utils.go b/connector/client/utils.go index c2ca699..9075d62 100644 --- a/connector/client/utils.go +++ b/connector/client/utils.go @@ -17,15 +17,21 @@ import ( type UnixTimeUnit string const ( - UnixTimeSecond UnixTimeUnit = "s" - UnixTimeMillisecond UnixTimeUnit = "ms" + UnixTimeSecond UnixTimeUnit = "s" + UnixTimeMilli UnixTimeUnit = "ms" + UnixTimeMicro UnixTimeUnit = "us" + UnixTimeNano UnixTimeUnit = "ns" ) // Duration returns the duration of the unit func (ut UnixTimeUnit) Duration() time.Duration { switch ut { - case UnixTimeMillisecond: + case UnixTimeMilli: return time.Millisecond + case UnixTimeMicro: + return time.Microsecond + case UnixTimeNano: + return time.Nanosecond default: return time.Second } @@ -44,40 +50,6 @@ func evalStepFromRange(start time.Time, end time.Time) time.Duration { } } -// ParseDuration parses duration from an unknown value -func ParseDuration(value any, unixTimeUnit UnixTimeUnit) (time.Duration, error) { - reflectValue, ok := utils.UnwrapPointerFromReflectValue(reflect.ValueOf(value)) - if !ok { - return 0, nil - } - - return parseDurationReflection(reflectValue, reflectValue.Kind(), unixTimeUnit) -} - -// parseDurationReflection parses duration from a reflection value -func parseDurationReflection(reflectValue reflect.Value, kind reflect.Kind, unixTimeUnit UnixTimeUnit) (time.Duration, error) { - switch kind { - case reflect.Invalid: - return 0, nil - case reflect.String: - strValue := reflectValue.String() - if d, err := model.ParseDuration(strValue); err == nil { - return time.Duration(d), nil - } else { - return 0, fmt.Errorf("unable to parse duration from string %s: %s", strValue, err) - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // or as a number in seconds - return time.Duration(reflectValue.Int()) * unixTimeUnit.Duration(), nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return time.Duration(reflectValue.Uint()) * unixTimeUnit.Duration(), nil - case reflect.Float32, reflect.Float64: - return time.Duration(int64(reflectValue.Float() * float64(unixTimeUnit.Duration()))), nil - default: - return 0, fmt.Errorf("unable to parse duration from kind %v", kind) - } -} - // RangeResolution represents the given range and resolution with format xx:xx type RangeResolution struct { Range model.Duration @@ -92,6 +64,18 @@ func (rr RangeResolution) String() string { return fmt.Sprintf("%s:%s", rr.Range.String(), rr.Resolution.String()) } +// ParseDuration parses duration from an unknown value +func ParseDuration(value any, unixTimeUnit UnixTimeUnit) (time.Duration, error) { + result, err := utils.DecodeNullableDuration(value, utils.WithBaseUnix(unixTimeUnit.Duration())) + if err != nil { + return 0, err + } + if result == nil { + return 0, nil + } + return *result, nil +} + // ParseRangeResolution parses the range resolution from a string func ParseRangeResolution(input any, unixTimeUnit UnixTimeUnit) (*RangeResolution, error) { reflectValue, ok := utils.UnwrapPointerFromReflectValue(reflect.ValueOf(input)) @@ -101,7 +85,7 @@ func ParseRangeResolution(input any, unixTimeUnit UnixTimeUnit) (*RangeResolutio kind := reflectValue.Kind() if kind != reflect.String { - rng, err := parseDurationReflection(reflectValue, kind, unixTimeUnit) + rng, err := utils.DecodeDuration(reflectValue.Interface(), utils.WithBaseUnix(unixTimeUnit.Duration())) if err != nil { return nil, fmt.Errorf("invalid range resolution %v: %s", input, err) } @@ -133,48 +117,7 @@ func ParseRangeResolution(input any, unixTimeUnit UnixTimeUnit) (*RangeResolutio // ParseTimestamp parses timestamp from an unknown value func ParseTimestamp(s any, unixTimeUnit UnixTimeUnit) (*time.Time, error) { - reflectValue, ok := utils.UnwrapPointerFromReflectValue(reflect.ValueOf(s)) - if !ok { - return nil, nil - } - - baseMs := int64(unixTimeUnit.Duration() / time.Millisecond) - kind := reflectValue.Kind() - switch kind { - case reflect.Invalid: - return nil, nil - case reflect.String: - strValue := reflectValue.String() - if strValue == "now" { - now := time.Now() - return &now, nil - } - // Input timestamps may be provided either in RFC3339 format - for _, format := range []string{time.RFC3339, "2006-01-02T15:04:05Z0700", "2006-01-02T15:04:05-0700", time.RFC3339Nano, time.DateOnly} { - if t, err := time.Parse(format, strValue); err == nil { - return &t, nil - } - } - if d, err := time.ParseDuration(strValue); err == nil { - result := time.Now().Add(-d) - return &result, nil - } else { - return nil, fmt.Errorf("unable to parse timestamp from string %s: %s", strValue, err) - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // or as a Unix timestamp, - // with optional decimal places for sub-second precision - result := time.UnixMilli(reflectValue.Int() * baseMs) - return &result, nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - result := time.UnixMilli(int64(reflectValue.Uint()) * baseMs) - return &result, nil - case reflect.Float32, reflect.Float64: - result := time.UnixMilli(int64(reflectValue.Float() * float64(baseMs))) - return &result, nil - default: - return nil, fmt.Errorf("unable to parse timestamp from kind %v", kind) - } + return utils.DecodeNullableDateTime(s, utils.WithBaseUnix(unixTimeUnit.Duration())) } type apiResponse struct { diff --git a/connector/internal/collection_request.go b/connector/internal/collection_request.go index 2a05b52..64d7589 100644 --- a/connector/internal/collection_request.go +++ b/connector/internal/collection_request.go @@ -95,14 +95,14 @@ func (pr *CollectionRequest) evalQueryPredicate(expression schema.Expression) er return errors.New("unsupported multiple equality for the timestamp") } pr.Timestamp = expr.Value - case metadata.Least: + case metadata.Least, metadata.LeastOrEqual: if pr.End != nil { - return errors.New("unsupported multiple _lt expressions for the timestamp") + return errors.New("unsupported multiple _lt or _lte expressions for the timestamp") } pr.End = expr.Value - case metadata.Greater: + case metadata.Greater, metadata.GreaterOrEqual: if pr.Start != nil { - return errors.New("unsupported multiple _gt expressions for the timestamp") + return errors.New("unsupported multiple _gt or _gt expressions for the timestamp") } pr.Start = expr.Value default: diff --git a/connector/internal/native_query.go b/connector/internal/native_query.go index ca08414..7db50db 100644 --- a/connector/internal/native_query.go +++ b/connector/internal/native_query.go @@ -78,7 +78,7 @@ func (nqe *NativeQueryExecutor) Explain(ctx context.Context) (*NativeQueryReques } if unresolvedArguments := metadata.FindNativeQueryVariableNames(queryString); len(unresolvedArguments) > 0 { - return nil, "", schema.BadRequestError(fmt.Sprintf("unresolved variables %v in the Prometheus query", unresolvedArguments), map[string]any{ + return nil, "", schema.UnprocessableContentError(fmt.Sprintf("unresolved variables %v in the query", unresolvedArguments), map[string]any{ "collection": nqe.Request.Collection, "query": queryString, }) diff --git a/connector/internal/utils.go b/connector/internal/utils.go index 1a95a3b..8a34086 100644 --- a/connector/internal/utils.go +++ b/connector/internal/utils.go @@ -5,9 +5,9 @@ import ( "fmt" "math" "slices" + "strconv" "time" - "github.com/hasura/ndc-prometheus/connector/client" "github.com/hasura/ndc-prometheus/connector/metadata" "github.com/hasura/ndc-sdk-go/schema" "github.com/hasura/ndc-sdk-go/utils" @@ -17,7 +17,7 @@ import ( func createQueryResultsFromVector(vector model.Vector, labels map[string]metadata.LabelInfo, runtime *metadata.RuntimeSettings, flat bool) []map[string]any { results := make([]map[string]any, len(vector)) for i, item := range vector { - ts := formatTimestamp(item.Timestamp, runtime.Format.Timestamp, runtime.UnixTimeUnit) + ts := formatTimestamp(item.Timestamp, runtime.Format.Timestamp) value := formatValue(item.Value, runtime.Format) r := map[string]any{ metadata.TimestampKey: ts, @@ -65,7 +65,7 @@ func createGroupQueryResultsFromMatrix(matrix model.Matrix, labels map[string]me valuesLen := len(item.Values) values := make([]map[string]any, valuesLen) for i, value := range item.Values { - ts := formatTimestamp(value.Timestamp, runtime.Format.Timestamp, runtime.UnixTimeUnit) + ts := formatTimestamp(value.Timestamp, runtime.Format.Timestamp) v := formatValue(value.Value, runtime.Format) values[i] = map[string]any{ metadata.TimestampKey: ts, @@ -89,7 +89,7 @@ func createFlatQueryResultsFromMatrix(matrix model.Matrix, labels map[string]met for _, item := range matrix { for _, value := range item.Values { - ts := formatTimestamp(value.Timestamp, runtime.Format.Timestamp, runtime.UnixTimeUnit) + ts := formatTimestamp(value.Timestamp, runtime.Format.Timestamp) v := formatValue(value.Value, runtime.Format) r := map[string]any{ metadata.LabelsKey: item.Metric, @@ -109,12 +109,18 @@ func createFlatQueryResultsFromMatrix(matrix model.Matrix, labels map[string]met return results } -func formatTimestamp(ts model.Time, format metadata.TimestampFormat, unixTime client.UnixTimeUnit) any { +func formatTimestamp(ts model.Time, format metadata.TimestampFormat) any { switch format { - case metadata.TimestampRFC3339: - return ts.Time().Format(time.RFC3339) + case metadata.TimestampUnix: + return ts.Unix() + case metadata.TimestampUnixMilli: + return ts.Time().UnixMilli() + case metadata.TimestampUnixMicro: + return ts.Time().UnixMicro() + case metadata.TimestampUnixNano: + return strconv.FormatInt(ts.UnixNano(), 10) default: - return ts.Unix() * int64(time.Second/unixTime.Duration()) + return ts.Time().Format(time.RFC3339) } } diff --git a/connector/metadata/configuration.go b/connector/metadata/configuration.go index 19f2436..91261a2 100644 --- a/connector/metadata/configuration.go +++ b/connector/metadata/configuration.go @@ -62,8 +62,16 @@ type GeneratorSettings struct { type TimestampFormat string const ( + // Represents the timestamp as a Unix timestamp in RFC3339 string. TimestampRFC3339 TimestampFormat = "rfc3339" - TimestampUnix TimestampFormat = "unix" + // Represents the timestamp as a Unix timestamp in seconds. + TimestampUnix TimestampFormat = "unix" + // Represents the timestamp as a Unix timestamp in milliseconds. + TimestampUnixMilli TimestampFormat = "unix_ms" + // Represents the timestamp as a Unix timestamp in microseconds. + TimestampUnixMicro TimestampFormat = "unix_us" + // Represents the timestamp as a Unix timestamp in nanoseconds. + TimestampUnixNano TimestampFormat = "unix_ns" ) // ValueFormat the format for value serialization @@ -77,7 +85,7 @@ const ( // RuntimeFormatSettings format settings for timestamps and values in runtime type RuntimeFormatSettings struct { // The serialization format for timestamp - Timestamp TimestampFormat `json:"timestamp" yaml:"timestamp" jsonschema:"enum=rfc3339,enum=unix,default=unix"` + Timestamp TimestampFormat `json:"timestamp" yaml:"timestamp" jsonschema:"enum=rfc3339,enum=unix,enum=unix_ms,enum=unix_us,enum=unix_ns,default=unix"` // The serialization format for value Value ValueFormat `json:"value" yaml:"value" jsonschema:"enum=string,enum=float64,default=string"` // The serialization format for not-a-number values @@ -93,7 +101,7 @@ type RuntimeSettings struct { // Flatten value points to the root array Flat bool `json:"flat" yaml:"flat"` // The default unit for unix timestamp - UnixTimeUnit client.UnixTimeUnit `json:"unix_time_unit" yaml:"unix_time_unit" jsonschema:"enum=s,enum=ms,default=s"` + UnixTimeUnit client.UnixTimeUnit `json:"unix_time_unit" yaml:"unix_time_unit" jsonschema:"enum=s,enum=ms,enum=us,enum=ns,default=s"` // The serialization format for response fields Format RuntimeFormatSettings `json:"format" yaml:"format"` // The concurrency limit of queries if there are many variables in a single query diff --git a/connector/metadata/const.go b/connector/metadata/const.go index 4e72187..32aaf1c 100644 --- a/connector/metadata/const.go +++ b/connector/metadata/const.go @@ -74,9 +74,11 @@ var defaultScalars = map[string]schema.ScalarType{ string(ScalarTimestamp): { AggregateFunctions: schema.ScalarTypeAggregateFunctions{}, ComparisonOperators: map[string]schema.ComparisonOperatorDefinition{ - Equal: schema.NewComparisonOperatorEqual().Encode(), - Least: schema.NewComparisonOperatorCustom(schema.NewNamedType(string(ScalarTimestamp))).Encode(), - Greater: schema.NewComparisonOperatorCustom(schema.NewNamedType(string(ScalarTimestamp))).Encode(), + Equal: schema.NewComparisonOperatorEqual().Encode(), + Least: schema.NewComparisonOperatorCustom(schema.NewNamedType(string(ScalarTimestamp))).Encode(), + LeastOrEqual: schema.NewComparisonOperatorCustom(schema.NewNamedType(string(ScalarTimestamp))).Encode(), + Greater: schema.NewComparisonOperatorCustom(schema.NewNamedType(string(ScalarTimestamp))).Encode(), + GreaterOrEqual: schema.NewComparisonOperatorCustom(schema.NewNamedType(string(ScalarTimestamp))).Encode(), }, Representation: schema.NewTypeRepresentationTimestamp().Encode(), }, diff --git a/connector/testdata/query/process_cpu_seconds_total/request.json b/connector/testdata/query/process_cpu_seconds_total/request.json index 5d9bbf1..4c2be59 100644 --- a/connector/testdata/query/process_cpu_seconds_total/request.json +++ b/connector/testdata/query/process_cpu_seconds_total/request.json @@ -17,7 +17,7 @@ "type": "binary_comparison_operator", "column": { "type": "column", "name": "timestamp", "path": [] }, "operator": "_gt", - "value": { "type": "scalar", "value": "2024-09-29T00:00:00Z" } + "value": { "type": "scalar", "value": "2024-10-29T00:00:00Z" } } }, "arguments": { @@ -25,7 +25,7 @@ "type": "literal", "value": [{ "increase": "1m" }, { "sum": ["job"] }, { "avg": ["job"] }] }, - "step": { "type": "literal", "value": "5m" }, + "step": { "type": "literal", "value": "1d" }, "timeout": { "type": "literal", "value": "1m" }, "flat": { "type": "literal", "value": true } }, diff --git a/go.mod b/go.mod index 4d14b52..f275a74 100644 --- a/go.mod +++ b/go.mod @@ -3,25 +3,25 @@ module github.com/hasura/ndc-prometheus go 1.23 require ( - github.com/alecthomas/kong v1.2.1 + github.com/alecthomas/kong v1.4.0 github.com/go-viper/mapstructure/v2 v2.2.1 - github.com/hasura/ndc-sdk-go v1.5.0 + github.com/hasura/ndc-sdk-go v1.6.2-0.20241107100235-ebdf1605df36 github.com/iancoleman/strcase v0.3.0 github.com/invopop/jsonschema v0.12.0 github.com/lmittmann/tint v1.0.5 - github.com/prometheus/client_golang v1.20.4 - github.com/prometheus/common v0.60.0 - go.opentelemetry.io/otel v1.30.0 - go.opentelemetry.io/otel/trace v1.30.0 + github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/common v0.60.1 + go.opentelemetry.io/otel v1.31.0 + go.opentelemetry.io/otel/trace v1.31.0 golang.org/x/sync v0.8.0 - google.golang.org/api v0.199.0 + google.golang.org/api v0.205.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) require ( - cloud.google.com/go/auth v0.9.7 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/auth v0.10.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect cloud.google.com/go/compute/metadata v0.5.2 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -36,10 +36,10 @@ require ( github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.10 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -49,26 +49,26 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.52.0 // indirect - go.opentelemetry.io/otel/metric v1.30.0 // indirect - go.opentelemetry.io/otel/sdk v1.30.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.30.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.53.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.31.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.19.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.67.1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index f251f2e..744bb24 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,14 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.7 h1:ha65jNwOfI48YmUzNfMaUDfqt5ykuYIUnSartpU1+BA= cloud.google.com/go/auth v0.9.7/go.mod h1:Xo0n7n66eHyOWWCnitop6870Ilwo3PiZyodVkkH1xWM= +cloud.google.com/go/auth v0.10.1 h1:TnK46qldSfHWt2a0b/hciaiVJsmDXWy9FqyUan0uYiI= +cloud.google.com/go/auth v0.10.1/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= +cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -10,6 +16,8 @@ github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZ github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/kong v1.2.1 h1:E8jH4Tsgv6wCRX2nGrdPyHDUCSG83WH2qE4XLACD33Q= github.com/alecthomas/kong v1.2.1/go.mod h1:rKTSFhbdp3Ryefn8x5MOEprnRFQ7nlmMC01GKhehhBM= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= @@ -73,8 +81,10 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gT github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= -github.com/hasura/ndc-sdk-go v1.5.0 h1:KvfzbrWBDrs21oz1xA0BvWNhKRqAX0NqLCfPyKz+l/M= -github.com/hasura/ndc-sdk-go v1.5.0/go.mod h1:oik0JrwuN5iZwZjZJzIRMw9uO2xDJbCXwhS1GgaRejk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= +github.com/hasura/ndc-sdk-go v1.6.2-0.20241107100235-ebdf1605df36 h1:H1MBcYou3FRq08BKYQHKVkxeVoYvMQc0BlvG8df4UPk= +github.com/hasura/ndc-sdk-go v1.6.2-0.20241107100235-ebdf1605df36/go.mod h1:H7iN3SFXSou2rjBKv9fLumbvDXMDGP0Eg+cXWHpkA3k= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= @@ -88,6 +98,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -111,11 +123,15 @@ 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.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= @@ -135,30 +151,56 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= go.opentelemetry.io/contrib/propagators/b3 v1.30.0 h1:vumy4r1KMyaoQRltX7cJ37p3nluzALX9nugCjNNefuY= go.opentelemetry.io/contrib/propagators/b3 v1.30.0/go.mod h1:fRbvRsaeVZ82LIl3u0rIvusIel2UUf+JcaaIpy5taho= +go.opentelemetry.io/contrib/propagators/b3 v1.31.0 h1:PQPXYscmwbCp76QDvO4hMngF2j8Bx/OTV86laEl8uqo= +go.opentelemetry.io/contrib/propagators/b3 v1.31.0/go.mod h1:jbqfV8wDdqSDrAYxVpXQnpM0XFMq2FtDesblJ7blOwQ= go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0 h1:WypxHH02KX2poqqbaadmkMYalGyy/vil4HE4PM4nRJc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0/go.mod h1:U79SV99vtvGSEBeeHnpgGJfTsnsdkWLpPN/CcHAzBSI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 h1:FZ6ei8GFW7kyPYdxJaV2rgI6M+4tvZzhYsQ2wgyVC08= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0/go.mod h1:MdEu/mC6j3D+tTEfvI15b5Ci2Fn7NneJ71YMoiS3tpI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 h1:VrMAbeJz4gnVDg2zEzjHG4dEH86j4jO6VYB+NgtGD8s= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0/go.mod h1:qqN/uFdpeitTvm+JDqqnjm517pmQRYxTORbETHq5tOc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.31.0 h1:ZsXq73BERAiNuuFXYqP4MR5hBrjXfMGSO+Cx7qoOZiM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.31.0/go.mod h1:hg1zaDMpyZJuUzjFxFsRYBoccE86tM9Uf4IqNMUxvrY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 h1:umZgi92IyxfXd/l4kaDhnKgY8rnN/cZcF1LKc6I8OQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0/go.mod h1:4lVs6obhSVRb1EW5FhOuBTyiQhtRtAnnva9vD3yRfq8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= go.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ= go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0= +go.opentelemetry.io/otel/exporters/prometheus v0.53.0 h1:QXobPHrwiGLM4ufrY3EOmDPJpo2P90UuFau4CDPJA/I= +go.opentelemetry.io/otel/exporters/prometheus v0.53.0/go.mod h1:WOAXGr3D00CfzmFxtTV1eR0GpoHuPEu+HJT8UWW2SIU= go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM= go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -205,6 +247,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.199.0 h1:aWUXClp+VFJmqE0JPvpZOK3LDQMyFKYIow4etYd9qxs= google.golang.org/api v0.199.0/go.mod h1:ohG4qSztDJmZdjK/Ar6MhbAmb/Rpi4JHOqagsh90K28= +google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg= +google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -212,8 +256,12 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f h1:jTm13A2itBi3La6yTGqn8bVSrc3ZZ1r8ENHlIXBfnRA= google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f/go.mod h1:CLGoBuH1VHxAUXVPP8FfPwPEVJB6lz3URE5mY2SuayE= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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= @@ -232,6 +280,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=