diff --git a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml index 755d61c919..1f5f8e4229 100644 --- a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml @@ -146,7 +146,7 @@ services: condition: on-failure query-service: - image: signoz/query-service:0.47.0 + image: signoz/query-service:0.48.0 command: [ "-config=/root/config/prometheus.yml", @@ -186,7 +186,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:0.47.0 + image: signoz/frontend:0.48.0 deploy: restart_policy: condition: on-failure @@ -199,7 +199,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector: - image: signoz/signoz-otel-collector:0.88.26 + image: signoz/signoz-otel-collector:0.102.0 command: [ "--config=/etc/otel-collector-config.yaml", @@ -237,7 +237,7 @@ services: - query-service otel-collector-migrator: - image: signoz/signoz-schema-migrator:0.88.26 + image: signoz/signoz-schema-migrator:0.102.0 deploy: restart_policy: condition: on-failure diff --git a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml index 32cd007d3a..13ab19ca2c 100644 --- a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml @@ -77,7 +77,16 @@ processors: # This is added to ensure the uniqueness of the timeseries # Otherwise, identical timeseries produced by multiple replicas of # collectors result in incorrect APM metrics - - name: 'signoz.collector.id' + - name: signoz.collector.id + - name: service.version + - name: browser.platform + - name: browser.mobile + - name: k8s.cluster.name + - name: k8s.node.name + - name: k8s.namespace.name + - name: host.name + - name: host.type + - name: container.name # memory_limiter: # # 80% of maximum memory up to 2G # limit_mib: 1500 @@ -108,6 +117,15 @@ processors: # Otherwise, identical timeseries produced by multiple replicas of # collectors result in incorrect APM metrics - name: signoz.collector.id + - name: service.version + - name: browser.platform + - name: browser.mobile + - name: k8s.cluster.name + - name: k8s.node.name + - name: k8s.namespace.name + - name: host.name + - name: host.type + - name: container.name exporters: clickhousetraces: diff --git a/deploy/docker/clickhouse-setup/docker-compose-core.yaml b/deploy/docker/clickhouse-setup/docker-compose-core.yaml index d18c10f913..bbafa71a1f 100644 --- a/deploy/docker/clickhouse-setup/docker-compose-core.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose-core.yaml @@ -66,7 +66,7 @@ services: - --storage.path=/data otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.26} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.0} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -81,7 +81,7 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` otel-collector: container_name: signoz-otel-collector - image: signoz/signoz-otel-collector:0.88.26 + image: signoz/signoz-otel-collector:0.102.0 command: [ "--config=/etc/otel-collector-config.yaml", diff --git a/deploy/docker/clickhouse-setup/docker-compose.testing.yaml b/deploy/docker/clickhouse-setup/docker-compose.testing.yaml index 48d77b98df..075bb3322c 100644 --- a/deploy/docker/clickhouse-setup/docker-compose.testing.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose.testing.yaml @@ -164,7 +164,7 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` query-service: - image: signoz/query-service:${DOCKER_TAG:-0.47.0} + image: signoz/query-service:${DOCKER_TAG:-0.48.0} container_name: signoz-query-service command: [ @@ -204,7 +204,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:${DOCKER_TAG:-0.47.0} + image: signoz/frontend:${DOCKER_TAG:-0.48.0} container_name: signoz-frontend restart: on-failure depends_on: @@ -216,7 +216,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.26} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.0} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -230,7 +230,7 @@ services: otel-collector: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.26} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.102.0} container_name: signoz-otel-collector command: [ diff --git a/deploy/docker/clickhouse-setup/docker-compose.yaml b/deploy/docker/clickhouse-setup/docker-compose.yaml index d47b7acd46..72980c15a5 100644 --- a/deploy/docker/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose.yaml @@ -164,7 +164,7 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` query-service: - image: signoz/query-service:${DOCKER_TAG:-0.47.0} + image: signoz/query-service:${DOCKER_TAG:-0.48.0} container_name: signoz-query-service command: [ @@ -203,7 +203,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:${DOCKER_TAG:-0.47.0} + image: signoz/frontend:${DOCKER_TAG:-0.48.0} container_name: signoz-frontend restart: on-failure depends_on: @@ -215,7 +215,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.26} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.0} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -229,7 +229,7 @@ services: otel-collector: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.26} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.102.0} container_name: signoz-otel-collector command: [ diff --git a/deploy/docker/clickhouse-setup/otel-collector-config.yaml b/deploy/docker/clickhouse-setup/otel-collector-config.yaml index 7a103d10bf..85e89498be 100644 --- a/deploy/docker/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker/clickhouse-setup/otel-collector-config.yaml @@ -75,7 +75,16 @@ processors: # This is added to ensure the uniqueness of the timeseries # Otherwise, identical timeseries produced by multiple replicas of # collectors result in incorrect APM metrics - - name: 'signoz.collector.id' + - name: signoz.collector.id + - name: service.version + - name: browser.platform + - name: browser.mobile + - name: k8s.cluster.name + - name: k8s.node.name + - name: k8s.namespace.name + - name: host.name + - name: host.type + - name: container.name # memory_limiter: # # 80% of maximum memory up to 2G # limit_mib: 1500 @@ -111,6 +120,15 @@ processors: # Otherwise, identical timeseries produced by multiple replicas of # collectors result in incorrect APM metrics - name: signoz.collector.id + - name: service.version + - name: browser.platform + - name: browser.mobile + - name: k8s.cluster.name + - name: k8s.node.name + - name: k8s.namespace.name + - name: host.name + - name: host.type + - name: container.name extensions: health_check: diff --git a/ee/query-service/app/api/auth.go b/ee/query-service/app/api/auth.go index 9ec99a4cc1..9a28fce263 100644 --- a/ee/query-service/app/api/auth.go +++ b/ee/query-service/app/api/auth.go @@ -14,7 +14,6 @@ import ( "go.signoz.io/signoz/ee/query-service/constants" "go.signoz.io/signoz/ee/query-service/model" - "go.signoz.io/signoz/pkg/query-service/auth" baseauth "go.signoz.io/signoz/pkg/query-service/auth" basemodel "go.signoz.io/signoz/pkg/query-service/model" ) @@ -51,7 +50,7 @@ func (ah *APIHandler) loginUser(w http.ResponseWriter, r *http.Request) { } // if all looks good, call auth - resp, err := auth.Login(ctx, &req) + resp, err := baseauth.Login(ctx, &req) if ah.HandleError(w, err, http.StatusUnauthorized) { return } @@ -130,7 +129,7 @@ func (ah *APIHandler) registerUser(w http.ResponseWriter, r *http.Request) { } else { // no-sso, validate password - if err := auth.ValidatePassword(req.Password); err != nil { + if err := baseauth.ValidatePassword(req.Password); err != nil { RespondError(w, model.InternalError(fmt.Errorf("password is not in a valid format")), nil) return } @@ -241,6 +240,11 @@ func (ah *APIHandler) receiveGoogleAuth(w http.ResponseWriter, r *http.Request) // prepare google callback handler using parsedState - // which contains redirect URL (front-end endpoint) callbackHandler, err := domain.PrepareGoogleOAuthProvider(parsedState) + if err != nil { + zap.L().Error("[receiveGoogleAuth] failed to prepare google oauth provider", zap.String("domain", domain.String()), zap.Error(err)) + handleSsoError(w, r, redirectUri) + return + } identity, err := callbackHandler.HandleCallback(r) if err != nil { diff --git a/ee/query-service/app/db/metrics.go b/ee/query-service/app/db/metrics.go index c7b41b17f5..0cc8a55c32 100644 --- a/ee/query-service/app/db/metrics.go +++ b/ee/query-service/app/db/metrics.go @@ -21,15 +21,15 @@ import ( // GetMetricResultEE runs the query and returns list of time series func (r *ClickhouseReader) GetMetricResultEE(ctx context.Context, query string) ([]*basemodel.Series, string, error) { - defer utils.Elapsed("GetMetricResult")() + defer utils.Elapsed("GetMetricResult", nil)() zap.L().Info("Executing metric result query: ", zap.String("query", query)) var hash string // If getSubTreeSpans function is used in the clickhouse query - if strings.Index(query, "getSubTreeSpans(") != -1 { + if strings.Contains(query, "getSubTreeSpans(") { var err error query, hash, err = r.getSubTreeSpansCustomFunction(ctx, query, hash) - if err == fmt.Errorf("No spans found for the given query") { + if err == fmt.Errorf("no spans found for the given query") { return nil, "", nil } if err != nil { @@ -183,7 +183,7 @@ func (r *ClickhouseReader) getSubTreeSpansCustomFunction(ctx context.Context, qu if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return query, hash, fmt.Errorf("Error in processing sql query") + return query, hash, fmt.Errorf("error in processing sql query") } var searchScanResponses []basemodel.SearchSpanDBResponseItem @@ -193,14 +193,14 @@ func (r *ClickhouseReader) getSubTreeSpansCustomFunction(ctx context.Context, qu modelQuery := fmt.Sprintf("SELECT timestamp, traceID, model FROM %s.%s WHERE traceID=$1", r.TraceDB, r.SpansTable) if len(getSpansSubQueryDBResponses) == 0 { - return query, hash, fmt.Errorf("No spans found for the given query") + return query, hash, fmt.Errorf("no spans found for the given query") } zap.L().Debug("Executing query to fetch all the spans from the same TraceID: ", zap.String("modelQuery", modelQuery)) err = r.conn.Select(ctx, &searchScanResponses, modelQuery, getSpansSubQueryDBResponses[0].TraceID) if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return query, hash, fmt.Errorf("Error in processing sql query") + return query, hash, fmt.Errorf("error in processing sql query") } // Process model to fetch the spans @@ -263,6 +263,7 @@ func (r *ClickhouseReader) getSubTreeSpansCustomFunction(ctx context.Context, qu return query, hash, nil } +//lint:ignore SA4009 return hash is feeded to the query func processQuery(query string, hash string) (string, string, string) { re3 := regexp.MustCompile(`getSubTreeSpans`) diff --git a/ee/query-service/app/db/trace.go b/ee/query-service/app/db/trace.go index dec222a09c..497f56e059 100644 --- a/ee/query-service/app/db/trace.go +++ b/ee/query-service/app/db/trace.go @@ -61,7 +61,7 @@ func SmartTraceAlgorithm(payload []basemodel.SearchSpanResponseItem, targetSpanI // If the target span is not found, return span not found error if targetSpan == nil { - return nil, errors.New("Span not found") + return nil, errors.New("span not found") } // Build the final result @@ -118,8 +118,8 @@ func SmartTraceAlgorithm(payload []basemodel.SearchSpanResponseItem, targetSpanI } searchSpansResult := []basemodel.SearchSpansResult{{ - Columns: []string{"__time", "SpanId", "TraceId", "ServiceName", "Name", "Kind", "DurationNano", "TagsKeys", "TagsValues", "References", "Events", "HasError"}, - Events: make([][]interface{}, len(resultSpansSet)), + Columns: []string{"__time", "SpanId", "TraceId", "ServiceName", "Name", "Kind", "DurationNano", "TagsKeys", "TagsValues", "References", "Events", "HasError"}, + Events: make([][]interface{}, len(resultSpansSet)), IsSubTree: true, }, } @@ -219,7 +219,7 @@ func breadthFirstSearch(spansPtr *model.SpanForTraceDetails, targetId string) (* } for _, child := range current.Children { - if ok, _ := visited[child.SpanID]; !ok { + if ok := visited[child.SpanID]; !ok { queue = append(queue, child) } } diff --git a/ee/query-service/app/server.go b/ee/query-service/app/server.go index 2e1df484d1..75af1d7ebc 100644 --- a/ee/query-service/app/server.go +++ b/ee/query-service/app/server.go @@ -28,7 +28,6 @@ import ( "go.signoz.io/signoz/ee/query-service/integrations/gateway" "go.signoz.io/signoz/ee/query-service/interfaces" baseauth "go.signoz.io/signoz/pkg/query-service/auth" - baseInterface "go.signoz.io/signoz/pkg/query-service/interfaces" v3 "go.signoz.io/signoz/pkg/query-service/model/v3" licensepkg "go.signoz.io/signoz/ee/query-service/license" @@ -79,9 +78,7 @@ type ServerOptions struct { // Server runs HTTP api service type Server struct { serverOptions *ServerOptions - conn net.Listener ruleManager *rules.Manager - separatePorts bool // public http router httpConn net.Listener @@ -91,9 +88,6 @@ type Server struct { privateConn net.Listener privateHTTP *http.Server - // feature flags - featureLookup baseint.FeatureLookup - // Usage manager usageManager *usage.Manager @@ -317,7 +311,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) { func (s *Server) createPrivateServer(apiHandler *api.APIHandler) (*http.Server, error) { - r := mux.NewRouter() + r := baseapp.NewRouter() r.Use(baseapp.LogCommentEnricher) r.Use(setTimeoutMiddleware) @@ -344,7 +338,7 @@ func (s *Server) createPrivateServer(apiHandler *api.APIHandler) (*http.Server, func (s *Server) createPublicServer(apiHandler *api.APIHandler) (*http.Server, error) { - r := mux.NewRouter() + r := baseapp.NewRouter() // add auth middleware getUserFromRequest := func(r *http.Request) (*basemodel.UserPayload, error) { @@ -385,7 +379,7 @@ func loggingMiddleware(next http.Handler) http.Handler { path, _ := route.GetPathTemplate() startTime := time.Now() next.ServeHTTP(w, r) - zap.L().Info(path+"\ttimeTaken:"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path)) + zap.L().Info(path, zap.Duration("timeTaken", time.Since(startTime)), zap.String("path", path)) }) } @@ -397,7 +391,7 @@ func loggingMiddlewarePrivate(next http.Handler) http.Handler { path, _ := route.GetPathTemplate() startTime := time.Now() next.ServeHTTP(w, r) - zap.L().Info(path+"\tprivatePort: true \ttimeTaken"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path), zap.Bool("tprivatePort", true)) + zap.L().Info(path, zap.Duration("timeTaken", time.Since(startTime)), zap.String("path", path), zap.Bool("tprivatePort", true)) }) } @@ -711,7 +705,7 @@ func makeRulesManager( db *sqlx.DB, ch baseint.Reader, disableRules bool, - fm baseInterface.FeatureLookup) (*rules.Manager, error) { + fm baseint.FeatureLookup) (*rules.Manager, error) { // create engine pqle, err := pqle.FromConfigPath(promConfigPath) diff --git a/ee/query-service/integrations/signozio/response.go b/ee/query-service/integrations/signozio/response.go index c8812105f1..67ad8aac88 100644 --- a/ee/query-service/integrations/signozio/response.go +++ b/ee/query-service/integrations/signozio/response.go @@ -2,11 +2,6 @@ package signozio type status string -const ( - statusSuccess status = "success" - statusError status = "error" -) - type ActivationResult struct { Status status `json:"status"` Data *ActivationResponse `json:"data,omitempty"` diff --git a/ee/query-service/license/db.go b/ee/query-service/license/db.go index d6065d045b..f6ccc88426 100644 --- a/ee/query-service/license/db.go +++ b/ee/query-service/license/db.go @@ -111,7 +111,7 @@ func (r *Repo) UpdatePlanDetails(ctx context.Context, planDetails string) error { if key == "" { - return fmt.Errorf("Update Plan Details failed: license key is required") + return fmt.Errorf("update plan details failed: license key is required") } query := `UPDATE licenses diff --git a/ee/query-service/license/sqlite/init.go b/ee/query-service/license/sqlite/init.go index e500ddb4aa..c80bbd5a86 100644 --- a/ee/query-service/license/sqlite/init.go +++ b/ee/query-service/license/sqlite/init.go @@ -32,7 +32,7 @@ func InitDB(db *sqlx.DB) error { _, err = db.Exec(table_schema) if err != nil { - return fmt.Errorf("Error in creating licenses table: %s", err.Error()) + return fmt.Errorf("error in creating licenses table: %s", err.Error()) } table_schema = `CREATE TABLE IF NOT EXISTS feature_status ( @@ -45,7 +45,7 @@ func InitDB(db *sqlx.DB) error { _, err = db.Exec(table_schema) if err != nil { - return fmt.Errorf("Error in creating feature_status table: %s", err.Error()) + return fmt.Errorf("error in creating feature_status table: %s", err.Error()) } return nil diff --git a/ee/query-service/main.go b/ee/query-service/main.go index f88f2cb498..4a8a12af6e 100644 --- a/ee/query-service/main.go +++ b/ee/query-service/main.go @@ -14,7 +14,6 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "go.signoz.io/signoz/ee/query-service/app" "go.signoz.io/signoz/pkg/query-service/auth" - "go.signoz.io/signoz/pkg/query-service/constants" baseconst "go.signoz.io/signoz/pkg/query-service/constants" "go.signoz.io/signoz/pkg/query-service/migrate" "go.signoz.io/signoz/pkg/query-service/version" @@ -52,7 +51,8 @@ func initZapLog(enableQueryServiceLogOTLPExport bool) *zap.Logger { ) if enableQueryServiceLogOTLPExport { - ctx, _ := context.WithTimeout(ctx, time.Second*30) + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() conn, err := grpc.DialContext(ctx, baseconst.OTLPTarget, grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("failed to establish connection: %v", err) @@ -148,7 +148,7 @@ func main() { zap.L().Info("JWT secret key set successfully.") } - if err := migrate.Migrate(constants.RELATIONAL_DATASOURCE_PATH); err != nil { + if err := migrate.Migrate(baseconst.RELATIONAL_DATASOURCE_PATH); err != nil { zap.L().Error("Failed to migrate", zap.Error(err)) } else { zap.L().Info("Migration successful") diff --git a/ee/query-service/model/domain.go b/ee/query-service/model/domain.go index 4d5ff66df2..59a2493525 100644 --- a/ee/query-service/model/domain.go +++ b/ee/query-service/model/domain.go @@ -104,7 +104,7 @@ func (od *OrgDomain) GetSAMLCert() string { // requesting OAuth and also used in processing response from google func (od *OrgDomain) PrepareGoogleOAuthProvider(siteUrl *url.URL) (sso.OAuthCallbackProvider, error) { if od.GoogleAuthConfig == nil { - return nil, fmt.Errorf("Google auth is not setup correctly for this domain") + return nil, fmt.Errorf("GOOGLE OAUTH is not setup correctly for this domain") } return od.GoogleAuthConfig.GetProvider(od.Name, siteUrl) diff --git a/ee/query-service/usage/manager.go b/ee/query-service/usage/manager.go index 72535c9ae5..d52d5ad0c2 100644 --- a/ee/query-service/usage/manager.go +++ b/ee/query-service/usage/manager.go @@ -53,7 +53,7 @@ func New(dbType string, modelDao dao.ModelDao, licenseRepo *license.Repo, clickh tenantID := "" if len(hostNameRegexMatches) == 2 { tenantID = hostNameRegexMatches[1] - tenantID = strings.TrimRight(tenantID, "-clickhouse") + tenantID = strings.TrimSuffix(tenantID, "-clickhouse") } m := &Manager{ diff --git a/frontend/public/Icons/alert_emoji.svg b/frontend/public/Icons/alert_emoji.svg new file mode 100644 index 0000000000..70f9091283 --- /dev/null +++ b/frontend/public/Icons/alert_emoji.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/frontend/public/locales/en-GB/alerts.json b/frontend/public/locales/en-GB/alerts.json index 0901b14d19..a43d04ab59 100644 --- a/frontend/public/locales/en-GB/alerts.json +++ b/frontend/public/locales/en-GB/alerts.json @@ -108,7 +108,7 @@ "user_tooltip_more_help": "More details on how to create alerts", "choose_alert_type": "Choose a type for the alert", "metric_based_alert": "Metric based Alert", - "metric_based_alert_desc": "Send a notification when a condition occurs in the metric data", + "metric_based_alert_desc": "Send a notification when a condition occurs in the metric data.", "log_based_alert": "Log-based Alert", "log_based_alert_desc": "Send a notification when a condition occurs in the logs data.", "traces_based_alert": "Trace-based Alert", diff --git a/frontend/public/locales/en/alerts.json b/frontend/public/locales/en/alerts.json index 597cc24096..e7ed6232ad 100644 --- a/frontend/public/locales/en/alerts.json +++ b/frontend/public/locales/en/alerts.json @@ -108,7 +108,7 @@ "user_tooltip_more_help": "More details on how to create alerts", "choose_alert_type": "Choose a type for the alert", "metric_based_alert": "Metric based Alert", - "metric_based_alert_desc": "Send a notification when a condition occurs in the metric data", + "metric_based_alert_desc": "Send a notification when a condition occurs in the metric data.", "log_based_alert": "Log-based Alert", "log_based_alert_desc": "Send a notification when a condition occurs in the logs data.", "traces_based_alert": "Trace-based Alert", diff --git a/frontend/src/AppRoutes/index.tsx b/frontend/src/AppRoutes/index.tsx index 945ac8b6be..645974204c 100644 --- a/frontend/src/AppRoutes/index.tsx +++ b/frontend/src/AppRoutes/index.tsx @@ -178,23 +178,25 @@ function App(): JSX.Element { }, [pathname]); useEffect(() => { - try { - const isThemeAnalyticsSent = getLocalStorageApi( - LOCALSTORAGE.THEME_ANALYTICS, - ); - if (!isThemeAnalyticsSent) { - trackEvent('Theme Analytics', { - theme: isDarkMode ? THEME_MODE.DARK : THEME_MODE.LIGHT, - user: pick(user, ['email', 'userId', 'name']), - org, - }); - setLocalStorageApi(LOCALSTORAGE.THEME_ANALYTICS, 'true'); + if (user && user?.email && user?.userId && user?.name) { + try { + const isThemeAnalyticsSent = getLocalStorageApi( + LOCALSTORAGE.THEME_ANALYTICS_V1, + ); + if (!isThemeAnalyticsSent) { + trackEvent('Theme Analytics', { + theme: isDarkMode ? THEME_MODE.DARK : THEME_MODE.LIGHT, + user: pick(user, ['email', 'userId', 'name']), + org, + }); + setLocalStorageApi(LOCALSTORAGE.THEME_ANALYTICS_V1, 'true'); + } + } catch { + console.error('Failed to parse local storage theme analytics event'); } - } catch { - console.error('Failed to parse local storage theme analytics event'); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [user]); return ( diff --git a/frontend/src/AppRoutes/pageComponents.ts b/frontend/src/AppRoutes/pageComponents.ts index bda390afbf..9275e7d6f6 100644 --- a/frontend/src/AppRoutes/pageComponents.ts +++ b/frontend/src/AppRoutes/pageComponents.ts @@ -11,6 +11,13 @@ export const ServiceMetricsPage = Loadable( ), ); +export const ServiceTopLevelOperationsPage = Loadable( + () => + import( + /* webpackChunkName: "ServiceMetricsPage" */ 'pages/ServiceTopLevelOperations' + ), +); + export const ServiceMapPage = Loadable( () => import(/* webpackChunkName: "ServiceMapPage" */ 'modules/Servicemap'), ); diff --git a/frontend/src/AppRoutes/routes.ts b/frontend/src/AppRoutes/routes.ts index fed77f186e..4fd421ffba 100644 --- a/frontend/src/AppRoutes/routes.ts +++ b/frontend/src/AppRoutes/routes.ts @@ -33,6 +33,7 @@ import { ServiceMapPage, ServiceMetricsPage, ServicesTablePage, + ServiceTopLevelOperationsPage, SettingsPage, ShortcutsPage, SignupPage, @@ -84,6 +85,13 @@ const routes: AppRoutes[] = [ isPrivate: true, key: 'SERVICE_METRICS', }, + { + path: ROUTES.SERVICE_TOP_LEVEL_OPERATIONS, + exact: true, + component: ServiceTopLevelOperationsPage, + isPrivate: true, + key: 'SERVICE_TOP_LEVEL_OPERATIONS', + }, { path: ROUTES.SERVICE_MAP, component: ServiceMapPage, diff --git a/frontend/src/components/DropDown/DropDown.tsx b/frontend/src/components/DropDown/DropDown.tsx index c29fbdd15b..df845b7084 100644 --- a/frontend/src/components/DropDown/DropDown.tsx +++ b/frontend/src/components/DropDown/DropDown.tsx @@ -3,6 +3,7 @@ import './DropDown.styles.scss'; import { EllipsisOutlined } from '@ant-design/icons'; import { Button, Dropdown, MenuProps } from 'antd'; import { useIsDarkMode } from 'hooks/useDarkMode'; +import { useState } from 'react'; function DropDown({ element }: { element: JSX.Element[] }): JSX.Element { const isDarkMode = useIsDarkMode(); @@ -14,12 +15,24 @@ function DropDown({ element }: { element: JSX.Element[] }): JSX.Element { }), ); + const [isDdOpen, setDdOpen] = useState(false); + return ( - + setDdOpen(true), + onMouseLeave: (): void => setDdOpen(false), + }} + open={isDdOpen} + > diff --git a/frontend/src/components/Uplot/Uplot.tsx b/frontend/src/components/Uplot/Uplot.tsx index 05f050a87c..af6e28ddf3 100644 --- a/frontend/src/components/Uplot/Uplot.tsx +++ b/frontend/src/components/Uplot/Uplot.tsx @@ -1,6 +1,7 @@ /* eslint-disable sonarjs/cognitive-complexity */ import './Uplot.styles.scss'; +import * as Sentry from '@sentry/react'; import { Typography } from 'antd'; import { ToggleGraphProps } from 'components/Graph/types'; import { LineChart } from 'lucide-react'; @@ -13,7 +14,6 @@ import { useImperativeHandle, useRef, } from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; import UPlot from 'uplot'; import { dataMatch, optionsUpdateState } from './utils'; @@ -139,7 +139,7 @@ const Uplot = forwardRef( } return ( - + }>
{data && data[0] && data[0]?.length === 0 ? (
@@ -147,7 +147,7 @@ const Uplot = forwardRef(
) : null}
-
+ ); }, ); diff --git a/frontend/src/components/facingIssueBtn/FacingIssueBtn.style.scss b/frontend/src/components/facingIssueBtn/FacingIssueBtn.style.scss index 68602d3aca..2cf239dfd9 100644 --- a/frontend/src/components/facingIssueBtn/FacingIssueBtn.style.scss +++ b/frontend/src/components/facingIssueBtn/FacingIssueBtn.style.scss @@ -2,12 +2,24 @@ color: var(--bg-amber-500); border-color: var(--bg-amber-500); - .ant-btn:hover { + > .ant-btn:hover { color: var(--bg-amber-400) !important; border-color: var(--bg-amber-300) !important; } } +.lightMode { + .facing-issue-button { + color: var(--bg-vanilla-500); + border-color: var(--bg-vanilla-300); + + > .ant-btn:hover { + color: var(--bg-vanilla-500) !important; + border-color: var(--bg-vanilla-300) !important; + } + } +} + .tooltip-overlay { text-wrap: nowrap; .ant-tooltip-inner { diff --git a/frontend/src/constants/localStorage.ts b/frontend/src/constants/localStorage.ts index 481bf5dab0..c7e8b81179 100644 --- a/frontend/src/constants/localStorage.ts +++ b/frontend/src/constants/localStorage.ts @@ -18,5 +18,5 @@ export enum LOCALSTORAGE { DASHBOARD_VARIABLES = 'DASHBOARD_VARIABLES', SHOW_EXPLORER_TOOLBAR = 'SHOW_EXPLORER_TOOLBAR', PINNED_ATTRIBUTES = 'PINNED_ATTRIBUTES', - THEME_ANALYTICS = 'THEME_ANALYTICS', + THEME_ANALYTICS_V1 = 'THEME_ANALYTICS_V1', } diff --git a/frontend/src/constants/panelTypes.ts b/frontend/src/constants/panelTypes.ts index 7476b20783..8892f0fcbe 100644 --- a/frontend/src/constants/panelTypes.ts +++ b/frontend/src/constants/panelTypes.ts @@ -40,4 +40,5 @@ export const getComponentForPanelType = ( export const AVAILABLE_EXPORT_PANEL_TYPES = [ PANEL_TYPES.TIME_SERIES, PANEL_TYPES.TABLE, + PANEL_TYPES.LIST, ]; diff --git a/frontend/src/constants/queryBuilder.ts b/frontend/src/constants/queryBuilder.ts index 9d09cd37ed..7b7b464b3e 100644 --- a/frontend/src/constants/queryBuilder.ts +++ b/frontend/src/constants/queryBuilder.ts @@ -174,8 +174,8 @@ export const initialQueryBuilderFormValues: IBuilderQuery = { sourceNames: alphabet, }), disabled: false, - having: [], stepInterval: 60, + having: [], limit: null, orderBy: [], groupBy: [], diff --git a/frontend/src/constants/routes.ts b/frontend/src/constants/routes.ts index cbeb672a5c..243bdd0bba 100644 --- a/frontend/src/constants/routes.ts +++ b/frontend/src/constants/routes.ts @@ -2,6 +2,7 @@ const ROUTES = { SIGN_UP: '/signup', LOGIN: '/login', SERVICE_METRICS: '/services/:servicename', + SERVICE_TOP_LEVEL_OPERATIONS: '/services/:servicename/top-level-operations', SERVICE_MAP: '/service-map', TRACE: '/trace', TRACE_DETAIL: '/trace/:id', diff --git a/frontend/src/constants/theme.ts b/frontend/src/constants/theme.ts index 427a13efe8..edc0eea75f 100644 --- a/frontend/src/constants/theme.ts +++ b/frontend/src/constants/theme.ts @@ -78,6 +78,82 @@ const themeColors = { mediumVioletRed: '#C71585', paleGreen: '#98FB98', }, + lightModeColor: { + robin: '#3F5ECC', + dodgerBlueDark: '#0C6EED', + steelgrey: '#2f4b7c', + steelpurple: '#665191', + steelindigo: '#a05195', + steelpink: '#d45087', + steelcoral: '#f95d6a', + steelorange: '#ff7c43', + steelgold: '#ffa600', + steelrust: '#de425b', + steelgreen: '#41967e', + mediumOrchidDark: '#C326FD', + seaBuckthornDark: '#E66E05', + seaGreen: '#219653', + turquoiseBlueDark: '#0099CC', + silverDark: '#757575', + outrageousOrangeDark: '#F9521A', + roseBudDark: '#EB6437', + deepSkyBlueDark: '#0595BD', + royalBlue: '#3366E6', + avocadoDark: '#8E8E29', + mintGreenDark: '#00C700', + chestnut: '#B34D4D', + limaDark: '#6E9900', + olive: '#809900', + beautyBushDark: '#E25555', + danube: '#6680B3', + oliveDrab: '#66991A', + lavenderRoseDark: '#F024BD', + electricLimeDark: '#84A800', + radicalRed: '#FF1A66', + harleyOrange: '#E6331A', + gladeGreen: '#66994D', + hemlock: '#66664D', + vidaLoca: '#4D8000', + rust: '#B33300', + red: '#FF0000', // Adding more colors, we need to get better colors from design team + blue: '#0000FF', + green: '#00FF00', + purple: '#800080', + magentaDark: '#EB00EB', + pinkDark: '#FF3D5E', + brown: '#A52A2A', + teal: '#008080', + limeDark: '#07A207', + maroon: '#800000', + navy: '#000080', + gray: '#808080', + skyBlueDark: '#0CA7E4', + indigo: '#4B0082', + slateGray: '#708090', + chocolate: '#D2691E', + tomato: '#FF6347', + steelBlue: '#4682B4', + peruDark: '#D16E0A', + darkOliveGreen: '#556B2F', + indianRed: '#CD5C5C', + mediumSlateBlue: '#7B68EE', + rosyBrownDark: '#CB4848', + darkSlateGray: '#2F4F4F', + fuchsia: '#FF0AFF', + salmonDark: '#FF432E', + darkSalmonDark: '#D26541', + paleVioletRedDark: '#E83089', + mediumPurple: '#9370DB', + darkOrchid: '#9932CC', + mediumSeaGreenDark: '#109E50', + lightCoralDark: '#F85959', + darkSeaGreenDark: '#509F50', + sandyBrownDark: '#D97117', + darkKhakiDark: '#99900A', + cornflowerBlueDark: '#3371E6', + mediumVioletRed: '#C71585', + paleGreenDark: '#0D910D', + }, errorColor: '#d32f2f', royalGrey: '#888888', matterhornGrey: '#555555', diff --git a/frontend/src/container/AllAlertChannels/index.tsx b/frontend/src/container/AllAlertChannels/index.tsx index 8038f17778..5f34264a60 100644 --- a/frontend/src/container/AllAlertChannels/index.tsx +++ b/frontend/src/container/AllAlertChannels/index.tsx @@ -1,5 +1,5 @@ import { PlusOutlined } from '@ant-design/icons'; -import { Typography } from 'antd'; +import { Tooltip, Typography } from 'antd'; import getAll from 'api/channels/getAll'; import Spinner from 'components/Spinner'; import TextToolTip from 'components/TextToolTip'; @@ -52,11 +52,21 @@ function AlertChannels(): JSX.Element { url="https://signoz.io/docs/userguide/alerts-management/#setting-notification-channel" /> - {addNewChannelPermission && ( - - )} + diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index f3beabb2bc..ef7be7eef4 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -3,6 +3,7 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import './AppLayout.styles.scss'; +import * as Sentry from '@sentry/react'; import { Flex } from 'antd'; import getLocalStorageKey from 'api/browser/localstorage/get'; import getDynamicConfigs from 'api/dynamicConfigs/getDynamicConfigs'; @@ -27,7 +28,6 @@ import { useRef, useState, } from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; import { Helmet } from 'react-helmet-async'; import { useTranslation } from 'react-i18next'; import { useQueries } from 'react-query'; @@ -342,7 +342,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element { /> )}
- + }> - +
diff --git a/frontend/src/container/BillingContainer/BillingContainer.tsx b/frontend/src/container/BillingContainer/BillingContainer.tsx index 9b45801356..248819723c 100644 --- a/frontend/src/container/BillingContainer/BillingContainer.tsx +++ b/frontend/src/container/BillingContainer/BillingContainer.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-loop-func */ import './BillingContainer.styles.scss'; -import { CheckCircleOutlined } from '@ant-design/icons'; +import { CheckCircleOutlined, CloudDownloadOutlined } from '@ant-design/icons'; import { Color } from '@signozhq/design-tokens'; import { Alert, @@ -40,6 +40,7 @@ import { isCloudUser } from 'utils/app'; import { getFormattedDate, getRemainingDays } from 'utils/timeUtils'; import { BillingUsageGraph } from './BillingUsageGraph/BillingUsageGraph'; +import { prepareCsvData } from './BillingUsageGraph/utils'; interface DataType { key: string; @@ -371,6 +372,37 @@ export default function BillingContainer(): JSX.Element { ); + const handleCsvDownload = useCallback((): void => { + try { + const csv = prepareCsvData(apiResponse); + + if (!csv.csvData || !csv.fileName) { + throw new Error('Invalid CSV data or file name.'); + } + + const csvBlob = new Blob([csv.csvData], { type: 'text/csv;charset=utf-8;' }); + const csvUrl = URL.createObjectURL(csvBlob); + const downloadLink = document.createElement('a'); + + downloadLink.href = csvUrl; + downloadLink.download = csv.fileName; + document.body.appendChild(downloadLink); // Required for Firefox + downloadLink.click(); + + // Clean up + downloadLink.remove(); + URL.revokeObjectURL(csvUrl); // Release the memory associated with the object URL + notifications.success({ + message: 'Download successful', + }); + } catch (error) { + console.error('Error downloading the CSV file:', error); + notifications.error({ + message: SOMETHING_WENT_WRONG, + }); + } + }, [apiResponse, notifications]); + return (
@@ -399,17 +431,29 @@ export default function BillingContainer(): JSX.Element { ) : null} - + + + + {licensesData?.payload?.onTrial && diff --git a/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx b/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx index 0aecc5d102..3afee8d0d6 100644 --- a/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx +++ b/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx @@ -166,6 +166,7 @@ export function BillingUsageGraph(props: BillingUsageGraphProps): JSX.Element { ), yAxisUnit: '', isBillingUsageGraphs: true, + isDarkMode, }), ], }), diff --git a/frontend/src/container/BillingContainer/BillingUsageGraph/generateCsvData.ts b/frontend/src/container/BillingContainer/BillingUsageGraph/generateCsvData.ts new file mode 100644 index 0000000000..b70526aaa8 --- /dev/null +++ b/frontend/src/container/BillingContainer/BillingUsageGraph/generateCsvData.ts @@ -0,0 +1,129 @@ +import dayjs from 'dayjs'; + +export interface QuantityData { + metric: string; + values: [number, number][]; + queryName: string; + legend: string; + quantity: number[]; + unit: string; +} + +interface DataPoint { + date: string; + metric: { + total: number; + cost: number; + }; + trace: { + total: number; + cost: number; + }; + log: { + total: number; + cost: number; + }; +} + +interface CsvData { + Date: string; + 'Metrics Vol (Mn samples)': number; + 'Metrics Cost ($)': number; + 'Traces Vol (GBs)': number; + 'Traces Cost ($)': number; + 'Logs Vol (GBs)': number; + 'Logs Cost ($)': number; +} + +const formatDate = (timestamp: number): string => + dayjs.unix(timestamp).format('MM/DD/YYYY'); + +const getQuantityData = ( + data: QuantityData[], + metricName: string, +): QuantityData => { + const defaultData: QuantityData = { + metric: metricName, + values: [], + queryName: metricName, + legend: metricName, + quantity: [], + unit: '', + }; + return data.find((d) => d.metric === metricName) || defaultData; +}; + +const generateCsvData = (quantityData: QuantityData[]): any[] => { + const convertData = (data: QuantityData[]): DataPoint[] => { + const metricsData = getQuantityData(data, 'Metrics'); + const tracesData = getQuantityData(data, 'Traces'); + const logsData = getQuantityData(data, 'Logs'); + + const timestamps = metricsData.values.map((value) => value[0]); + + return timestamps.map((timestamp, index) => { + const date = formatDate(timestamp); + + return { + date, + metric: { + total: metricsData.quantity[index] ?? 0, + cost: metricsData.values[index]?.[1] ?? 0, + }, + trace: { + total: tracesData.quantity[index] ?? 0, + cost: tracesData.values[index]?.[1] ?? 0, + }, + log: { + total: logsData.quantity[index] ?? 0, + cost: logsData.values[index]?.[1] ?? 0, + }, + }; + }); + }; + + const formattedData = convertData(quantityData); + + // Calculate totals + const totals = formattedData.reduce( + (acc, dataPoint) => { + acc.metric.total += dataPoint.metric.total; + acc.metric.cost += dataPoint.metric.cost; + acc.trace.total += dataPoint.trace.total; + acc.trace.cost += dataPoint.trace.cost; + acc.log.total += dataPoint.log.total; + acc.log.cost += dataPoint.log.cost; + return acc; + }, + { + metric: { total: 0, cost: 0 }, + trace: { total: 0, cost: 0 }, + log: { total: 0, cost: 0 }, + }, + ); + + const csvData: CsvData[] = formattedData.map((dataPoint) => ({ + Date: dataPoint.date, + 'Metrics Vol (Mn samples)': parseFloat(dataPoint.metric.total.toFixed(2)), + 'Metrics Cost ($)': parseFloat(dataPoint.metric.cost.toFixed(2)), + 'Traces Vol (GBs)': parseFloat(dataPoint.trace.total.toFixed(2)), + 'Traces Cost ($)': parseFloat(dataPoint.trace.cost.toFixed(2)), + 'Logs Vol (GBs)': parseFloat(dataPoint.log.total.toFixed(2)), + 'Logs Cost ($)': parseFloat(dataPoint.log.cost.toFixed(2)), + })); + + // Add totals row + csvData.push({ + Date: 'Total', + 'Metrics Vol (Mn samples)': parseFloat(totals.metric.total.toFixed(2)), + 'Metrics Cost ($)': parseFloat(totals.metric.cost.toFixed(2)), + 'Traces Vol (GBs)': parseFloat(totals.trace.total.toFixed(2)), + 'Traces Cost ($)': parseFloat(totals.trace.cost.toFixed(2)), + 'Logs Vol (GBs)': parseFloat(totals.log.total.toFixed(2)), + 'Logs Cost ($)': parseFloat(totals.log.cost.toFixed(2)), + }); + + return csvData; +}; + +export default generateCsvData; diff --git a/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts b/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts index d40c8a6097..5123d59329 100644 --- a/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts +++ b/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts @@ -1,6 +1,12 @@ +import { UsageResponsePayloadProps } from 'api/billing/getUsage'; +import dayjs from 'dayjs'; +import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData'; import { isEmpty, isNull } from 'lodash-es'; +import { unparse } from 'papaparse'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; +import generateCsvData, { QuantityData } from './generateCsvData'; + export const convertDataToMetricRangePayload = ( data: any, ): MetricRangePayloadProps => { @@ -58,10 +64,7 @@ export const convertDataToMetricRangePayload = ( }; }; -export function fillMissingValuesForQuantities( - data: any, - timestampArray: number[], -): MetricRangePayloadProps { +export function quantityDataArr(data: any, timestampArray: number[]): any[] { const { result } = data.data; const transformedResultArr: any[] = []; @@ -76,6 +79,14 @@ export function fillMissingValuesForQuantities( ); transformedResultArr.push({ ...item, quantity: quantityArray }); }); + return transformedResultArr; +} + +export function fillMissingValuesForQuantities( + data: any, + timestampArray: number[], +): MetricRangePayloadProps { + const transformedResultArr = quantityDataArr(data, timestampArray); return { data: { @@ -85,3 +96,36 @@ export function fillMissingValuesForQuantities( }, }; } + +const formatDate = (timestamp: number): string => + dayjs.unix(timestamp).format('MM/DD/YYYY'); + +export function csvFileName(csvData: QuantityData[]): string { + if (!csvData.length) { + return `billing-usage.csv`; + } + + const { values } = csvData[0]; + + const timestamps = values.map((item) => item[0]); + const startDate = formatDate(Math.min(...timestamps)); + const endDate = formatDate(Math.max(...timestamps)); + + return `billing_usage_(${startDate}-${endDate}).csv`; +} + +export function prepareCsvData( + data: Partial, +): { + csvData: string; + fileName: string; +} { + const graphCompatibleData = convertDataToMetricRangePayload(data); + const chartData = getUPlotChartData(graphCompatibleData); + const quantityMapArr = quantityDataArr(graphCompatibleData, chartData[0]); + + return { + csvData: unparse(generateCsvData(quantityMapArr)), + fileName: csvFileName(quantityMapArr), + }; +} diff --git a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx index 60bf658e5d..cd837b666b 100644 --- a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx +++ b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx @@ -12,6 +12,30 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element { const optionList = getOptionList(t); + function handleRedirection(option: AlertTypes): void { + let url = ''; + switch (option) { + case AlertTypes.METRICS_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples'; + break; + case AlertTypes.LOGS_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples'; + break; + case AlertTypes.TRACES_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples'; + break; + case AlertTypes.EXCEPTIONS_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples'; + break; + default: + break; + } + window.open(url, '_blank'); + } const renderOptions = useMemo( () => ( <> @@ -23,7 +47,16 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element { onSelect(option.selection); }} > - {option.description} + {option.description}{' '} + { + e.preventDefault(); + e.stopPropagation(); + handleRedirection(option.selection); + }} + > + Click here to see how to create a sample alert. + {' '} ))} diff --git a/frontend/src/container/CreateAlertRule/defaults.ts b/frontend/src/container/CreateAlertRule/defaults.ts index 677f4accc4..20cd020158 100644 --- a/frontend/src/container/CreateAlertRule/defaults.ts +++ b/frontend/src/container/CreateAlertRule/defaults.ts @@ -130,7 +130,7 @@ export const exceptionAlertDefaults: AlertDef = { disabled: false, }, }, - queryType: EQueryType.QUERY_BUILDER, + queryType: EQueryType.CLICKHOUSE, panelType: PANEL_TYPES.TIME_SERIES, unit: undefined, }, diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss b/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss index 8af1e4ad0a..2076b858f9 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss @@ -1,18 +1,27 @@ +.explorer-options-container { + position: fixed; + bottom: 24px; + left: calc(50% + 240px); + transform: translate(calc(-50% - 120px), 0); + transition: left 0.2s linear; + + display: flex; + gap: 16px; + background-color: transparent; +} + .hide-update { left: calc(50% - 72px) !important; } + .explorer-update { - position: fixed; - bottom: 24px; - left: calc(50% - 352px); - display: flex; + display: inline-flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 50px; border: 1px solid var(--bg-slate-400); background: rgba(22, 24, 29, 0.6); - box-shadow: 4px 4px 16px 4px rgba(0, 0, 0, 0.25); backdrop-filter: blur(20px); .action-icon { @@ -38,16 +47,10 @@ } .explorer-options { - position: fixed; - bottom: 24px; - left: calc(50% + 240px); padding: 10px 12px; - transform: translate(calc(-50% - 120px), 0); - transition: left 0.2s linear; border: 1px solid var(--bg-slate-400); border-radius: 50px; background: rgba(22, 24, 29, 0.6); - box-shadow: 4px 4px 16px 4px rgba(0, 0, 0, 0.25); backdrop-filter: blur(20px); cursor: default; @@ -124,7 +127,7 @@ .app-content { &.collapsed { - .explorer-options { + .explorer-options-container { left: calc(50% + 72px); } } diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx index 7253b45b94..1aaf22f796 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx @@ -289,7 +289,7 @@ function ExplorerOptions({ const isEditDeleteSupported = allowedRoles.includes(role as string); return ( - <> +
{isQueryUpdated && !isExplorerOptionHidden && (
- +
); } diff --git a/frontend/src/container/FormAlertRules/BasicInfo.tsx b/frontend/src/container/FormAlertRules/BasicInfo.tsx index 54877f5e0b..5fae4a713d 100644 --- a/frontend/src/container/FormAlertRules/BasicInfo.tsx +++ b/frontend/src/container/FormAlertRules/BasicInfo.tsx @@ -1,7 +1,17 @@ -import { Form, Select, Switch } from 'antd'; -import { useEffect, useState } from 'react'; +import './FormAlertRules.styles.scss'; + +import { PlusOutlined } from '@ant-design/icons'; +import { Button, Form, Select, Switch, Tooltip } from 'antd'; +import getChannels from 'api/channels/getAll'; +import ROUTES from 'constants/routes'; +import useComponentPermission from 'hooks/useComponentPermission'; +import useFetch from 'hooks/useFetch'; +import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; +import { AppState } from 'store/reducers'; import { AlertDef, Labels } from 'types/api/alerts/def'; +import AppReducer from 'types/reducer/app'; import { requireErrorMessage } from 'utils/form/requireErrorMessage'; import { popupContainer } from 'utils/selectPopupContainer'; @@ -31,6 +41,13 @@ function BasicInfo({ }: BasicInfoProps): JSX.Element { const { t } = useTranslation('alerts'); + const channels = useFetch(getChannels); + const { role } = useSelector((state) => state.app); + const [addNewChannelPermission] = useComponentPermission( + ['add_new_channel'], + role, + ); + const [ shouldBroadCastToAllChannels, setShouldBroadCastToAllChannels, @@ -54,6 +71,11 @@ function BasicInfo({ }); }; + const noChannels = channels.payload?.length === 0; + const handleCreateNewChannels = useCallback(() => { + window.open(ROUTES.CHANNELS_NEW, '_blank'); + }, []); + return ( <> {t('alert_form_step3')} @@ -137,32 +159,74 @@ function BasicInfo({ name="alert_all_configured_channels" label="Alert all the configured channels" > - + + + {!shouldBroadCastToAllChannels && ( - - { - setAlertDef({ - ...alertDef, - preferredChannels, - }); - }} - /> - + + { + setAlertDef({ + ...alertDef, + preferredChannels, + }); + }} + /> + + + )} + + {noChannels && ( + + + )} diff --git a/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx b/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx index 15f391c7cf..ad1b9fb327 100644 --- a/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx +++ b/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx @@ -1,9 +1,9 @@ import { Select } from 'antd'; -import getChannels from 'api/channels/getAll'; -import useFetch from 'hooks/useFetch'; +import { State } from 'hooks/useFetch'; import { useNotifications } from 'hooks/useNotifications'; import { ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; +import { PayloadProps } from 'types/api/channels/getAll'; import { StyledSelect } from './styles'; @@ -11,38 +11,42 @@ export interface ChannelSelectProps { disabled?: boolean; currentValue?: string[]; onSelectChannels: (s: string[]) => void; + channels: State; } function ChannelSelect({ disabled, currentValue, onSelectChannels, + channels, }: ChannelSelectProps): JSX.Element | null { // init namespace for translations const { t } = useTranslation('alerts'); - const { loading, payload, error, errorMessage } = useFetch(getChannels); - const { notifications } = useNotifications(); const handleChange = (value: string[]): void => { onSelectChannels(value); }; - if (error && errorMessage !== '') { + if (channels.error && channels.errorMessage !== '') { notifications.error({ message: 'Error', - description: errorMessage, + description: channels.errorMessage, }); } const renderOptions = (): ReactNode[] => { const children: ReactNode[] = []; - if (loading || payload === undefined || payload.length === 0) { + if ( + channels.loading || + channels.payload === undefined || + channels.payload.length === 0 + ) { return children; } - payload.forEach((o) => { + channels.payload.forEach((o) => { children.push( {o.name} @@ -55,7 +59,7 @@ function ChannelSelect({ return ( ((state) => state.globalTime); const urlQuery = useUrlQuery(); - const panelType = urlQuery.get(QueryParams.panelTypes) as PANEL_TYPES | null; + // In case of alert the panel types should always be "Graph" only + const panelType = PANEL_TYPES.TIME_SERIES; const { currentQuery, @@ -102,6 +104,13 @@ function FormAlertRules({ const [alertDef, setAlertDef] = useState(initialValue); const [yAxisUnit, setYAxisUnit] = useState(currentQuery.unit || ''); + useEffect(() => { + if (!isEqual(currentQuery.unit, yAxisUnit)) { + setYAxisUnit(currentQuery.unit || ''); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentQuery.unit]); + // initQuery contains initial query when component was mounted const initQuery = useMemo(() => initialValue.condition.compositeQuery, [ initialValue, @@ -183,7 +192,9 @@ function FormAlertRules({ } const query: Query = { ...currentQuery, queryType: val }; - redirectWithQueryBuilderData(updateStepInterval(query, maxTime, minTime)); + // update step interval is removed from here as if the user enters + // any value we will use that rather than auto update + redirectWithQueryBuilderData(query); }; const { notifications } = useNotifications(); @@ -245,7 +256,7 @@ function FormAlertRules({ if ( !currentQuery.builder.queryData || - currentQuery.builder.queryData.length === 0 + currentQuery.builder.queryData?.length === 0 ) { notifications.error({ message: 'Error', @@ -502,6 +513,31 @@ function FormAlertRules({ const isRuleCreated = !ruleId || ruleId === 0; + function handleRedirection(option: AlertTypes): void { + let url = ''; + switch (option) { + case AlertTypes.METRICS_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples'; + break; + case AlertTypes.LOGS_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples'; + break; + case AlertTypes.TRACES_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples'; + break; + case AlertTypes.EXCEPTIONS_BASED_ALERT: + url = + 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples'; + break; + default: + break; + } + window.open(url, '_blank'); + } + return ( <> {Element} @@ -532,7 +568,7 @@ function FormAlertRules({ queryCategory={currentQuery.queryType} setQueryCategory={onQueryCategoryChange} alertType={alertType || AlertTypes.METRICS_BASED_ALERT} - runQuery={handleRunQuery} + runQuery={(): void => handleRunQuery(true)} alertDef={alertDef} panelType={panelType || PANEL_TYPES.TIME_SERIES} key={currentQuery.queryType} @@ -585,22 +621,33 @@ function FormAlertRules({ - +
+ + +
diff --git a/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx b/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx index 184c34e77b..02d71ed9bb 100644 --- a/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx +++ b/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx @@ -15,7 +15,6 @@ import { } from 'container/NewWidget/RightContainer/timeItems'; import PanelWrapper from 'container/PanelWrapper/PanelWrapper'; import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange'; -import { useStepInterval } from 'hooks/queryBuilder/useStepInterval'; import { useChartMutable } from 'hooks/useChartMutable'; import useUrlQuery from 'hooks/useUrlQuery'; import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables'; @@ -71,7 +70,7 @@ function FullView({ enum: widget?.timePreferance || 'GLOBAL_TIME', }); - const updatedQuery = useStepInterval(widget?.query); + const updatedQuery = widget?.query; const [requestData, setRequestData] = useState(() => { if (widget.panelTypes !== PANEL_TYPES.LIST) { @@ -204,7 +203,7 @@ function FullView({
l.i === widget.id, + ); + + // added the cloned panel on the top as it is given most priority when arranging + // in the layout. React_grid_layout assigns priority from top, hence no random position for cloned panel const layout = [ - ...(selectedDashboard.data.layout || []), { i: uuid, - w: 6, + w: originalPanelLayout?.w || 6, x: 0, - h: 6, + h: originalPanelLayout?.h || 6, y: 0, }, + ...(selectedDashboard.data.layout || []), ]; updateDashboardMutation.mutateAsync( diff --git a/frontend/src/container/GridCardLayout/GridCard/index.tsx b/frontend/src/container/GridCardLayout/GridCard/index.tsx index a553fe7241..28c67ae92e 100644 --- a/frontend/src/container/GridCardLayout/GridCard/index.tsx +++ b/frontend/src/container/GridCardLayout/GridCard/index.tsx @@ -3,7 +3,6 @@ import { QueryParams } from 'constants/query'; import { PANEL_TYPES } from 'constants/queryBuilder'; import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config'; import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange'; -import { useStepInterval } from 'hooks/queryBuilder/useStepInterval'; import { useIntersectionObserver } from 'hooks/useIntersectionObserver'; import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables'; import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults'; @@ -90,7 +89,7 @@ function GridCardGraph({ } }, [toScrollWidgetId, setToScrollWidgetId, widget.id]); - const updatedQuery = useStepInterval(widget?.query); + const updatedQuery = widget?.query; const isEmptyWidget = widget?.id === PANEL_TYPES.EMPTY_WIDGET || isEmpty(widget); @@ -109,6 +108,7 @@ function GridCardGraph({ query: updatedQuery, globalSelectedInterval, variables: getDashboardVariables(variables), + fillGaps: widget.fillSpans, }; } updatedQuery.builder.queryData[0].pageSize = 10; @@ -123,6 +123,7 @@ function GridCardGraph({ limit: updatedQuery.builder.queryData[0].limit || 0, }, }, + fillGaps: widget.fillSpans, }; }); @@ -153,6 +154,7 @@ function GridCardGraph({ widget?.query, widget?.panelTypes, widget.timePreferance, + widget.fillSpans, requestData, ], retry(failureCount, error): boolean { diff --git a/frontend/src/container/GridTableComponent/index.tsx b/frontend/src/container/GridTableComponent/index.tsx index 26bdda1a49..171f09da07 100644 --- a/frontend/src/container/GridTableComponent/index.tsx +++ b/frontend/src/container/GridTableComponent/index.tsx @@ -62,10 +62,11 @@ function GridTableComponent({ mutateDataSource = mutateDataSource.map( (val): RowData => { - const newValue = val; + const newValue = { ...val }; Object.keys(val).forEach((k) => { if (columnUnits[k]) { newValue[k] = getYAxisFormattedValue(String(val[k]), columnUnits[k]); + newValue[`${k}_without_unit`] = val[k]; } }); return newValue; @@ -81,7 +82,6 @@ function GridTableComponent({ applyColumnUnits, originalDataSource, ]); - useEffect(() => { if (tableProcessedDataRef) { // eslint-disable-next-line no-param-reassign diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx new file mode 100644 index 0000000000..76403a1884 --- /dev/null +++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx @@ -0,0 +1,37 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +import { ArrowRightOutlined } from '@ant-design/icons'; +import { Typography } from 'antd'; + +interface AlertInfoCardProps { + header: string; + subheader: string; + link: string; +} + +function AlertInfoCard({ + header, + subheader, + link, +}: AlertInfoCardProps): JSX.Element { + return ( +
{ + window.open(link, '_blank'); + }} + > +
+ + {header} + + + {subheader} + +
+ +
+ ); +} + +export default AlertInfoCard; diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss new file mode 100644 index 0000000000..c852b5833b --- /dev/null +++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss @@ -0,0 +1,251 @@ +.alert-list-container { + margin-top: 104px; + margin-bottom: 30px; + display: flex; + justify-content: center; + width: 100%; + + .alert-list-view-content { + width: calc(100% - 30px); + max-width: 836px; + + .alert-list-title-container { + .title { + color: var(--bg-vanilla-100); + font-size: var(--font-size-lg); + font-style: normal; + font-weight: var(--font-weight-normal); + line-height: 28px; /* 155.556% */ + letter-spacing: -0.09px; + } + + .subtitle { + color: var(--bg-vanilla-400); + font-size: var(--font-size-sm); + font-style: normal; + font-weight: var(--font-weight-normal); + line-height: 20px; /* 142.857% */ + letter-spacing: -0.07px; + } + } + + .empty-alert-info-container { + display: flex; + padding: 71px 193.5px; + justify-content: center; + align-items: center; + border-radius: 6px; + border: 1px dashed var(--bg-slate-500); + margin-top: 16px; + + .alert-content { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; + + .heading { + display: flex; + flex-direction: column; + gap: 4px; + + .icons { + color: white; + } + + .empty-alert-action { + color: var(--bg-vanilla-400); + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 24px; /* 171.429% */ + letter-spacing: -0.07px; + } + + .empty-info { + color: var(--bg-vanilla-100); + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.07px; + } + } + + .action-container { + display: flex; + gap: 24px; + align-items: center; + padding-top: 24px; + padding-bottom: 24px; + width: 100%; + } + } + } + + .get-started-text { + display: flex; + justify-content: center; + align-items: center; + gap: 16px; + margin-top: 24px; + margin-bottom: 24px; + width: 100%; + + .ant-divider::before, + .ant-divider::after { + border-bottom: 2px dotted var(--bg-slate-300); + border-top: 2px dotted var(--bg-slate-300); + height: 8px; + } + + .ant-typography { + color: var(--bg-vanilla-400); + font-family: Inter; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 20px; /* 166.667% */ + letter-spacing: 0.48px; + text-transform: uppercase; + padding-top: 8px; + } + } + + .alert-info-card { + display: flex; + padding: 16px; + justify-content: space-between; + align-items: center; + + border-radius: 6px; + border: 1px solid var(--bg-slate-500); + background: var(--bg-ink-400); + margin-bottom: 16px; + + &:hover { + cursor: pointer; + } + + .alert-card-text { + display: flex; + gap: 2px; + flex-direction: column; + + .alert-card-text-header { + color: var(--bg-vanilla-100); + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; /* 142.857% */ + letter-spacing: -0.07px; + } + + .alert-card-text-subheader { + color: var(--bg-vanilla-400); + font-family: Inter; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 18px; /* 150% */ + } + } + } + } +} + +.info-text { + color: var(--bg-robin-400) !important; + font-family: Inter; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; /* 133.333% */ + letter-spacing: -0.06px; +} + +.info-link-container { + .anticon { + color: var(--bg-robin-400); + } + + :hover { + cursor: pointer; + } +} + +.lightMode { + .alert-list-container { + .alert-list-view-content { + .alert-list-title-container { + .title { + color: var(--bg-slate-400); + } + + .subtitle { + color: var(--bg-slate-100); + } + } + + .empty-alert-info-container { + border: 1px dashed var(--bg-vanilla-400); + + .alert-content { + .heading { + .icons { + color: white; + } + + .empty-alert-action { + color: var(--bg-slate-100); + } + + .empty-info { + color: var(--bg-slate-400); + } + } + } + } + + .get-started-text { + .ant-divider::before, + .ant-divider::after { + border-bottom: 2px dotted var(--bg-vanilla-400); + border-top: 2px dotted var(--bg-vanilla-400); + } + + .ant-typography { + color: var(--bg-slate-100); + } + } + + .alert-info-card { + border: 1px solid var(--bg-vanilla-200); + background: var(--bg-vanilla-100); + + .alert-card-text { + .alert-card-text-header { + color: var(--bg-slate-400); + } + + .alert-card-text-subheader { + color: var(--bg-slate-100); + } + } + } + } + } + + .info-text { + color: var(--bg-robin-600) !important; + } + + .info-link-container { + .anticon { + color: var(--bg-robin-400); + } + } +} diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx new file mode 100644 index 0000000000..0f388053c0 --- /dev/null +++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx @@ -0,0 +1,127 @@ +import './AlertsEmptyState.styles.scss'; + +import { PlusOutlined } from '@ant-design/icons'; +import { Button, Divider, Typography } from 'antd'; +import ROUTES from 'constants/routes'; +import useComponentPermission from 'hooks/useComponentPermission'; +import { useNotifications } from 'hooks/useNotifications'; +import history from 'lib/history'; +import { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; +import { AppState } from 'store/reducers'; +import AppReducer from 'types/reducer/app'; + +import AlertInfoCard from './AlertInfoCard'; +import { ALERT_CARDS, ALERT_INFO_LINKS } from './alertLinks'; +import InfoLinkText from './InfoLinkText'; + +export function AlertsEmptyState(): JSX.Element { + const { t } = useTranslation('common'); + const { role, featureResponse } = useSelector( + (state) => state.app, + ); + const [addNewAlert] = useComponentPermission( + ['add_new_alert', 'action'], + role, + ); + + const { notifications: notificationsApi } = useNotifications(); + + const handleError = useCallback((): void => { + notificationsApi.error({ + message: t('something_went_wrong'), + }); + }, [notificationsApi, t]); + + const [loading, setLoading] = useState(false); + + const onClickNewAlertHandler = useCallback(() => { + setLoading(true); + featureResponse + .refetch() + .then(() => { + setLoading(false); + history.push(ROUTES.ALERTS_NEW); + }) + .catch(handleError) + .finally(() => setLoading(false)); + }, [featureResponse, handleError]); + + return ( +
+
+
+ Alert Rules + + Create and manage alert rules for your resources. + +
+
+
+
+ alert-header +
+ + No Alert rules yet.{' '} + + + Create an Alert Rule to get started + +
+
+
+ + +
+ + {ALERT_INFO_LINKS.map((info) => ( + + ))} +
+
+
+ + + Or get started with these sample alerts + + +
+ + {ALERT_CARDS.map((card) => ( + + ))} +
+
+ ); +} diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx new file mode 100644 index 0000000000..1f17cd3969 --- /dev/null +++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx @@ -0,0 +1,31 @@ +import { ArrowRightOutlined, PlayCircleFilled } from '@ant-design/icons'; +import { Flex, Typography } from 'antd'; + +interface InfoLinkTextProps { + infoText: string; + link: string; + leftIconVisible: boolean; + rightIconVisible: boolean; +} + +function InfoLinkText({ + infoText, + link, + leftIconVisible, + rightIconVisible, +}: InfoLinkTextProps): JSX.Element { + return ( + { + window.open(link, '_blank'); + }} + className="info-link-container" + > + {leftIconVisible && } + {infoText} + {rightIconVisible && } + + ); +} + +export default InfoLinkText; diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts b/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts new file mode 100644 index 0000000000..fac0ad6b12 --- /dev/null +++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts @@ -0,0 +1,50 @@ +export const ALERT_INFO_LINKS = [ + { + infoText: 'How to create Metrics-based alerts', + link: + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page', + leftIconVisible: false, + rightIconVisible: true, + }, + { + infoText: 'How to create Log-based alerts', + link: + 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-empty-page', + leftIconVisible: false, + rightIconVisible: true, + }, + { + infoText: 'How to create Trace-based alerts', + link: + 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-empty-page', + leftIconVisible: false, + rightIconVisible: true, + }, +]; + +export const ALERT_CARDS = [ + { + header: 'Alert on high memory usage', + subheader: "Monitor your host's memory usage", + link: + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-memory-usage-for-host-goes-above-400-mb-or-any-fixed-memory', + }, + { + header: 'Alert on slow external API calls', + subheader: 'Monitor your external API calls', + link: + 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-external-api-latency-p90-is-over-1-second-for-last-5-mins', + }, + { + header: 'Alert on high percentage of timeout errors in logs', + subheader: 'Monitor your logs for errors', + link: + 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-percentage-of-redis-timeout-error-logs-greater-than-7-in-last-5-mins', + }, + { + header: 'Alert on high error percentage of an endpoint', + subheader: 'Monitor your API endpoint', + link: + 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page#3-alert-when-the-error-percentage-for-an-endpoint-exceeds-5', + }, +]; diff --git a/frontend/src/container/ListAlertRules/ListAlert.tsx b/frontend/src/container/ListAlertRules/ListAlert.tsx index 37a56ba921..91e0786e05 100644 --- a/frontend/src/container/ListAlertRules/ListAlert.tsx +++ b/frontend/src/container/ListAlertRules/ListAlert.tsx @@ -55,6 +55,9 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { role, ); + const [editLoader, setEditLoader] = useState(false); + const [cloneLoader, setCloneLoader] = useState(false); + const params = useUrlQuery(); const orderColumnParam = params.get('columnKey'); const orderQueryParam = params.get('order'); @@ -113,6 +116,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { }, [featureResponse, handleError]); const onEditHandler = (record: GettableAlert) => (): void => { + setEditLoader(true); featureResponse .refetch() .then(() => { @@ -129,9 +133,11 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { params.set(QueryParams.ruleId, record.id.toString()); + setEditLoader(false); history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`); }) - .catch(handleError); + .catch(handleError) + .finally(() => setEditLoader(false)); }; const onCloneHandler = ( @@ -143,33 +149,41 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { }; const apiReq = { data: copyAlert }; - const response = await saveAlertApi(apiReq); + try { + setCloneLoader(true); + const response = await saveAlertApi(apiReq); - if (response.statusCode === 200) { - notificationsApi.success({ - message: 'Success', - description: 'Alert cloned successfully', - }); + if (response.statusCode === 200) { + notificationsApi.success({ + message: 'Success', + description: 'Alert cloned successfully', + }); - const { data: refetchData, status } = await refetch(); - if (status === 'success' && refetchData.payload) { - setData(refetchData.payload || []); - setTimeout(() => { - const clonedAlert = refetchData.payload[refetchData.payload.length - 1]; - params.set(QueryParams.ruleId, String(clonedAlert.id)); - history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`); - }, 2000); - } - if (status === 'error') { + const { data: refetchData, status } = await refetch(); + if (status === 'success' && refetchData.payload) { + setData(refetchData.payload || []); + setTimeout(() => { + const clonedAlert = refetchData.payload[refetchData.payload.length - 1]; + params.set(QueryParams.ruleId, String(clonedAlert.id)); + history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`); + }, 2000); + } + if (status === 'error') { + notificationsApi.error({ + message: t('something_went_wrong'), + }); + } + } else { notificationsApi.error({ - message: t('something_went_wrong'), + message: 'Error', + description: response.error || t('something_went_wrong'), }); } - } else { - notificationsApi.error({ - message: 'Error', - description: response.error || t('something_went_wrong'), - }); + } catch (error) { + handleError(); + console.error(error); + } finally { + setCloneLoader(false); } }; @@ -314,10 +328,20 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { setData={setData} id={id} />, - + Edit , - + Clone , ; + } + // in case of loading if (isLoading || !data?.payload) { return ; diff --git a/frontend/src/container/ListAlertRules/styles.ts b/frontend/src/container/ListAlertRules/styles.ts index c0deac35de..6d89b88c53 100644 --- a/frontend/src/container/ListAlertRules/styles.ts +++ b/frontend/src/container/ListAlertRules/styles.ts @@ -27,5 +27,8 @@ export const ColumnButton = styled(ButtonComponent)` padding-left: 0; padding-right: 0; margin-right: 1.5em; + width: 100%; + display: flex; + align-items: center; } `; diff --git a/frontend/src/container/ListOfDashboard/DashboardsList.tsx b/frontend/src/container/ListOfDashboard/DashboardsList.tsx index f44b71e2bd..1c8e96b6f7 100644 --- a/frontend/src/container/ListOfDashboard/DashboardsList.tsx +++ b/frontend/src/container/ListOfDashboard/DashboardsList.tsx @@ -53,6 +53,7 @@ import { Search, } from 'lucide-react'; import { handleContactSupport } from 'pages/Integrations/utils'; +import { useDashboard } from 'providers/Dashboard/Dashboard'; import { ChangeEvent, Key, @@ -91,6 +92,11 @@ function DashboardsList(): JSX.Element { const { role } = useSelector((state) => state.app); + const { + listSortOrder: sortOrder, + setListSortOrder: setSortOrder, + } = useDashboard(); + const [action, createNewDashboard] = useComponentPermission( ['action', 'create_new_dashboards'], role, @@ -116,18 +122,9 @@ function DashboardsList(): JSX.Element { ); const params = useUrlQuery(); - const orderColumnParam = params.get('columnKey'); - const orderQueryParam = params.get('order'); - const paginationParam = params.get('page'); const searchParams = params.get('search'); const [searchString, setSearchString] = useState(searchParams || ''); - const [sortOrder, setSortOrder] = useState({ - columnKey: orderColumnParam, - order: orderQueryParam, - pagination: paginationParam, - }); - const getLocalStorageDynamicColumns = (): DashboardDynamicColumns => { const dashboardDynamicColumnsString = localStorage.getItem('dashboard'); let dashboardDynamicColumns: DashboardDynamicColumns = { @@ -198,7 +195,6 @@ function DashboardsList(): JSX.Element { }, [sortOrder]); const sortHandle = (key: string): void => { - console.log(dashboards); if (!dashboards) return; if (key === 'createdAt') { sortDashboardsByCreatedAt(dashboards); @@ -225,13 +221,29 @@ function DashboardsList(): JSX.Element { } useEffect(() => { - sortDashboardsByCreatedAt(dashboardListResponse); const filteredDashboards = filterDashboard( searchString, dashboardListResponse, ); - setDashboards(filteredDashboards || []); - }, [dashboardListResponse, searchString]); + if (sortOrder.columnKey === 'updatedAt') { + sortDashboardsByUpdatedAt(filteredDashboards || []); + } else if (sortOrder.columnKey === 'createdAt') { + sortDashboardsByCreatedAt(filteredDashboards || []); + } else if (sortOrder.columnKey === 'null') { + setSortOrder({ + columnKey: 'updatedAt', + order: 'descend', + pagination: sortOrder.pagination || '1', + }); + sortDashboardsByUpdatedAt(filteredDashboards || []); + } + }, [ + dashboardListResponse, + searchString, + setSortOrder, + sortOrder.columnKey, + sortOrder.pagination, + ]); const [newDashboardState, setNewDashboardState] = useState({ loading: false, @@ -687,7 +699,16 @@ function DashboardsList(): JSX.Element { New Dashboard - @@ -807,6 +828,7 @@ function DashboardsList(): JSX.Element { showTotal: showPaginationItem, showSizeChanger: false, onChange: (page): void => handlePageSizeUpdate(page), + current: Number(sortOrder.pagination), defaultCurrent: Number(sortOrder.pagination) || 1, } } diff --git a/frontend/src/container/LiveLogs/constants.ts b/frontend/src/container/LiveLogs/constants.ts index 83df3759ee..79d3415517 100644 --- a/frontend/src/container/LiveLogs/constants.ts +++ b/frontend/src/container/LiveLogs/constants.ts @@ -30,8 +30,8 @@ export const constructCompositeQuery = ({ }: GetDefaultCompositeQueryParams): Query => ({ ...query, builder: { - ...query.builder, - queryData: query.builder.queryData.map((item) => ({ + ...query?.builder, + queryData: query?.builder?.queryData?.map((item) => ({ ...initialQueryData, ...item, ...customQueryData, diff --git a/frontend/src/container/LiveLogs/utils.ts b/frontend/src/container/LiveLogs/utils.ts index 8e41db49e3..a7b6ffe9db 100644 --- a/frontend/src/container/LiveLogs/utils.ts +++ b/frontend/src/container/LiveLogs/utils.ts @@ -42,7 +42,7 @@ export const prepareQueryByFilter = ( ...query, builder: { ...query.builder, - queryData: query.builder.queryData.map((item) => ({ + queryData: query.builder.queryData?.map((item) => ({ ...item, filters: value ? getFilter(item.filters, tagFilter, value) : item.filters, })), @@ -57,7 +57,7 @@ export const getQueryWithoutFilterId = (query: Query): Query => { ...query, builder: { ...query.builder, - queryData: query.builder.queryData.map((item) => ({ + queryData: query.builder.queryData?.map((item) => ({ ...item, filters: { ...item.filters, diff --git a/frontend/src/container/LogDetailedView/JsonView.tsx b/frontend/src/container/LogDetailedView/JsonView.tsx index 5984cf9fd0..1f22b1a134 100644 --- a/frontend/src/container/LogDetailedView/JsonView.tsx +++ b/frontend/src/container/LogDetailedView/JsonView.tsx @@ -10,7 +10,7 @@ import { JSONViewProps } from './LogDetailedView.types'; import { aggregateAttributesResourcesToString } from './utils'; function JSONView({ logData }: JSONViewProps): JSX.Element { - const [isWrapWord, setIsWrapWord] = useState(false); + const [isWrapWord, setIsWrapWord] = useState(true); const LogJsonData = useMemo( () => aggregateAttributesResourcesToString(logData), @@ -22,7 +22,7 @@ function JSONView({ logData }: JSONViewProps): JSX.Element { const options: EditorProps['options'] = { automaticLayout: true, readOnly: true, - wordWrap: 'on', + wordWrap: isWrapWord ? 'on' : 'off', minimap: { enabled: false, }, @@ -68,7 +68,7 @@ function JSONView({ logData }: JSONViewProps): JSX.Element { return (
{}} diff --git a/frontend/src/container/LogDetailedView/Overview.tsx b/frontend/src/container/LogDetailedView/Overview.tsx index ff2a22fa09..957aac5bf7 100644 --- a/frontend/src/container/LogDetailedView/Overview.tsx +++ b/frontend/src/container/LogDetailedView/Overview.tsx @@ -35,7 +35,7 @@ function Overview({ onClickActionItem, isListViewPanel = false, }: Props): JSX.Element { - const [isWrapWord, setIsWrapWord] = useState(false); + const [isWrapWord, setIsWrapWord] = useState(true); const [isSearchVisible, setIsSearchVisible] = useState(false); const [isAttributesExpanded, setIsAttributesExpanded] = useState( true, @@ -48,7 +48,7 @@ function Overview({ automaticLayout: true, readOnly: true, height: '40vh', - wordWrap: 'on', + wordWrap: isWrapWord ? 'on' : 'off', minimap: { enabled: false, }, @@ -118,8 +118,8 @@ function Overview({ children: (
{}} height="20vh" @@ -143,7 +143,7 @@ function Overview({
), - extra: {isWrapWord ? 'Raw' : 'JSON'}, + // extra: JSON, className: 'collapse-content', }, ]} diff --git a/frontend/src/container/LogExplorerQuerySection/index.tsx b/frontend/src/container/LogExplorerQuerySection/index.tsx index 39b027a51d..1eea60da47 100644 --- a/frontend/src/container/LogExplorerQuerySection/index.tsx +++ b/frontend/src/container/LogExplorerQuerySection/index.tsx @@ -47,7 +47,7 @@ function LogExplorerQuerySection({ const isTable = panelTypes === PANEL_TYPES.TABLE; const isList = panelTypes === PANEL_TYPES.LIST; const config: QueryBuilderProps['filterConfigs'] = { - stepInterval: { isHidden: isTable, isDisabled: true }, + stepInterval: { isHidden: isTable, isDisabled: false }, having: { isHidden: isList, isDisabled: true }, filters: { customKey: 'body', diff --git a/frontend/src/container/LogsContextList/utils.ts b/frontend/src/container/LogsContextList/utils.ts index 2b1b903fa9..8e06d64ecc 100644 --- a/frontend/src/container/LogsContextList/utils.ts +++ b/frontend/src/container/LogsContextList/utils.ts @@ -40,7 +40,7 @@ export const getRequestData = ({ ...query, builder: { ...query.builder, - queryData: query.builder.queryData.map((item) => ({ + queryData: query.builder.queryData?.map((item) => ({ ...item, ...paginateData, pageSize, diff --git a/frontend/src/container/LogsExplorerViews/index.tsx b/frontend/src/container/LogsExplorerViews/index.tsx index 28e199066a..ced6556f44 100644 --- a/frontend/src/container/LogsExplorerViews/index.tsx +++ b/frontend/src/container/LogsExplorerViews/index.tsx @@ -37,7 +37,7 @@ import { useNotifications } from 'hooks/useNotifications'; import useUrlQueryData from 'hooks/useUrlQueryData'; import { FlatLogData } from 'lib/logs/flatLogData'; import { getPaginationQueryData } from 'lib/newQueryBuilder/getPaginationQueryData'; -import { defaultTo, isEmpty, omit } from 'lodash-es'; +import { cloneDeep, defaultTo, isEmpty, omit, set } from 'lodash-es'; import { Sliders } from 'lucide-react'; import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; @@ -117,6 +117,12 @@ function LogsExplorerViews({ return stagedQuery.builder.queryData.find((item) => !item.disabled) || null; }, [stagedQuery]); + const { options, config } = useOptionsMenu({ + storageKey: LOCALSTORAGE.LOGS_LIST_OPTIONS, + dataSource: initialDataSource || DataSource.LOGS, + aggregateOperator: listQuery?.aggregateOperator || StringOperators.NOOP, + }); + const orderByTimestamp: OrderByPayload | null = useMemo(() => { const timestampOrderBy = listQuery?.orderBy.find( (item) => item.columnName === 'timestamp', @@ -174,10 +180,10 @@ function LogsExplorerViews({ () => updateAllQueriesOperators( currentQuery || initialQueriesMap.logs, - PANEL_TYPES.TIME_SERIES, + selectedPanelType, DataSource.LOGS, ), - [currentQuery, updateAllQueriesOperators], + [currentQuery, selectedPanelType, updateAllQueriesOperators], ); const handleModeChange = (panelType: PANEL_TYPES): void => { @@ -309,6 +315,14 @@ function LogsExplorerViews({ isLoading: isUpdateDashboardLoading, } = useUpdateDashboard(); + const getUpdatedQueryForExport = useCallback((): Query => { + const updatedQuery = cloneDeep(currentQuery); + + set(updatedQuery, 'builder.queryData[0].pageSize', 10); + + return updatedQuery; + }, [currentQuery]); + const handleExport = useCallback( (dashboard: Dashboard | null): void => { if (!dashboard || !panelType) return; @@ -319,11 +333,17 @@ function LogsExplorerViews({ const widgetId = v4(); + const query = + panelType === PANEL_TYPES.LIST + ? getUpdatedQueryForExport() + : exportDefaultQuery; + const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( dashboard, - exportDefaultQuery, + query, widgetId, panelTypeParam, + options.selectColumns, ); updateDashboard(updatedDashboard, { @@ -353,7 +373,7 @@ function LogsExplorerViews({ } const dashboardEditView = generateExportToDashboardLink({ - query: exportDefaultQuery, + query, panelType: panelTypeParam, dashboardId: data.payload?.uuid || '', widgetId, @@ -365,7 +385,9 @@ function LogsExplorerViews({ }); }, [ + getUpdatedQueryForExport, exportDefaultQuery, + options.selectColumns, history, notifications, panelType, @@ -460,12 +482,6 @@ function LogsExplorerViews({ selectedView, ]); - const { options, config } = useOptionsMenu({ - storageKey: LOCALSTORAGE.LOGS_LIST_OPTIONS, - dataSource: initialDataSource || DataSource.METRICS, - aggregateOperator: listQuery?.aggregateOperator || StringOperators.NOOP, - }); - const chartData = useMemo(() => { if (!stagedQuery) return []; diff --git a/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss b/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss index 5fa4ce0cda..6317ea2134 100644 --- a/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss +++ b/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss @@ -5,7 +5,7 @@ height: 100%; .resize-table { - height: calc(100% - 40px); + height: calc(100% - 70px); overflow: scroll; overflow-x: hidden; diff --git a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx index 54c2115927..d45476b6f4 100644 --- a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx @@ -27,6 +27,7 @@ import { handleNonInQueryRange, onGraphClickHandler, onViewTracePopupClick, + useGetAPMToTracesQueries, } from './util'; function DBCall(): JSX.Element { @@ -96,6 +97,11 @@ function DBCall(): JSX.Element { [servicename, tagFilterItems], ); + const apmToTraceQuery = useGetAPMToTracesQueries({ + servicename, + isDBCall: true, + }); + return ( @@ -107,6 +113,7 @@ function DBCall(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, + apmToTraceQuery, })} > View Traces @@ -139,6 +146,7 @@ function DBCall(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, + apmToTraceQuery, })} > View Traces diff --git a/frontend/src/container/MetricsApplication/Tabs/External.tsx b/frontend/src/container/MetricsApplication/Tabs/External.tsx index 62ce71b6b4..ff0bc1f682 100644 --- a/frontend/src/container/MetricsApplication/Tabs/External.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/External.tsx @@ -27,6 +27,7 @@ import { handleNonInQueryRange, onGraphClickHandler, onViewTracePopupClick, + useGetAPMToTracesQueries, } from './util'; function External(): JSX.Element { @@ -138,6 +139,11 @@ function External(): JSX.Element { [servicename, tagFilterItems], ); + const apmToTraceQuery = useGetAPMToTracesQueries({ + servicename, + isExternalCall: true, + }); + return ( <> @@ -150,7 +156,7 @@ function External(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, - isExternalCall: true, + apmToTraceQuery, })} > View Traces @@ -184,7 +190,7 @@ function External(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, - isExternalCall: true, + apmToTraceQuery, })} > View Traces @@ -221,7 +227,7 @@ function External(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, - isExternalCall: true, + apmToTraceQuery, })} > View Traces @@ -255,7 +261,7 @@ function External(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, - isExternalCall: true, + apmToTraceQuery, })} > View Traces diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx index cfaf339d2e..7410e4ccb3 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx @@ -22,6 +22,8 @@ import { useQuery } from 'react-query'; import { useDispatch } from 'react-redux'; import { useLocation, useParams } from 'react-router-dom'; import { UpdateTimeInterval } from 'store/actions'; +import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { EQueryType } from 'types/common/dashboard'; import { v4 as uuid } from 'uuid'; @@ -43,6 +45,7 @@ import { handleNonInQueryRange, onGraphClickHandler, onViewTracePopupClick, + useGetAPMToTracesQueries, } from './util'; function Application(): JSX.Element { @@ -92,6 +95,8 @@ function Application(): JSX.Element { convertRawQueriesToTraceSelectedTags(queries) || [], ); + const apmToTraceQuery = useGetAPMToTracesQueries({ servicename }); + const tagFilterItems = useMemo( () => handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [], @@ -159,7 +164,10 @@ function Application(): JSX.Element { [dispatch, pathname, urlQuery], ); - const onErrorTrackHandler = (timestamp: number): (() => void) => (): void => { + const onErrorTrackHandler = ( + timestamp: number, + apmToTraceQuery: Query, + ): (() => void) => (): void => { const currentTime = timestamp; const tPlusOne = timestamp + 60 * 1000; @@ -170,15 +178,38 @@ function Application(): JSX.Element { const avialableParams = routeConfig[ROUTES.TRACE]; const queryString = getQueryString(avialableParams, urlParams); - history.replace( - `${ - ROUTES.TRACE - }?selected={"serviceName":["${servicename}"],"status":["error"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&isFilterExclude={"serviceName":false,"status":false}&userSelectedFilter={"serviceName":["${servicename}"],"status":["error"]}&spanAggregateCurrentPage=1&${queryString.join( - '', - )}`, + const JSONCompositeQuery = encodeURIComponent( + JSON.stringify(apmToTraceQuery), ); + + const newTraceExplorerPath = `${ + ROUTES.TRACES_EXPLORER + }?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${ + QueryParams.compositeQuery + }=${JSONCompositeQuery}&${queryString.join('&')}`; + + history.push(newTraceExplorerPath); }; + const errorTrackQuery = useGetAPMToTracesQueries({ + servicename, + filters: [ + { + id: uuid().slice(0, 8), + key: { + key: 'hasError', + dataType: DataTypes.bool, + type: 'tag', + isColumn: true, + isJSON: false, + id: 'hasError--bool--tag--true', + }, + op: 'in', + value: ['true'], + }, + ], + }); + return ( <> @@ -202,6 +233,7 @@ function Application(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, + apmToTraceQuery, })} > View Traces @@ -229,6 +261,7 @@ function Application(): JSX.Element { servicename, selectedTraceTags, timestamp: selectedTimeStamp, + apmToTraceQuery, })} > View Traces @@ -245,7 +278,7 @@ function Application(): JSX.Element { type="default" size="small" id="Error_button" - onClick={onErrorTrackHandler(selectedTimeStamp)} + onClick={onErrorTrackHandler(selectedTimeStamp, errorTrackQuery)} > View Traces diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx index 4007c152ef..9651e16d3a 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx @@ -21,7 +21,11 @@ import { v4 as uuid } from 'uuid'; import { Button } from '../styles'; import { IServiceName } from '../types'; -import { handleNonInQueryRange, onViewTracePopupClick } from '../util'; +import { + handleNonInQueryRange, + onViewTracePopupClick, + useGetAPMToTracesQueries, +} from '../util'; function ServiceOverview({ onDragSelect, @@ -69,6 +73,8 @@ function ServiceOverview({ const isQueryEnabled = !topLevelOperationsIsLoading && topLevelOperationsRoute.length > 0; + const apmToTraceQuery = useGetAPMToTracesQueries({ servicename }); + return ( <> @@ -297,7 +303,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element { buttonText="Facing issues with dashboards?" onHoverText="Click here to get help with dashboard details" /> - +
{ let numberOfUnsavedChanges = 0; - if (!isEqual(updatedTitle, selectedData?.title)) { - numberOfUnsavedChanges += 1; - } - if (!isEqual(updatedDescription, selectedData?.description)) { - numberOfUnsavedChanges += 1; - } - if (!isEqual(updatedTags, selectedData?.tags)) { - numberOfUnsavedChanges += 1; - } - if (!isEqual(updatedImage, selectedData?.image)) { - numberOfUnsavedChanges += 1; - } + const initialValues = [title, description, tags, image]; + const updatedValues = [ + updatedTitle, + updatedDescription, + updatedTags, + updatedImage, + ]; + initialValues.forEach((val, index) => { + if (!isEqual(val, updatedValues[index])) { + numberOfUnsavedChanges += 1; + } + }); setNumberOfUnsavedChanges(numberOfUnsavedChanges); }, [ - selectedData?.description, - selectedData?.image, - selectedData?.tags, - selectedData?.title, + description, + image, + tags, + title, updatedDescription, updatedImage, updatedTags, @@ -167,7 +167,8 @@ function GeneralDashboardSettings(): JSX.Element {
- {numberOfUnsavedChanges} Unsaved change + {numberOfUnsavedChanges} unsaved change + {numberOfUnsavedChanges > 1 && 's'}
diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss index f610198f4a..f7fcb83a53 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss @@ -40,12 +40,46 @@ } .variable-select { - .ant-select-dropdown { - max-width: 300px; + .ant-select-item { + display: flex; + align-items: center; + } + + .all-label { + display: flex; + gap: 16px; + } + + .dropdown-checkbox-label { + display: grid; + grid-template-columns: 24px 1fr; + } + + .dropdown-value { + display: flex; + justify-content: space-between; + align-items: center; + + .option-text { + max-width: 180px; + padding: 0 8px; + } + + .toggle-tag-label { + padding-left: 8px; + right: 40px; + font-weight: normal; + position: absolute; + } } } } +.dropdown-styles { + min-width: 300px; + max-width: 350px; +} + .lightMode { .variable-item { .variable-name { diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx index 0572196fbf..813185e0b6 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx @@ -138,6 +138,7 @@ function DashboardVariableSelection(): JSX.Element | null { }} onValueUpdate={onValueUpdate} variablesToGetUpdated={variablesToGetUpdated} + setVariablesToGetUpdated={setVariablesToGetUpdated} /> ))} diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx index cd8b23ea46..0c8fbd51ae 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx @@ -54,6 +54,7 @@ describe('VariableItem', () => { existingVariables={{}} onValueUpdate={mockOnValueUpdate} variablesToGetUpdated={[]} + setVariablesToGetUpdated={(): void => {}} /> , ); @@ -69,6 +70,7 @@ describe('VariableItem', () => { existingVariables={{}} onValueUpdate={mockOnValueUpdate} variablesToGetUpdated={[]} + setVariablesToGetUpdated={(): void => {}} /> , ); @@ -83,6 +85,7 @@ describe('VariableItem', () => { existingVariables={{}} onValueUpdate={mockOnValueUpdate} variablesToGetUpdated={[]} + setVariablesToGetUpdated={(): void => {}} /> , ); @@ -111,6 +114,7 @@ describe('VariableItem', () => { existingVariables={{}} onValueUpdate={mockOnValueUpdate} variablesToGetUpdated={[]} + setVariablesToGetUpdated={(): void => {}} /> , ); @@ -123,6 +127,8 @@ describe('VariableItem', () => { const customVariableData = { ...mockCustomVariableData, allSelected: true, + showALLOption: true, + multiSelect: true, }; render( @@ -132,6 +138,7 @@ describe('VariableItem', () => { existingVariables={{}} onValueUpdate={mockOnValueUpdate} variablesToGetUpdated={[]} + setVariablesToGetUpdated={(): void => {}} /> , ); @@ -147,6 +154,7 @@ describe('VariableItem', () => { existingVariables={{}} onValueUpdate={mockOnValueUpdate} variablesToGetUpdated={[]} + setVariablesToGetUpdated={(): void => {}} /> , ); diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx index 2a14aa19e5..baa8228b3c 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx @@ -1,15 +1,29 @@ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable react/jsx-props-no-spreading */ +/* eslint-disable no-nested-ternary */ import './DashboardVariableSelection.styles.scss'; import { orange } from '@ant-design/colors'; import { WarningOutlined } from '@ant-design/icons'; -import { Input, Popover, Select, Typography } from 'antd'; +import { + Checkbox, + Input, + Popover, + Select, + Tag, + Tooltip, + Typography, +} from 'antd'; +import { CheckboxChangeEvent } from 'antd/es/checkbox'; import dashboardVariablesQuery from 'api/dashboard/variables/dashboardVariablesQuery'; import { REACT_QUERY_KEY } from 'constants/reactQueryKeys'; import { commaValuesParser } from 'lib/dashbaordVariables/customCommaValuesParser'; import sortValues from 'lib/dashbaordVariables/sortVariableValues'; import { debounce, isArray, isString } from 'lodash-es'; import map from 'lodash-es/map'; -import { memo, useEffect, useMemo, useState } from 'react'; +import { ChangeEvent, memo, useEffect, useMemo, useState } from 'react'; import { useQuery } from 'react-query'; import { IDashboardVariable } from 'types/api/dashboard/getAll'; import { VariableResponseProps } from 'types/api/dashboard/variables/query'; @@ -23,6 +37,11 @@ const ALL_SELECT_VALUE = '__ALL__'; const variableRegexPattern = /\{\{\s*?\.([^\s}]+)\s*?\}\}/g; +enum ToggleTagValue { + Only = 'Only', + All = 'All', +} + interface VariableItemProps { variableData: IDashboardVariable; existingVariables: Record; @@ -33,12 +52,17 @@ interface VariableItemProps { allSelected: boolean, ) => void; variablesToGetUpdated: string[]; + setVariablesToGetUpdated: React.Dispatch>; } const getSelectValue = ( selectedValue: IDashboardVariable['selectedValue'], + variableData: IDashboardVariable, ): string | string[] => { if (Array.isArray(selectedValue)) { + if (!variableData.multiSelect && selectedValue.length === 1) { + return selectedValue[0]?.toString() || ''; + } return selectedValue.map((item) => item.toString()); } return selectedValue?.toString() || ''; @@ -50,6 +74,7 @@ function VariableItem({ existingVariables, onValueUpdate, variablesToGetUpdated, + setVariablesToGetUpdated, }: VariableItemProps): JSX.Element { const [optionsData, setOptionsData] = useState<(string | number | boolean)[]>( [], @@ -148,6 +173,10 @@ function VariableItem({ } setOptionsData(newOptionsData); + } else { + setVariablesToGetUpdated((prev) => + prev.filter((name) => name !== variableData.name), + ); } } } catch (e) { @@ -193,7 +222,7 @@ function VariableItem({ }); const handleChange = (value: string | string[]): void => { - if (variableData.name) + if (variableData.name) { if ( value === ALL_SELECT_VALUE || (Array.isArray(value) && value.includes(ALL_SELECT_VALUE)) || @@ -203,25 +232,29 @@ function VariableItem({ } else { onValueUpdate(variableData.name, variableData.id, value, false); } + } }; // do not debounce the above function as we do not need debounce in select variables const debouncedHandleChange = debounce(handleChange, 500); const { selectedValue } = variableData; - const selectedValueStringified = useMemo(() => getSelectValue(selectedValue), [ - selectedValue, - ]); + const selectedValueStringified = useMemo( + () => getSelectValue(selectedValue, variableData), + [selectedValue, variableData], + ); - const selectValue = variableData.allSelected - ? 'ALL' - : selectedValueStringified; + const enableSelectAll = variableData.multiSelect && variableData.showALLOption; - const mode = + const selectValue = + variableData.allSelected && enableSelectAll + ? 'ALL' + : selectedValueStringified; + + const mode: 'multiple' | undefined = variableData.multiSelect && !variableData.allSelected ? 'multiple' : undefined; - const enableSelectAll = variableData.multiSelect && variableData.showALLOption; useEffect(() => { // Fetch options for CUSTOM Type @@ -231,6 +264,117 @@ function VariableItem({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [variableData.type, variableData.customValue]); + const checkAll = (e: MouseEvent): void => { + e.stopPropagation(); + e.preventDefault(); + const isChecked = + variableData.allSelected || selectValue.includes(ALL_SELECT_VALUE); + + if (isChecked) { + handleChange([]); + } else { + handleChange(ALL_SELECT_VALUE); + } + }; + + const handleOptionSelect = ( + e: CheckboxChangeEvent, + option: string | number | boolean, + ): void => { + const newSelectedValue = Array.isArray(selectedValue) + ? ((selectedValue.filter( + (val) => val.toString() !== option.toString(), + ) as unknown) as string[]) + : []; + + if ( + !e.target.checked && + Array.isArray(selectedValueStringified) && + selectedValueStringified.includes(option.toString()) + ) { + if (newSelectedValue.length === 0) { + handleChange(ALL_SELECT_VALUE); + return; + } + if (newSelectedValue.length === 1) { + handleChange(newSelectedValue[0].toString()); + return; + } + handleChange(newSelectedValue); + } else if (!e.target.checked && selectedValue === option.toString()) { + handleChange(ALL_SELECT_VALUE); + } else if (newSelectedValue.length === optionsData.length - 1) { + handleChange(ALL_SELECT_VALUE); + } + }; + + const [optionState, setOptionState] = useState({ + tag: '', + visible: false, + }); + + function currentToggleTagValue({ + option, + }: { + option: string; + }): ToggleTagValue { + if ( + option.toString() === selectValue || + (Array.isArray(selectValue) && + selectValue?.includes(option.toString()) && + selectValue.length === 1) + ) { + return ToggleTagValue.All; + } + return ToggleTagValue.Only; + } + + function handleToggle(e: ChangeEvent, option: string): void { + e.stopPropagation(); + const mode = currentToggleTagValue({ option: option as string }); + const isChecked = + variableData.allSelected || + option.toString() === selectValue || + (Array.isArray(selectValue) && selectValue?.includes(option.toString())); + + if (isChecked) { + if (mode === ToggleTagValue.Only) { + handleChange(option.toString()); + } else if (!variableData.multiSelect) { + handleChange(option.toString()); + } else { + handleChange(ALL_SELECT_VALUE); + } + } else { + handleChange(option.toString()); + } + } + + function retProps( + option: string, + ): { + onMouseOver: () => void; + onMouseOut: () => void; + } { + return { + onMouseOver: (): void => + setOptionState({ + tag: option.toString(), + visible: true, + }), + onMouseOut: (): void => + setOptionState({ + tag: option.toString(), + visible: false, + }), + }; + } + + const ensureValidOption = (option: string): boolean => + !( + currentToggleTagValue({ option }) === ToggleTagValue.All && !enableSelectAll + ); + return (
@@ -264,19 +408,35 @@ function VariableItem({ onChange={handleChange} bordered={false} placeholder="Select value" - placement="bottomRight" + placement="bottomLeft" mode={mode} - dropdownMatchSelectWidth={false} style={SelectItemStyle} loading={isLoading} showSearch data-testid="variable-select" className="variable-select" + popupClassName="dropdown-styles" + maxTagCount={4} getPopupContainer={popupContainer} + // eslint-disable-next-line react/no-unstable-nested-components + tagRender={(props): JSX.Element => ( + + {props.value} + + )} + // eslint-disable-next-line react/no-unstable-nested-components + maxTagPlaceholder={(omittedValues): JSX.Element => ( + value).join(', ')}> + + {omittedValues.length} + + )} > {enableSelectAll && ( - ALL +
checkAll(e as any)}> + + ALL +
)} {map(optionsData, (option) => ( @@ -285,7 +445,45 @@ function VariableItem({ key={option.toString()} value={option} > - {option.toString()} +
+ {variableData.multiSelect && ( + { + e.stopPropagation(); + e.preventDefault(); + handleOptionSelect(e, option); + }} + checked={ + variableData.allSelected || + option.toString() === selectValue || + (Array.isArray(selectValue) && + selectValue?.includes(option.toString())) + } + /> + )} +
handleToggle(e as any, option as string)} + > + + + {option.toString()} + + + + {variableData.multiSelect && + optionState.tag === option.toString() && + optionState.visible && + ensureValidOption(option as string) && ( + + {currentToggleTagValue({ option: option as string })} + + )} +
+
))} diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts b/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts index 5c5de3e97e..02530dbd0f 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts @@ -42,4 +42,5 @@ export const VariableValue = styled(Typography)` export const SelectItemStyle = { minWidth: 120, fontSize: '0.8rem', + width: '100%', }; diff --git a/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx b/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx index beed344d8b..3f6deab6f8 100644 --- a/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx @@ -12,7 +12,6 @@ import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interface import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; -import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval'; import { useIsDarkMode } from 'hooks/useDarkMode'; import useUrlQuery from 'hooks/useUrlQuery'; import { defaultTo } from 'lodash-es'; @@ -33,7 +32,6 @@ import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { EQueryType } from 'types/common/dashboard'; import AppReducer from 'types/reducer/app'; -import { GlobalReducer } from 'types/reducer/globalTime'; import ClickHouseQueryContainer from './QueryBuilder/clickHouse'; import PromQLQueryContainer from './QueryBuilder/promQL'; @@ -46,10 +44,6 @@ function QuerySection({ const urlQuery = useUrlQuery(); const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys(); - const { minTime, maxTime } = useSelector( - (state) => state.globalTime, - ); - const { featureResponse } = useSelector( (state) => state.app, ); @@ -80,8 +74,6 @@ function QuerySection({ return; } - const updatedQuery = updateStepInterval(query, maxTime, minTime); - const selectedWidgetIndex = getSelectedWidgetIndex( selectedDashboard, selectedWidget.id, @@ -102,18 +94,16 @@ function QuerySection({ ...previousWidgets, { ...selectedWidget, - query: updatedQuery, + query, }, ...nextWidgets, ], }, }); - redirectWithQueryBuilderData(updatedQuery); + redirectWithQueryBuilderData(query); }, [ selectedDashboard, - maxTime, - minTime, selectedWidget, setSelectedDashboard, redirectWithQueryBuilderData, @@ -137,7 +127,7 @@ function QuerySection({ const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => { const config: QueryBuilderProps['filterConfigs'] = { - stepInterval: { isHidden: false, isDisabled: true }, + stepInterval: { isHidden: false, isDisabled: false }, }; return config; diff --git a/frontend/src/container/NewWidget/LeftContainer/index.tsx b/frontend/src/container/NewWidget/LeftContainer/index.tsx index e7c149c246..0363b4c6f8 100644 --- a/frontend/src/container/NewWidget/LeftContainer/index.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/index.tsx @@ -72,10 +72,16 @@ function LeftContainer({ globalSelectedInterval, graphType: getGraphType(selectedGraph || selectedWidget.panelTypes), query: stagedQuery, + fillGaps: selectedWidget.fillSpans || false, })); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [stagedQuery, selectedTime, globalSelectedInterval]); + }, [ + stagedQuery, + selectedTime, + selectedWidget.fillSpans, + globalSelectedInterval, + ]); const queryResponse = useGetQueryRange( requestData, diff --git a/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx b/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx index 6eff73fdf6..8ed4c898a7 100644 --- a/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx +++ b/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx @@ -4,6 +4,7 @@ import { Typography } from 'antd'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { Dispatch, SetStateAction } from 'react'; import { ColumnUnit } from 'types/api/dashboard/getAll'; +import { EQueryType } from 'types/common/dashboard'; import YAxisUnitSelector from '../YAxisUnitSelector'; @@ -18,7 +19,13 @@ export function ColumnUnitSelector( const { currentQuery } = useQueryBuilder(); function getAggregateColumnsNamesAndLabels(): string[] { - return currentQuery.builder.queryData.map((q) => q.queryName); + if (currentQuery.queryType === EQueryType.QUERY_BUILDER) { + return currentQuery.builder.queryData.map((q) => q.queryName); + } + if (currentQuery.queryType === EQueryType.CLICKHOUSE) { + return currentQuery.clickhouse_sql.map((q) => q.name); + } + return currentQuery.promql.map((q) => q.name); } const { columnUnits, setColumnUnits } = props; diff --git a/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss b/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss index ebcbbedbbc..55d717926a 100644 --- a/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss +++ b/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss @@ -241,6 +241,24 @@ } } + .stack-chart { + margin-top: 16px; + display: flex; + justify-content: space-between; + gap: 8px; + + .label { + color: var(--bg-vanilla-400); + font-family: 'Space Mono'; + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 18px; /* 138.462% */ + letter-spacing: 0.52px; + text-transform: uppercase; + } + } + .bucket-config { margin-top: 16px; display: flex; @@ -411,6 +429,21 @@ } } + .bucket-config { + .label { + color: var(--bg-ink-400); + } + + .bucket-input { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-300); + + .ant-input { + background: var(--bg-vanilla-300); + } + } + } + .panel-time-text { color: var(--bg-ink-400); } diff --git a/frontend/src/container/NewWidget/RightContainer/constants.ts b/frontend/src/container/NewWidget/RightContainer/constants.ts index 5276fc2bcd..171f6b81d3 100644 --- a/frontend/src/container/NewWidget/RightContainer/constants.ts +++ b/frontend/src/container/NewWidget/RightContainer/constants.ts @@ -132,3 +132,17 @@ export const panelTypeVsColumnUnitPreferences: { [PANEL_TYPES.HISTOGRAM]: false, [PANEL_TYPES.EMPTY_WIDGET]: false, } as const; + +export const panelTypeVsStackingChartPreferences: { + [key in PANEL_TYPES]: boolean; +} = { + [PANEL_TYPES.TIME_SERIES]: false, + [PANEL_TYPES.VALUE]: false, + [PANEL_TYPES.TABLE]: false, + [PANEL_TYPES.LIST]: false, + [PANEL_TYPES.PIE]: false, + [PANEL_TYPES.BAR]: true, + [PANEL_TYPES.TRACE]: false, + [PANEL_TYPES.HISTOGRAM]: false, + [PANEL_TYPES.EMPTY_WIDGET]: false, +} as const; diff --git a/frontend/src/container/NewWidget/RightContainer/index.tsx b/frontend/src/container/NewWidget/RightContainer/index.tsx index f615d37829..08387cd069 100644 --- a/frontend/src/container/NewWidget/RightContainer/index.tsx +++ b/frontend/src/container/NewWidget/RightContainer/index.tsx @@ -29,6 +29,7 @@ import { panelTypeVsFillSpan, panelTypeVsPanelTimePreferences, panelTypeVsSoftMinMax, + panelTypeVsStackingChartPreferences, panelTypeVsThreshold, panelTypeVsYAxisUnit, } from './constants'; @@ -48,6 +49,8 @@ function RightContainer({ selectedGraph, bucketCount, bucketWidth, + stackedBarChart, + setStackedBarChart, setBucketCount, setBucketWidth, setSelectedTime, @@ -87,6 +90,8 @@ function RightContainer({ const allowYAxisUnit = panelTypeVsYAxisUnit[selectedGraph]; const allowCreateAlerts = panelTypeVsCreateAlert[selectedGraph]; const allowBucketConfig = panelTypeVsBucketConfig[selectedGraph]; + const allowStackingBarChart = + panelTypeVsStackingChartPreferences[selectedGraph]; const allowPanelTimePreference = panelTypeVsPanelTimePreferences[selectedGraph]; @@ -231,6 +236,17 @@ function RightContainer({
)} + {allowStackingBarChart && ( +
+ Stack series + setStackedBarChart(checked)} + /> +
+ )} + {allowBucketConfig && (
Number of buckets @@ -312,6 +328,8 @@ interface RightContainerProps { setSelectedTime: Dispatch>; selectedTime: timePreferance; yAxisUnit: string; + stackedBarChart: boolean; + setStackedBarChart: Dispatch>; bucketWidth: number; bucketCount: number; combineHistogram: boolean; diff --git a/frontend/src/container/NewWidget/index.tsx b/frontend/src/container/NewWidget/index.tsx index bc7f5bf1fd..79c9cb9028 100644 --- a/frontend/src/container/NewWidget/index.tsx +++ b/frontend/src/container/NewWidget/index.tsx @@ -126,6 +126,10 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { const [stacked, setStacked] = useState( selectedWidget?.isStacked || false, ); + + const [stackedBarChart, setStackedBarChart] = useState( + selectedWidget?.stackedBarChart || false, + ); const [opacity, setOpacity] = useState(selectedWidget?.opacity || '1'); const [thresholds, setThresholds] = useState( selectedWidget?.thresholds || [], @@ -195,6 +199,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { fillSpans: isFillSpans, columnUnits, bucketCount, + stackedBarChart, bucketWidth, mergeAllActiveQueries: combineHistogram, selectedLogFields, @@ -219,6 +224,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { bucketWidth, bucketCount, combineHistogram, + stackedBarChart, ]); const closeModal = (): void => { @@ -307,6 +313,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { opacity: selectedWidget?.opacity || '1', nullZeroValues: selectedWidget?.nullZeroValues || 'zero', title: selectedWidget?.title, + stackedBarChart: selectedWidget?.stackedBarChart || false, yAxisUnit: selectedWidget?.yAxisUnit, panelTypes: graphType, query: currentQuery, @@ -332,6 +339,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { opacity: selectedWidget?.opacity || '1', nullZeroValues: selectedWidget?.nullZeroValues || 'zero', title: selectedWidget?.title, + stackedBarChart: selectedWidget?.stackedBarChart || false, yAxisUnit: selectedWidget?.yAxisUnit, panelTypes: graphType, query: currentQuery, @@ -532,6 +540,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { setDescription={setDescription} stacked={stacked} setStacked={setStacked} + stackedBarChart={stackedBarChart} + setStackedBarChart={setStackedBarChart} opacity={opacity} yAxisUnit={yAxisUnit} columnUnits={columnUnits} diff --git a/frontend/src/container/NewWidget/styles.ts b/frontend/src/container/NewWidget/styles.ts index 54a01817b4..6b52d1fee1 100644 --- a/frontend/src/container/NewWidget/styles.ts +++ b/frontend/src/container/NewWidget/styles.ts @@ -10,10 +10,9 @@ export const Container = styled.div` export const RightContainerWrapper = styled(Col)` &&& { - min-width: 330px; - overflow-y: auto; max-width: 400px; width: 30%; + overflow-y: auto; } &::-webkit-scrollbar { width: 0rem; @@ -26,7 +25,7 @@ interface LeftContainerWrapperProps { export const LeftContainerWrapper = styled(Col)` &&& { - min-width: 70%; + width: 100%; overflow-y: auto; border-right: ${({ isDarkMode }): string => isDarkMode diff --git a/frontend/src/container/NewWidget/utils.ts b/frontend/src/container/NewWidget/utils.ts index a8ac095d1e..b840d6e71a 100644 --- a/frontend/src/container/NewWidget/utils.ts +++ b/frontend/src/container/NewWidget/utils.ts @@ -189,50 +189,6 @@ export const panelTypeDataSourceFormValuesMap: Record< }, }, }, - [PANEL_TYPES.HISTOGRAM]: { - [DataSource.LOGS]: { - builder: { - queryData: [ - 'filters', - 'aggregateOperator', - 'aggregateAttribute', - 'groupBy', - 'limit', - 'having', - 'orderBy', - 'functions', - ], - }, - }, - [DataSource.METRICS]: { - builder: { - queryData: [ - 'filters', - 'aggregateOperator', - 'aggregateAttribute', - 'groupBy', - 'limit', - 'having', - 'orderBy', - 'functions', - 'spaceAggregation', - ], - }, - }, - [DataSource.TRACES]: { - builder: { - queryData: [ - 'filters', - 'aggregateOperator', - 'aggregateAttribute', - 'groupBy', - 'limit', - 'having', - 'orderBy', - ], - }, - }, - }, [PANEL_TYPES.TABLE]: { [DataSource.LOGS]: { builder: { diff --git a/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx b/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx index bfe6db81cd..a176247781 100644 --- a/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx +++ b/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx @@ -60,7 +60,7 @@ function PiePanelWrapper({ d.series?.length === 1 ? getLabel(Object.values(s.labels)[0], widget.query, d.queryName) : getLabel(Object.values(s.labels)[0], {} as Query, d.queryName, true), - themeColors.chartcolors, + isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor, ), })), ) diff --git a/frontend/src/container/PanelWrapper/UplotPanelWrapper.styles.scss b/frontend/src/container/PanelWrapper/UplotPanelWrapper.styles.scss new file mode 100644 index 0000000000..a1ab2e3c9e --- /dev/null +++ b/frontend/src/container/PanelWrapper/UplotPanelWrapper.styles.scss @@ -0,0 +1,4 @@ +.info-text { + margin-top: 8px; + padding: 8px; +} diff --git a/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx b/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx index f95d5772af..dc404adabb 100644 --- a/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx +++ b/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx @@ -1,3 +1,6 @@ +import './UplotPanelWrapper.styles.scss'; + +import { Alert } from 'antd'; import { ToggleGraphProps } from 'components/Graph/types'; import Uplot from 'components/Uplot'; import { PANEL_TYPES } from 'constants/queryBuilder'; @@ -8,6 +11,7 @@ import { useIsDarkMode } from 'hooks/useDarkMode'; import { useResizeObserver } from 'hooks/useDimensions'; import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions'; import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData'; +import { cloneDeep, isEqual, isUndefined } from 'lodash-es'; import _noop from 'lodash-es/noop'; import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useEffect, useMemo, useRef, useState } from 'react'; @@ -35,6 +39,8 @@ function UplotPanelWrapper({ const [maxTimeScale, setMaxTimeScale] = useState(); const { currentQuery } = useQueryBuilder(); + const [hiddenGraph, setHiddenGraph] = useState<{ [key: string]: boolean }>(); + useEffect(() => { if (toScrollWidgetId === widget.id) { graphRef.current?.scrollIntoView({ @@ -78,8 +84,26 @@ function UplotPanelWrapper({ const chartData = getUPlotChartData( queryResponse?.data?.payload, widget.fillSpans, + widget?.stackedBarChart, + hiddenGraph, ); + useEffect(() => { + if (widget.panelTypes === PANEL_TYPES.BAR && widget?.stackedBarChart) { + const graphV = cloneDeep(graphVisibility)?.slice(1); + const isSomeSelectedLegend = graphV?.some((v) => v === false); + if (isSomeSelectedLegend) { + const hiddenIndex = graphV?.findIndex((v) => v === true); + if (!isUndefined(hiddenIndex) && hiddenIndex !== -1) { + const updatedHiddenGraph = { [hiddenIndex]: true }; + if (!isEqual(hiddenGraph, updatedHiddenGraph)) { + setHiddenGraph(updatedHiddenGraph); + } + } + } + } + }, [graphVisibility, hiddenGraph, widget.panelTypes, widget?.stackedBarChart]); + const options = useMemo( () => getUPlotChartOptions({ @@ -99,6 +123,9 @@ function UplotPanelWrapper({ setGraphsVisibilityStates: setGraphVisibility, panelType: selectedGraph || widget.panelTypes, currentQuery, + stackBarChart: widget?.stackedBarChart, + hiddenGraph, + setHiddenGraph, }), [ widget?.id, @@ -107,6 +134,7 @@ function UplotPanelWrapper({ widget.softMax, widget.softMin, widget.panelTypes, + widget?.stackedBarChart, queryResponse.data?.payload, containerDimensions, isDarkMode, @@ -118,15 +146,23 @@ function UplotPanelWrapper({ setGraphVisibility, selectedGraph, currentQuery, + hiddenGraph, ], ); return (
- {isFullViewMode && setGraphVisibility && ( + {widget?.stackedBarChart && isFullViewMode && ( + + )} + {isFullViewMode && setGraphVisibility && !widget?.stackedBarChart && ( { jest.advanceTimersByTime(299); expect(setPipelineValue).not.toHaveBeenCalled(); - // Wait for the debounce delay to pass + // Fast-forward time by 1ms to reach the debounce delay + jest.advanceTimersByTime(1); + + // Wait for the debounce delay to pass and expect the callback to be called await waitFor(() => { - // Expect the callback to be called after debounce delay expect(setPipelineValue).toHaveBeenCalledWith('sample_pipeline'); }); diff --git a/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx b/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx index b272a39475..372f301008 100644 --- a/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx +++ b/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx @@ -1,13 +1,26 @@ +import '../ServiceApplication.styles.scss'; + import { SearchOutlined } from '@ant-design/icons'; +import { Popconfirm, PopconfirmProps } from 'antd'; import type { ColumnType } from 'antd/es/table'; import ROUTES from 'constants/routes'; import { routeConfig } from 'container/SideNav/config'; import { getQueryString } from 'container/SideNav/helper'; +import history from 'lib/history'; +import { Info } from 'lucide-react'; import { Link } from 'react-router-dom'; import { ServicesList } from 'types/api/metrics/getService'; import { filterDropdown } from '../Filter/FilterDropdown'; -import { Name } from '../styles'; + +const MAX_TOP_LEVEL_OPERATIONS = 2500; + +const highTopLevelOperationsPopoverDesc = (metrics: string): JSX.Element => ( +
+ The service `{metrics}` has too many top level operations. It makes the + dashboard slow to load. +
+); export const getColumnSearchProps = ( dataIndex: keyof ServicesList, @@ -15,24 +28,61 @@ export const getColumnSearchProps = ( ): ColumnType => ({ filterDropdown, filterIcon: , - onFilter: (value: string | number | boolean, record: ServicesList): boolean => - record[dataIndex] - .toString() - .toLowerCase() - .includes(value.toString().toLowerCase()), - render: (metrics: string): JSX.Element => { + onFilter: ( + value: string | number | boolean, + record: ServicesList, + ): boolean => { + if (record[dataIndex]) { + record[dataIndex] + ?.toString() + .toLowerCase() + .includes(value.toString().toLowerCase()); + } + + return false; + }, + render: (metrics: string, record: ServicesList): JSX.Element => { const urlParams = new URLSearchParams(search); const avialableParams = routeConfig[ROUTES.SERVICE_METRICS]; const queryString = getQueryString(avialableParams, urlParams); + const topLevelOperations = record?.dataWarning?.topLevelOps || []; + + const handleShowTopLevelOperations: PopconfirmProps['onConfirm'] = () => { + history.push( + `${ROUTES.APPLICATION}/${encodeURIComponent(metrics)}/top-level-operations`, + ); + }; + + const hasHighTopLevelOperations = + topLevelOperations && + Array.isArray(topLevelOperations) && + topLevelOperations.length > MAX_TOP_LEVEL_OPERATIONS; return ( - - {metrics} - +
+ {hasHighTopLevelOperations && ( + + + + )} + + + {metrics} + +
); }, }); diff --git a/frontend/src/container/ServiceApplication/ServiceApplication.styles.scss b/frontend/src/container/ServiceApplication/ServiceApplication.styles.scss new file mode 100644 index 0000000000..9cdbd2329c --- /dev/null +++ b/frontend/src/container/ServiceApplication/ServiceApplication.styles.scss @@ -0,0 +1,25 @@ +.serviceName { + color: #4e74f8; + font-weight: 600; + cursor: pointer; + + display: flex; + align-items: center; + gap: 8px; +} + +.error { + color: var(--bg-cherry-500); + + a { + color: var(--bg-cherry-500); + } +} + +.service-high-top-level-operations { + width: 300px; + + .popover-description { + padding: 16px 0; + } +} diff --git a/frontend/src/container/ServiceApplication/index.tsx b/frontend/src/container/ServiceApplication/index.tsx index b7b22018e1..0afdc6950d 100644 --- a/frontend/src/container/ServiceApplication/index.tsx +++ b/frontend/src/container/ServiceApplication/index.tsx @@ -1,7 +1,7 @@ +import * as Sentry from '@sentry/react'; import { FeatureKeys } from 'constants/features'; import useFeatureFlag from 'hooks/useFeatureFlag'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; -import { ErrorBoundary } from 'react-error-boundary'; import ServiceMetrics from './ServiceMetrics'; import ServiceTraces from './ServiceTraces'; @@ -12,11 +12,11 @@ function Services(): JSX.Element { ?.active; return ( - + }> {isSpanMetricEnabled ? : } - + ); } diff --git a/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx b/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx index 4257dc57ec..059063e5d9 100644 --- a/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx +++ b/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx @@ -15,11 +15,19 @@ export const getColumnSearchProps = ( ): ColumnType => ({ filterDropdown, filterIcon: , - onFilter: (value: string | number | boolean, record: ServicesList): boolean => - record[dataIndex] - .toString() - .toLowerCase() - .includes(value.toString().toLowerCase()), + onFilter: ( + value: string | number | boolean, + record: ServicesList, + ): boolean => { + if (record[dataIndex]) { + record[dataIndex] + ?.toString() + .toLowerCase() + .includes(value.toString().toLowerCase()); + } + + return false; + }, render: (metrics: string): JSX.Element => { const urlParams = new URLSearchParams(search); const avialableParams = routeConfig[ROUTES.SERVICE_METRICS]; diff --git a/frontend/src/container/SideNav/SideNav.tsx b/frontend/src/container/SideNav/SideNav.tsx index 3b35a75a81..6cec0448b2 100644 --- a/frontend/src/container/SideNav/SideNav.tsx +++ b/frontend/src/container/SideNav/SideNav.tsx @@ -209,7 +209,9 @@ function SideNav({ if (event && isCtrlMetaKey(event)) { openInNewTab(`${key}?${queryString.join('&')}`); } else { - history.push(`${key}?${queryString.join('&')}`); + history.push(`${key}?${queryString.join('&')}`, { + from: pathname, + }); } } }, diff --git a/frontend/src/container/SideNav/menuItems.tsx b/frontend/src/container/SideNav/menuItems.tsx index 6c9a87db02..31bd96333e 100644 --- a/frontend/src/container/SideNav/menuItems.tsx +++ b/frontend/src/container/SideNav/menuItems.tsx @@ -125,8 +125,8 @@ const menuItems: SidebarItem[] = [ /** Mapping of some newly added routes and their corresponding active sidebar menu key */ export const NEW_ROUTES_MENU_ITEM_KEY_MAP: Record = { - [ROUTES.TRACES_EXPLORER]: ROUTES.TRACE, - [ROUTES.TRACE_EXPLORER]: ROUTES.TRACE, + [ROUTES.TRACE]: ROUTES.TRACES_EXPLORER, + [ROUTES.TRACE_EXPLORER]: ROUTES.TRACES_EXPLORER, [ROUTES.LOGS_BASE]: ROUTES.LOGS_EXPLORER, }; diff --git a/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts b/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts index 7909984592..7543e02a47 100644 --- a/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts +++ b/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts @@ -202,6 +202,7 @@ export const routesToSkip = [ ROUTES.INTEGRATIONS, ROUTES.DASHBOARD, ROUTES.DASHBOARD_WIDGET, + ROUTES.SERVICE_TOP_LEVEL_OPERATIONS, ]; export const routesToDisable = [ROUTES.LOGS_EXPLORER, ROUTES.LIVE_LOGS]; diff --git a/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx b/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx index b5c8868184..427b57198c 100644 --- a/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx +++ b/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx @@ -22,7 +22,6 @@ import { QueryHistoryState } from 'container/LiveLogs/types'; import NewExplorerCTA from 'container/NewExplorerCTA'; import dayjs, { Dayjs } from 'dayjs'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; -import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval'; import useUrlQuery from 'hooks/useUrlQuery'; import GetMinMax from 'lib/getMinMax'; import getTimeString from 'lib/getTimeString'; @@ -315,8 +314,6 @@ function DateTimeSelection({ return; } - const { maxTime, minTime } = GetMinMax(value, getTime()); - if (!isLogsExplorerPage) { urlQuery.delete('startTime'); urlQuery.delete('endTime'); @@ -333,7 +330,8 @@ function DateTimeSelection({ return; } // the second boolean param directs the qb about the time change so to merge the query and retain the current state - initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true); + // we removed update step interval to stop auto updating the value on time change + initQueryBuilderData(stagedQuery, true); }; const onRefreshHandler = (): void => { @@ -383,8 +381,6 @@ function DateTimeSelection({ setIsValidteRelativeTime(true); - const { maxTime, minTime } = GetMinMax(dateTimeStr, getTime()); - if (!isLogsExplorerPage) { urlQuery.delete('startTime'); urlQuery.delete('endTime'); @@ -400,7 +396,8 @@ function DateTimeSelection({ } // the second boolean param directs the qb about the time change so to merge the query and retain the current state - initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true); + // we removed update step interval to stop auto updating the value on time change + initQueryBuilderData(stagedQuery, true); }; const getCustomOrIntervalTime = ( diff --git a/frontend/src/container/TraceDetail/TraceDetails.styles.scss b/frontend/src/container/TraceDetail/TraceDetails.styles.scss index 676160aecc..0c309bc83d 100644 --- a/frontend/src/container/TraceDetail/TraceDetails.styles.scss +++ b/frontend/src/container/TraceDetail/TraceDetails.styles.scss @@ -1,7 +1,17 @@ .span-details-sider { + padding-top: 16px; + + ::-webkit-scrollbar { + width: 0.2em; + } + + ::-webkit-scrollbar-track { + box-shadow: inset 0 0 6px rgba(18, 18, 18, 0.3); + } + &.dark { .ant-layout-sider-trigger { - background-color: black !important; + background-color: #0b0c0e !important; } } diff --git a/frontend/src/container/TraceDetail/index.tsx b/frontend/src/container/TraceDetail/index.tsx index 67b55a1bca..4b333e0dad 100644 --- a/frontend/src/container/TraceDetail/index.tsx +++ b/frontend/src/container/TraceDetail/index.tsx @@ -246,13 +246,14 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element { setCollapsed(value)} > {!collapsed && ( diff --git a/frontend/src/container/TracesExplorer/ListView/utils.tsx b/frontend/src/container/TracesExplorer/ListView/utils.tsx index 732c8eacdf..254ff93296 100644 --- a/frontend/src/container/TracesExplorer/ListView/utils.tsx +++ b/frontend/src/container/TracesExplorer/ListView/utils.tsx @@ -3,6 +3,7 @@ import { ColumnsType } from 'antd/es/table'; import ROUTES from 'constants/routes'; import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util'; import { formUrlParams } from 'container/TraceDetail/utils'; +import dayjs from 'dayjs'; import { RowData } from 'lib/query/createTableColumnsFromQuery'; import { ILog } from 'types/api/logs/log'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; @@ -30,6 +31,13 @@ export const getListColumns = ( key: 'date', title: 'Timestamp', width: 145, + render: (item): JSX.Element => { + const date = + typeof item === 'string' + ? dayjs(item).format('YYYY-MM-DD HH:mm:ss.SSS') + : dayjs(item / 1e6).format('YYYY-MM-DD HH:mm:ss.SSS'); + return {date}; + }, }, ]; diff --git a/frontend/src/container/TracesExplorer/QuerySection/index.tsx b/frontend/src/container/TracesExplorer/QuerySection/index.tsx index 0bd9515720..8f5d2606f0 100644 --- a/frontend/src/container/TracesExplorer/QuerySection/index.tsx +++ b/frontend/src/container/TracesExplorer/QuerySection/index.tsx @@ -19,7 +19,7 @@ function QuerySection(): JSX.Element { const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => { const isList = panelTypes === PANEL_TYPES.LIST; const config: QueryBuilderProps['filterConfigs'] = { - stepInterval: { isHidden: false, isDisabled: true }, + stepInterval: { isHidden: false, isDisabled: false }, limit: { isHidden: isList, isDisabled: true }, having: { isHidden: isList, isDisabled: true }, }; @@ -56,7 +56,7 @@ function QuerySection(): JSX.Element { version="v3" // setting this to v3 as we this is rendered in logs explorer actions={ - diff --git a/frontend/src/container/TracesExplorer/TracesView/configs.tsx b/frontend/src/container/TracesExplorer/TracesView/configs.tsx index a6296e362a..f5980a044d 100644 --- a/frontend/src/container/TracesExplorer/TracesView/configs.tsx +++ b/frontend/src/container/TracesExplorer/TracesView/configs.tsx @@ -3,7 +3,7 @@ import { ColumnsType } from 'antd/es/table'; import ROUTES from 'constants/routes'; import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util'; import { DEFAULT_PER_PAGE_OPTIONS } from 'hooks/queryPagination'; -import { generatePath } from 'react-router-dom'; +import { generatePath, Link } from 'react-router-dom'; import { ListItem } from 'types/api/widgets/getQuery'; export const PER_PAGE_OPTIONS: number[] = [10, ...DEFAULT_PER_PAGE_OPTIONS]; @@ -38,14 +38,14 @@ export const columns: ColumnsType = [ dataIndex: 'traceID', key: 'traceID', render: (traceID: string): JSX.Element => ( - {traceID} - + ), }, ]; diff --git a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss index 0787972eec..74e80f8764 100644 --- a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss +++ b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss @@ -5,7 +5,7 @@ height: 100%; .resize-table { - height: calc(100% - 40px); + height: calc(100% - 70px); overflow: scroll; overflow-x: hidden; diff --git a/frontend/src/hooks/dashboard/utils.ts b/frontend/src/hooks/dashboard/utils.ts index ad3fadd8b9..ed61e25581 100644 --- a/frontend/src/hooks/dashboard/utils.ts +++ b/frontend/src/hooks/dashboard/utils.ts @@ -1,43 +1,61 @@ import { PANEL_TYPES } from 'constants/queryBuilder'; +import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils'; import { Dashboard } from 'types/api/dashboard/getAll'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; +const baseLogsSelectedColumns = { + dataType: 'string', + type: '', + name: 'timestamp', +}; + export const addEmptyWidgetInDashboardJSONWithQuery = ( dashboard: Dashboard, query: Query, widgetId: string, - panelTypes?: PANEL_TYPES, -): Dashboard => ({ - ...dashboard, - data: { - ...dashboard.data, - layout: [ - { - i: widgetId, - w: 6, - x: 0, - h: 6, - y: 0, - }, - ...(dashboard?.data?.layout || []), - ], - widgets: [ - ...(dashboard?.data?.widgets || []), - { - id: widgetId, - query, - description: '', - isStacked: false, - nullZeroValues: '', - opacity: '', - title: '', - timePreferance: 'GLOBAL_TIME', - panelTypes: panelTypes || PANEL_TYPES.TIME_SERIES, - softMax: null, - softMin: null, - selectedLogFields: [], - selectedTracesFields: [], - }, - ], - }, -}); + panelType?: PANEL_TYPES, + selectedColumns?: BaseAutocompleteData[] | null, +): Dashboard => { + const logsSelectedColumns = [ + baseLogsSelectedColumns, + ...convertKeysToColumnFields(selectedColumns || []), + ]; + + return { + ...dashboard, + data: { + ...dashboard.data, + layout: [ + { + i: widgetId, + w: 6, + x: 0, + h: 6, + y: 0, + }, + ...(dashboard?.data?.layout || []), + ], + widgets: [ + ...(dashboard?.data?.widgets || []), + { + id: widgetId, + query, + description: '', + isStacked: false, + nullZeroValues: '', + opacity: '', + title: '', + timePreferance: 'GLOBAL_TIME', + panelTypes: panelType || PANEL_TYPES.TIME_SERIES, + softMax: null, + softMin: null, + selectedLogFields: + panelType === PANEL_TYPES.LIST ? logsSelectedColumns : [], + selectedTracesFields: + panelType === PANEL_TYPES.LIST ? selectedColumns || [] : [], + }, + ], + }, + }; +}; diff --git a/frontend/src/hooks/queryBuilder/useStepInterval.ts b/frontend/src/hooks/queryBuilder/useStepInterval.ts index 55dad54664..62f8a0d7c1 100644 --- a/frontend/src/hooks/queryBuilder/useStepInterval.ts +++ b/frontend/src/hooks/queryBuilder/useStepInterval.ts @@ -8,6 +8,7 @@ export const updateStepInterval = ( query: Widgets['query'], maxTime: number, minTime: number, + shallUpdateStepInterval?: boolean, ): Widgets['query'] => { const stepInterval = getStep({ start: minTime, @@ -15,6 +16,14 @@ export const updateStepInterval = ( inputFormat: 'ns', }); + function getStepInterval(customInterval: number): number { + // if user enters some value then auto update should never come + if (shallUpdateStepInterval) { + return customInterval; + } + return stepInterval; + } + return { ...query, builder: { @@ -22,7 +31,7 @@ export const updateStepInterval = ( queryData: query?.builder?.queryData?.map((item) => ({ ...item, - stepInterval, + stepInterval: getStepInterval(item.stepInterval), })) || [], }, }; diff --git a/frontend/src/hooks/useDarkMode/index.tsx b/frontend/src/hooks/useDarkMode/index.tsx index d7e3a279e0..ef2883b4b3 100644 --- a/frontend/src/hooks/useDarkMode/index.tsx +++ b/frontend/src/hooks/useDarkMode/index.tsx @@ -30,7 +30,7 @@ export function ThemeProvider({ children }: ThemeProviderProps): JSX.Element { setTheme(THEME_MODE.LIGHT); set(LOCALSTORAGE.THEME, THEME_MODE.LIGHT); } - set(LOCALSTORAGE.THEME_ANALYTICS, ''); + set(LOCALSTORAGE.THEME_ANALYTICS_V1, ''); }, [theme]); const value = useMemo( diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 570db8c1da..45a1b6f11a 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -7,7 +7,6 @@ import { AxiosError } from 'axios'; import { ThemeProvider } from 'hooks/useDarkMode'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { createRoot } from 'react-dom/client'; -import { ErrorBoundary } from 'react-error-boundary'; import { HelmetProvider } from 'react-helmet-async'; import { QueryClient, QueryClientProvider } from 'react-query'; import { Provider } from 'react-redux'; @@ -58,7 +57,7 @@ if (container) { const root = createRoot(container); root.render( - + }> @@ -68,6 +67,6 @@ if (container) { - , + , ); } diff --git a/frontend/src/lib/dashboard/getQueryResults.ts b/frontend/src/lib/dashboard/getQueryResults.ts index e3f956c32a..7b7276c378 100644 --- a/frontend/src/lib/dashboard/getQueryResults.ts +++ b/frontend/src/lib/dashboard/getQueryResults.ts @@ -75,6 +75,7 @@ export interface GetQueryResultsProps { globalSelectedInterval: Time | TimeV2 | CustomTimeType; variables?: Record; params?: Record; + fillGaps?: boolean; tableParams?: { pagination?: Pagination; selectColumns?: any; diff --git a/frontend/src/lib/dashboard/prepareQueryRangePayload.ts b/frontend/src/lib/dashboard/prepareQueryRangePayload.ts index 0b918bcb14..244e096079 100644 --- a/frontend/src/lib/dashboard/prepareQueryRangePayload.ts +++ b/frontend/src/lib/dashboard/prepareQueryRangePayload.ts @@ -20,6 +20,7 @@ export const prepareQueryRangePayload = ({ tableParams, variables = {}, params = {}, + fillGaps = false, }: GetQueryResultsProps): PrepareQueryRangePayload => { let legendMap: Record = {}; const { allowSelectedIntervalForStepGen, ...restParams } = params; @@ -27,6 +28,7 @@ export const prepareQueryRangePayload = ({ const compositeQuery: QueryRangePayload['compositeQuery'] = { queryType: query.queryType, panelType: graphType, + fillGaps, }; switch (query.queryType) { diff --git a/frontend/src/lib/query/createTableColumnsFromQuery.ts b/frontend/src/lib/query/createTableColumnsFromQuery.ts index 85b876dc11..18926f2f0c 100644 --- a/frontend/src/lib/query/createTableColumnsFromQuery.ts +++ b/frontend/src/lib/query/createTableColumnsFromQuery.ts @@ -1,20 +1,25 @@ import { ColumnsType } from 'antd/es/table'; import { ColumnType } from 'antd/lib/table'; import { + initialClickHouseData, initialFormulaBuilderFormValues, initialQueryBuilderFormValues, + initialQueryPromQLData, } from 'constants/queryBuilder'; import { FORMULA_REGEXP } from 'constants/regExp'; import { QUERY_TABLE_CONFIG } from 'container/QueryTable/config'; import { QueryTableProps } from 'container/QueryTable/QueryTable.intefaces'; -import { isEqual, isNaN, isObject } from 'lodash-es'; +import { get, isEqual, isNaN, isObject } from 'lodash-es'; import { ReactNode } from 'react'; import { IBuilderFormula, IBuilderQuery, + IClickHouseQuery, + IPromQLQuery, Query, } from 'types/api/queryBuilder/queryBuilderData'; import { ListItem, QueryDataV3, SeriesItem } from 'types/api/widgets/getQuery'; +import { EQueryType } from 'types/common/dashboard'; import { QueryBuilderData } from 'types/common/queryBuilder'; import { v4 as uuid } from 'uuid'; @@ -30,7 +35,7 @@ export type RowData = { }; export type DynamicColumn = { - query: IBuilderQuery | IBuilderFormula; + query: IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery; field: string; dataIndex: string; title: string; @@ -75,24 +80,43 @@ const isValueExist = ( }; const getQueryByName = ( - builder: QueryBuilderData, + query: Query, currentQueryName: string, type: T, -): T extends 'queryData' ? IBuilderQuery : IBuilderFormula => { - const queryArray = builder[type]; - const defaultValue = - type === 'queryData' - ? initialQueryBuilderFormValues - : initialFormulaBuilderFormValues; +): IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery => { + if (query.queryType === EQueryType.CLICKHOUSE) { + const queryArray = query.clickhouse_sql; + const defaultQueryValue = initialClickHouseData; - const currentQuery = - queryArray.find((q) => q.queryName === currentQueryName) || defaultValue; + return ( + queryArray.find((q) => q.name === currentQueryName) || defaultQueryValue + ); + } + if (query.queryType === EQueryType.QUERY_BUILDER) { + const queryArray = query.builder[type]; + const defaultValue = + type === 'queryData' + ? initialQueryBuilderFormValues + : initialFormulaBuilderFormValues; - return currentQuery as T extends 'queryData' ? IBuilderQuery : IBuilderFormula; + const currentQuery = + queryArray.find((q) => q.queryName === currentQueryName) || defaultValue; + + return currentQuery as T extends 'queryData' + ? IBuilderQuery + : IBuilderFormula; + } + + const queryArray = query.promql; + const defaultQueryValue = initialQueryPromQLData; + + return ( + queryArray.find((q) => q.name === currentQueryName) || defaultQueryValue + ); }; const addLabels = ( - query: IBuilderQuery | IBuilderFormula, + query: IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery, label: string, dynamicColumns: DynamicColumns, ): void => { @@ -111,11 +135,13 @@ const addLabels = ( }; const addOperatorFormulaColumns = ( - query: IBuilderFormula | IBuilderQuery, + query: IBuilderFormula | IBuilderQuery | IClickHouseQuery | IPromQLQuery, dynamicColumns: DynamicColumns, + queryType: EQueryType, customLabel?: string, + // eslint-disable-next-line sonarjs/cognitive-complexity ): void => { - if (isFormula(query.queryName)) { + if (isFormula(get(query, 'queryName', ''))) { const formulaQuery = query as IBuilderFormula; let formulaLabel = `${formulaQuery.queryName}(${formulaQuery.expression})`; @@ -137,27 +163,68 @@ const addOperatorFormulaColumns = ( return; } - const currentQueryData = query as IBuilderQuery; + if (queryType === EQueryType.QUERY_BUILDER) { + const currentQueryData = query as IBuilderQuery; + let operatorLabel = `${currentQueryData.aggregateOperator}`; + if (currentQueryData.aggregateAttribute.key) { + operatorLabel += `(${currentQueryData.aggregateAttribute.key})`; + } - let operatorLabel = `${currentQueryData.aggregateOperator}`; - if (currentQueryData.aggregateAttribute.key) { - operatorLabel += `(${currentQueryData.aggregateAttribute.key})`; + if (currentQueryData.legend) { + operatorLabel = currentQueryData.legend; + } + + const operatorColumn: DynamicColumn = { + query, + field: currentQueryData.queryName, + dataIndex: currentQueryData.queryName, + title: customLabel || operatorLabel, + data: [], + type: 'operator', + }; + + dynamicColumns.push(operatorColumn); } - if (currentQueryData.legend) { - operatorLabel = currentQueryData.legend; + if (queryType === EQueryType.CLICKHOUSE) { + const currentQueryData = query as IClickHouseQuery; + let operatorLabel = `${currentQueryData.name}`; + + if (currentQueryData.legend) { + operatorLabel = currentQueryData.legend; + } + + const operatorColumn: DynamicColumn = { + query, + field: currentQueryData.name, + dataIndex: currentQueryData.name, + title: customLabel || operatorLabel, + data: [], + type: 'operator', + }; + + dynamicColumns.push(operatorColumn); } - const operatorColumn: DynamicColumn = { - query, - field: currentQueryData.queryName, - dataIndex: currentQueryData.queryName, - title: customLabel || operatorLabel, - data: [], - type: 'operator', - }; + if (queryType === EQueryType.PROM) { + const currentQueryData = query as IPromQLQuery; + let operatorLabel = `${currentQueryData.name}`; - dynamicColumns.push(operatorColumn); + if (currentQueryData.legend) { + operatorLabel = currentQueryData.legend; + } + + const operatorColumn: DynamicColumn = { + query, + field: currentQueryData.name, + dataIndex: currentQueryData.name, + title: customLabel || operatorLabel, + data: [], + type: 'operator', + }; + + dynamicColumns.push(operatorColumn); + } }; const transformColumnTitles = ( @@ -175,8 +242,16 @@ const transformColumnTitles = ( if (sameValues.length > 1) { return { ...item, - dataIndex: `${item.title} - ${item.query.queryName}`, - title: `${item.title} - ${item.query.queryName}`, + dataIndex: `${item.title} - ${get( + item.query, + 'queryName', + get(item.query, 'name', ''), + )}`, + title: `${item.title} - ${get( + item.query, + 'queryName', + get(item.query, 'name', ''), + )}`, }; } @@ -190,7 +265,7 @@ const getDynamicColumns: GetDynamicColumns = (queryTableData, query) => { const { series, queryName, list } = currentQuery; const currentStagedQuery = getQueryByName( - query.builder, + query, queryName, isFormula(queryName) ? 'queryFormulas' : 'queryData', ); @@ -210,7 +285,8 @@ const getDynamicColumns: GetDynamicColumns = (queryTableData, query) => { addOperatorFormulaColumns( currentStagedQuery, dynamicColumns, - isEveryValuesExist ? undefined : currentStagedQuery.queryName, + query.queryType, + isEveryValuesExist ? undefined : get(currentStagedQuery, 'queryName', ''), ); } @@ -289,6 +365,7 @@ const fillRestAggregationData = ( queryTableData: QueryDataV3[], seria: SeriesItem, equalQueriesByLabels: string[], + isEqualQuery: boolean, ): void => { const nextQueryData = queryTableData.find((q) => q.queryName === column.field) || null; @@ -298,13 +375,13 @@ const fillRestAggregationData = ( nextQueryData, ); + const isEqual = isEqualQueriesByLabel(equalQueriesByLabels, column.field); if (targetSeria) { - const isEqual = isEqualQueriesByLabel(equalQueriesByLabels, column.field); if (!isEqual) { // This line is crucial. It ensures that no additional rows are added to the table for similar labels across all formulas here is how this check is applied: signoz/frontend/src/lib/query/createTableColumnsFromQuery.ts line number 370 equalQueriesByLabels.push(column.field); } - } else { + } else if (!isEqualQuery) { column.data.push('N/A'); } }; @@ -359,6 +436,7 @@ const fillDataFromSeries = ( queryTableData, seria, equalQueriesByLabels, + isEqualQuery, ); return; @@ -461,8 +539,12 @@ const generateTableColumns = ( width: QUERY_TABLE_CONFIG.width, render: renderColumnCell && renderColumnCell[item.dataIndex], sorter: (a: RowData, b: RowData): number => { - const valueA = Number(a[item.dataIndex]); - const valueB = Number(b[item.dataIndex]); + const valueA = Number( + a[`${item.dataIndex}_without_unit`] ?? a[item.dataIndex], + ); + const valueB = Number( + b[`${item.dataIndex}_without_unit`] ?? b[item.dataIndex], + ); if (!isNaN(valueA) && !isNaN(valueB)) { return valueA - valueB; @@ -490,6 +572,29 @@ export const createTableColumnsFromQuery: CreateTableDataFromQuery = ({ a.queryName < b.queryName ? -1 : 1, ); + // the reason we need this is because the filling of values in rows doesn't account for mismatch enteries + // in the response. Example : Series A -> [label1, label2] and Series B -> [label2,label1] this isn't accounted for + sortedQueryTableData.forEach((q) => { + q.series?.forEach((s) => { + s.labelsArray?.sort((a, b) => + Object.keys(a)[0] < Object.keys(b)[0] ? -1 : 1, + ); + }); + q.series?.sort((a, b) => { + let labelA = ''; + let labelB = ''; + a.labelsArray.forEach((lab) => { + labelA += Object.values(lab)[0]; + }); + + b.labelsArray.forEach((lab) => { + labelB += Object.values(lab)[0]; + }); + + return labelA < labelB ? -1 : 1; + }); + }); + const dynamicColumns = getDynamicColumns(sortedQueryTableData, query); const { filledDynamicColumns, rowsLength } = fillColumnsData( diff --git a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts index 2247ec90bd..dd08cbfff1 100644 --- a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts +++ b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts @@ -10,9 +10,11 @@ import { saveLegendEntriesToLocalStorage } from 'container/GridCardLayout/GridCa import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types'; import { Dimensions } from 'hooks/useDimensions'; import { convertValue } from 'lib/getConvertedValue'; +import { cloneDeep, isUndefined } from 'lodash-es'; import _noop from 'lodash-es/noop'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; +import { QueryData, QueryDataV3 } from 'types/api/widgets/getQuery'; import uPlot from 'uplot'; import onClickPlugin, { OnClickPluginOpts } from './plugins/onClickPlugin'; @@ -42,6 +44,84 @@ export interface GetUPlotChartOptions { softMin: number | null; softMax: number | null; currentQuery?: Query; + stackBarChart?: boolean; + hiddenGraph?: { + [key: string]: boolean; + }; + setHiddenGraph?: Dispatch< + SetStateAction<{ + [key: string]: boolean; + }> + >; +} + +/** the function converts series A , series B , series C to + * series A , series A + series B , series A + series B + series C + * which helps us to always ensure the bar in the front is always + * of the smallest value. + */ + +function getStackedSeries(apiResponse: QueryData[]): QueryData[] { + const series = cloneDeep(apiResponse); + + for (let i = series.length - 2; i >= 0; i--) { + const { values } = series[i]; + for (let j = 0; j < values.length; j++) { + values[j][1] = String( + parseFloat(values[j]?.[1] || '0') + + parseFloat(series[i + 1].values[j]?.[1] || '0'), + ); + } + + series[i].values = values; + } + + return series; +} + +/** this does the exact same operations as the function above for a different + * response format. + */ +function getStackedSeriesQueryFormat(apiResponse: QueryData[]): QueryData[] { + const series = cloneDeep(apiResponse); + + for (let i = series.length - 2; i >= 0; i--) { + const { values } = series[i]; + for (let j = 0; j < values.length; j++) { + values[j].value = String( + parseFloat(values[j]?.value || '0') + + parseFloat(series[i + 1].values[j]?.value || '0'), + ); + } + + series[i].values = values; + } + + return series; +} + +function getStackedSeriesYAxis(apiResponse: QueryDataV3[]): QueryDataV3[] { + const series = cloneDeep(apiResponse); + + for (let i = 0; i < series.length; i++) { + series[i].series = getStackedSeriesQueryFormat(series[i].series); + } + + return series; +} + +/** + * here we define the different series bands which should get highlighted based + * on cursor hover. basically the to and the from destination of a particular band. + */ +function getBands(series): any[] { + const bands = []; + for (let i = 0; i < series.length; i++) { + bands.push({ + series: [i === 0 ? -1 : i, i + 1], + }); + } + return bands; } export const getUPlotChartOptions = ({ @@ -61,9 +141,18 @@ export const getUPlotChartOptions = ({ softMin, panelType, currentQuery, + stackBarChart: stackChart, + hiddenGraph, + setHiddenGraph, }: GetUPlotChartOptions): uPlot.Options => { const timeScaleProps = getXAxisScale(minTimeScale, maxTimeScale); + const stackBarChart = stackChart && isUndefined(hiddenGraph); + + const series = getStackedSeries(apiResponse?.data?.result || []); + + const bands = stackBarChart ? getBands(series) : null; + return { id, width: dimensions.width, @@ -91,6 +180,7 @@ export const getUPlotChartOptions = ({ }, }, padding: [16, 16, 8, 8], + bands, scales: { x: { spanGaps: true, @@ -99,7 +189,9 @@ export const getUPlotChartOptions = ({ y: { ...getYAxisScale({ thresholds, - series: apiResponse?.data?.newResult?.data?.result || [], + series: stackBarChart + ? getStackedSeriesYAxis(apiResponse?.data?.newResult?.data?.result || []) + : apiResponse?.data?.newResult?.data?.result || [], yAxisUnit, softMax, softMin, @@ -107,7 +199,7 @@ export const getUPlotChartOptions = ({ }, }, plugins: [ - tooltipPlugin({ apiResponse, yAxisUnit }), + tooltipPlugin({ apiResponse, yAxisUnit, stackBarChart, isDarkMode }), onClickPlugin({ onClick: onClickHandler, }), @@ -192,6 +284,17 @@ export const getUPlotChartOptions = ({ const seriesArray = Array.from(seriesEls); seriesArray.forEach((seriesEl, index) => { seriesEl.addEventListener('click', () => { + if (stackChart) { + setHiddenGraph((prev) => { + if (isUndefined(prev)) { + return { [index]: true }; + } + if (prev[index] === true) { + return undefined; + } + return { [index]: true }; + }); + } if (graphsVisibilityStates) { setGraphsVisibilityStates?.((prev) => { const newGraphVisibilityStates = [...prev]; @@ -221,11 +324,17 @@ export const getUPlotChartOptions = ({ ], }, series: getSeries({ - apiResponse, + series: + stackBarChart && isUndefined(hiddenGraph) + ? series + : apiResponse?.data?.result, widgetMetaData: apiResponse?.data.result, graphsVisibilityStates, panelType, currentQuery, + stackBarChart, + hiddenGraph, + isDarkMode, }), axes: getAxes(isDarkMode, yAxisUnit), }; diff --git a/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts b/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts index 15bea36cba..2ff0f3051e 100644 --- a/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts +++ b/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts @@ -35,6 +35,7 @@ type GetHistogramSeriesProps = { widgetMetaData?: QueryData[]; graphsVisibilityStates?: boolean[]; isMergedSeries?: boolean; + isDarkMode: boolean; }; const { bars } = uPlot.paths; @@ -56,6 +57,7 @@ const getHistogramSeries = ({ widgetMetaData, graphsVisibilityStates, isMergedSeries, + isDarkMode, }: GetHistogramSeriesProps): uPlot.Options['series'] => { const configurations: uPlot.Series[] = [ { label: 'Timestamp', stroke: 'purple' }, @@ -75,10 +77,13 @@ const getHistogramSeries = ({ const legend = newLegend || lgd || ''; const label = isMergedSeries - ? 'merged_series' + ? '' : getLabelName(metric, queryName || '', legend); - const color = generateColor(label, themeColors.chartcolors); + const color = generateColor( + label, + isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor, + ); const pointSize = seriesList[i].values.length > 1 ? 5 : 10; const showPoints = !(seriesList[i].values.length > 1); @@ -133,6 +138,7 @@ export const getUplotHistogramChartOptions = ({ apiResponse, isHistogramGraphs: true, isMergedSeries: mergeAllQueries, + isDarkMode, }), ], scales: { @@ -157,6 +163,7 @@ export const getUplotHistogramChartOptions = ({ currentQuery, graphsVisibilityStates, isMergedSeries: mergeAllQueries, + isDarkMode, }), hooks: { ready: [ diff --git a/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts b/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts index 2c1040daf4..16178fe5f0 100644 --- a/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts +++ b/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts @@ -22,15 +22,30 @@ interface UplotTooltipDataProps { queryName: string; } +function getTooltipBaseValue( + data: any[], + index: number, + idx: number, + stackBarChart: boolean | undefined, +): any { + if (stackBarChart && index + 1 < data.length) { + return data[index][idx] - data[index + 1][idx]; + } + + return data[index][idx]; +} + const generateTooltipContent = ( seriesList: any[], data: any[], idx: number, + isDarkMode: boolean, yAxisUnit?: string, series?: uPlot.Options['series'], isBillingUsageGraphs?: boolean, isHistogramGraphs?: boolean, isMergedSeries?: boolean, + stackBarChart?: boolean, // eslint-disable-next-line sonarjs/cognitive-complexity ): HTMLElement => { const container = document.createElement('div'); @@ -67,13 +82,17 @@ const generateTooltipContent = ( unit = '', } = seriesList[index - 1] || {}; - const value = data[index][idx]; + const value = getTooltipBaseValue(data, index, idx, stackBarChart); + const dataIngested = quantity[idx]; const label = isMergedSeries - ? 'merged_series' + ? '' : getLabelName(metric, queryName || '', legend || ''); - let color = generateColor(label, themeColors.chartcolors); + let color = generateColor( + label, + isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor, + ); // in case of billing graph pick colors from the series options if (isBillingUsageGraphs) { @@ -201,6 +220,8 @@ type ToolTipPluginProps = { isBillingUsageGraphs?: boolean; isHistogramGraphs?: boolean; isMergedSeries?: boolean; + stackBarChart?: boolean; + isDarkMode: boolean; }; const tooltipPlugin = ({ @@ -209,6 +230,8 @@ const tooltipPlugin = ({ isBillingUsageGraphs, isHistogramGraphs, isMergedSeries, + stackBarChart, + isDarkMode, }: ToolTipPluginProps): any => { let over: HTMLElement; let bound: HTMLElement; @@ -267,11 +290,13 @@ const tooltipPlugin = ({ apiResult, u.data, idx, + isDarkMode, yAxisUnit, u.series, isBillingUsageGraphs, isHistogramGraphs, isMergedSeries, + stackBarChart, ); overlay.appendChild(content); placement(overlay, anchor, 'right', 'start', { bound }); diff --git a/frontend/src/lib/uPlotLib/utils/getSeriesData.ts b/frontend/src/lib/uPlotLib/utils/getSeriesData.ts index 92dbbab8bb..5de1f6d207 100644 --- a/frontend/src/lib/uPlotLib/utils/getSeriesData.ts +++ b/frontend/src/lib/uPlotLib/utils/getSeriesData.ts @@ -2,7 +2,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder'; import { themeColors } from 'constants/theme'; import getLabelName from 'lib/getLabelName'; -import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; +import { isUndefined } from 'lodash-es'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { QueryData } from 'types/api/widgets/getQuery'; @@ -28,16 +28,19 @@ const paths = ( }; const getSeries = ({ - apiResponse, + series, widgetMetaData, graphsVisibilityStates, panelType, + hiddenGraph, + isDarkMode, }: GetSeriesProps): uPlot.Options['series'] => { const configurations: uPlot.Series[] = [ { label: 'Timestamp', stroke: 'purple' }, ]; - const seriesList = apiResponse?.data.result || []; + const seriesList = series || []; + const newGraphVisibilityStates = graphsVisibilityStates?.slice(1); for (let i = 0; i < seriesList?.length; i += 1) { @@ -49,7 +52,10 @@ const getSeries = ({ legend || '', ); - const color = generateColor(label, themeColors.chartcolors); + const color = generateColor( + label, + isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor, + ); const pointSize = seriesList[i].values.length > 1 ? 5 : 10; const showPoints = !(seriesList[i].values.length > 1); @@ -64,7 +70,12 @@ const getSeries = ({ panelType && panelType === PANEL_TYPES.BAR ? null : lineInterpolations.spline, - show: newGraphVisibilityStates ? newGraphVisibilityStates[i] : true, + // eslint-disable-next-line no-nested-ternary + show: newGraphVisibilityStates + ? newGraphVisibilityStates[i] + : !isUndefined(hiddenGraph) + ? hiddenGraph[i] + : true, label, fill: panelType && panelType === PANEL_TYPES.BAR ? `${color}40` : undefined, stroke: color, @@ -84,11 +95,16 @@ const getSeries = ({ }; export type GetSeriesProps = { - apiResponse?: MetricRangePayloadProps; + series?: QueryData[]; widgetMetaData: QueryData[]; + isDarkMode: boolean; graphsVisibilityStates?: boolean[]; panelType?: PANEL_TYPES; currentQuery?: Query; + stackBarChart?: boolean; + hiddenGraph?: { + [key: string]: boolean; + }; }; export default getSeries; diff --git a/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts b/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts index d1f5a7ffbc..3e88f8769e 100644 --- a/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts +++ b/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts @@ -1,3 +1,4 @@ +import { cloneDeep, isUndefined } from 'lodash-es'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { QueryData } from 'types/api/widgets/getQuery'; @@ -16,11 +17,7 @@ function getXAxisTimestamps(seriesList: QueryData[]): number[] { return timestampsArr.sort((a, b) => a - b); } -function fillMissingXAxisTimestamps( - timestampArr: number[], - data: any[], - fillSpans: boolean, -): any { +function fillMissingXAxisTimestamps(timestampArr: number[], data: any[]): any { // Generate a set of all timestamps in the range const allTimestampsSet = new Set(timestampArr); const processedData = JSON.parse(JSON.stringify(data)); @@ -34,14 +31,14 @@ function fillMissingXAxisTimestamps( ); missingTimestamps.forEach((timestamp) => { - const value = fillSpans ? 0 : null; + const value = null; entry.values.push([timestamp, value]); }); entry.values.forEach((v) => { if (Number.isNaN(v[1])) { - const replaceValue = fillSpans ? 0 : null; + const replaceValue = null; // eslint-disable-next-line no-param-reassign v[1] = replaceValue; } else if (v[1] !== null) { @@ -62,17 +59,34 @@ function fillMissingXAxisTimestamps( ); } +function getStackedSeries(val: any): any { + const series = cloneDeep(val) || []; + + for (let i = series.length - 2; i >= 0; i--) { + for (let j = 0; j < series[i].length; j++) { + series[i][j] += series[i + 1][j]; + } + } + + return series; +} + export const getUPlotChartData = ( apiResponse?: MetricRangePayloadProps, fillSpans?: boolean, + stackedBarChart?: boolean, + hiddenGraph?: { + [key: string]: boolean; + }, ): any[] => { const seriesList = apiResponse?.data?.result || []; const timestampArr = getXAxisTimestamps(seriesList); - const yAxisValuesArr = fillMissingXAxisTimestamps( - timestampArr, - seriesList, - fillSpans || false, - ); + const yAxisValuesArr = fillMissingXAxisTimestamps(timestampArr, seriesList); - return [timestampArr, ...yAxisValuesArr]; + return [ + timestampArr, + ...(stackedBarChart && isUndefined(hiddenGraph) + ? getStackedSeries(yAxisValuesArr) + : yAxisValuesArr), + ]; }; diff --git a/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts b/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts index 2ff063e2ab..88e50ada6e 100644 --- a/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts +++ b/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts @@ -3,360 +3,91 @@ import { PANEL_TYPES } from 'constants/queryBuilder'; import { GetSeriesProps } from '../../getSeriesData'; export const seriesBarChartData = { - apiResponse: { - data: { - result: [ - { - metric: {}, - values: [ - [1708683840, '6260'], - [1708683240, '6251'], - [1708683780, '6237'], - [1708683660, '6188'], - [1708683720, '6176'], - [1708683360, '6169'], - [1708683480, '6068'], - [1708683540, '6025'], - [1708683300, '6042'], - [1708683420, '6001'], - [1708683600, '5969'], - [1708683900, '5955'], - [1708683180, '4301'], - ], - queryName: 'F1', - legend: 'firstLegend', - }, - { - metric: {}, - values: [ - [1708683240, '3378'], - [1708683300, '3269'], - [1708683360, '3341'], - [1708683420, '3269'], - [1708683480, '3296'], - [1708683540, '3280'], - [1708683600, '3260'], - [1708683660, '3351'], - [1708683720, '3345'], - [1708683780, '3370'], - [1708683840, '3382'], - [1708683900, '3249'], - [1708683960, '212'], - ], - queryName: 'A', - legend: 'secondLegend', - }, - { - metric: {}, - values: [ - [1708683840, '2878'], - [1708683240, '2873'], - [1708683780, '2867'], - [1708683660, '2837'], - [1708683720, '2831'], - [1708683360, '2828'], - [1708683300, '2773'], - [1708683480, '2772'], - [1708683540, '2745'], - [1708683420, '2732'], - [1708683180, '2729'], - [1708683600, '2709'], - [1708683900, '2706'], - ], - queryName: 'B', - legend: 'thirdLegend', - }, - { - metric: { - F2: 'F2', - }, - values: [ - [1708683840, '504'], - [1708683240, '505'], - [1708683780, '503'], - [1708683660, '514'], - [1708683720, '514'], - [1708683360, '513'], - [1708683480, '524'], - [1708683540, '535'], - [1708683300, '496'], - [1708683420, '537'], - [1708683600, '551'], - [1708683900, '543'], - [1708683180, '-1157'], - ], - queryName: 'F2', - legend: 'forthLength', - }, + series: [ + { + metric: {}, + values: [ + [1708683840, '6260'], + [1708683240, '6251'], + [1708683780, '6237'], + [1708683660, '6188'], + [1708683720, '6176'], + [1708683360, '6169'], + [1708683480, '6068'], + [1708683540, '6025'], + [1708683300, '6042'], + [1708683420, '6001'], + [1708683600, '5969'], + [1708683900, '5955'], + [1708683180, '4301'], ], - resultType: '', - newResult: { - status: 'success', - data: { - resultType: '', - result: [ - { - queryName: 'A', - series: [ - { - labels: {}, - labelsArray: [], - values: [ - { - timestamp: 1708683240000, - value: '3378', - }, - { - timestamp: 1708683300000, - value: '3269', - }, - { - timestamp: 1708683360000, - value: '3341', - }, - { - timestamp: 1708683420000, - value: '3269', - }, - { - timestamp: 1708683480000, - value: '3296', - }, - { - timestamp: 1708683540000, - value: '3280', - }, - { - timestamp: 1708683600000, - value: '3260', - }, - { - timestamp: 1708683660000, - value: '3351', - }, - { - timestamp: 1708683720000, - value: '3345', - }, - { - timestamp: 1708683780000, - value: '3370', - }, - { - timestamp: 1708683840000, - value: '3382', - }, - { - timestamp: 1708683900000, - value: '3249', - }, - { - timestamp: 1708683960000, - value: '212', - }, - ], - }, - ], - list: null, - }, - { - queryName: 'B', - series: [ - { - labels: {}, - labelsArray: [], - values: [ - { - timestamp: 1708683840000, - value: '2878', - }, - { - timestamp: 1708683240000, - value: '2873', - }, - { - timestamp: 1708683780000, - value: '2867', - }, - { - timestamp: 1708683660000, - value: '2837', - }, - { - timestamp: 1708683720000, - value: '2831', - }, - { - timestamp: 1708683360000, - value: '2828', - }, - { - timestamp: 1708683300000, - value: '2773', - }, - { - timestamp: 1708683480000, - value: '2772', - }, - { - timestamp: 1708683540000, - value: '2745', - }, - { - timestamp: 1708683420000, - value: '2732', - }, - { - timestamp: 1708683180000, - value: '2729', - }, - { - timestamp: 1708683600000, - value: '2709', - }, - { - timestamp: 1708683900000, - value: '2706', - }, - ], - }, - ], - list: null, - }, - { - queryName: 'F2', - series: [ - { - labels: { - F2: 'F2', - }, - values: [ - { - timestamp: 1708683840000, - value: '504', - }, - { - timestamp: 1708683240000, - value: '505', - }, - { - timestamp: 1708683780000, - value: '503', - }, - { - timestamp: 1708683660000, - value: '514', - }, - { - timestamp: 1708683720000, - value: '514', - }, - { - timestamp: 1708683360000, - value: '513', - }, - { - timestamp: 1708683480000, - value: '524', - }, - { - timestamp: 1708683540000, - value: '535', - }, - { - timestamp: 1708683300000, - value: '496', - }, - { - timestamp: 1708683420000, - value: '537', - }, - { - timestamp: 1708683600000, - value: '551', - }, - { - timestamp: 1708683900000, - value: '543', - }, - { - timestamp: 1708683180000, - value: '-1157', - }, - ], - }, - ], - list: null, - }, - { - queryName: 'F1', - series: [ - { - labels: {}, - labelsArray: null, - values: [ - { - timestamp: 1708683840000, - value: '6260', - }, - { - timestamp: 1708683240000, - value: '6251', - }, - { - timestamp: 1708683780000, - value: '6237', - }, - { - timestamp: 1708683660000, - value: '6188', - }, - { - timestamp: 1708683720000, - value: '6176', - }, - { - timestamp: 1708683360000, - value: '6169', - }, - { - timestamp: 1708683480000, - value: '6068', - }, - { - timestamp: 1708683540000, - value: '6025', - }, - { - timestamp: 1708683300000, - value: '6042', - }, - { - timestamp: 1708683420000, - value: '6001', - }, - { - timestamp: 1708683600000, - value: '5969', - }, - { - timestamp: 1708683900000, - value: '5955', - }, - { - timestamp: 1708683180000, - value: '4301', - }, - ], - }, - ], - list: null, - }, - ], - }, - }, + queryName: 'F1', + legend: 'firstLegend', }, - }, + { + metric: {}, + values: [ + [1708683240, '3378'], + [1708683300, '3269'], + [1708683360, '3341'], + [1708683420, '3269'], + [1708683480, '3296'], + [1708683540, '3280'], + [1708683600, '3260'], + [1708683660, '3351'], + [1708683720, '3345'], + [1708683780, '3370'], + [1708683840, '3382'], + [1708683900, '3249'], + [1708683960, '212'], + ], + queryName: 'A', + legend: 'secondLegend', + }, + { + metric: {}, + values: [ + [1708683840, '2878'], + [1708683240, '2873'], + [1708683780, '2867'], + [1708683660, '2837'], + [1708683720, '2831'], + [1708683360, '2828'], + [1708683300, '2773'], + [1708683480, '2772'], + [1708683540, '2745'], + [1708683420, '2732'], + [1708683180, '2729'], + [1708683600, '2709'], + [1708683900, '2706'], + ], + queryName: 'B', + legend: 'thirdLegend', + }, + { + metric: { + F2: 'F2', + }, + values: [ + [1708683840, '504'], + [1708683240, '505'], + [1708683780, '503'], + [1708683660, '514'], + [1708683720, '514'], + [1708683360, '513'], + [1708683480, '524'], + [1708683540, '535'], + [1708683300, '496'], + [1708683420, '537'], + [1708683600, '551'], + [1708683900, '543'], + [1708683180, '-1157'], + ], + queryName: 'F2', + legend: 'forthLength', + }, + ], + widgetMetaData: [ { metric: {}, @@ -443,363 +174,95 @@ export const seriesBarChartData = { ], graphsVisibilityStates: [true, true, true, true, true], panelType: PANEL_TYPES.BAR, + isDarkMode: true, } as GetSeriesProps; export const seriesLineChartData = { - apiResponse: { - data: { - result: [ - { - metric: {}, - values: [ - [1708683840, '6260'], - [1708683240, '6251'], - [1708683780, '6237'], - [1708683660, '6188'], - [1708683720, '6176'], - [1708683360, '6169'], - [1708683480, '6068'], - [1708683540, '6025'], - [1708683300, '6042'], - [1708683420, '6001'], - [1708683600, '5969'], - [1708683900, '5955'], - [1708683180, '4301'], - ], - queryName: 'F1', - legend: 'firstLegend', - }, - { - metric: {}, - values: [ - [1708683240, '3378'], - [1708683300, '3269'], - [1708683360, '3341'], - [1708683420, '3269'], - [1708683480, '3296'], - [1708683540, '3280'], - [1708683600, '3260'], - [1708683660, '3351'], - [1708683720, '3345'], - [1708683780, '3370'], - [1708683840, '3382'], - [1708683900, '3249'], - [1708683960, '212'], - ], - queryName: 'A', - legend: 'secondLegend', - }, - { - metric: {}, - values: [ - [1708683840, '2878'], - [1708683240, '2873'], - [1708683780, '2867'], - [1708683660, '2837'], - [1708683720, '2831'], - [1708683360, '2828'], - [1708683300, '2773'], - [1708683480, '2772'], - [1708683540, '2745'], - [1708683420, '2732'], - [1708683180, '2729'], - [1708683600, '2709'], - [1708683900, '2706'], - ], - queryName: 'B', - legend: 'thirdLegend', - }, - { - metric: { - F2: 'F2', - }, - values: [ - [1708683840, '504'], - [1708683240, '505'], - [1708683780, '503'], - [1708683660, '514'], - [1708683720, '514'], - [1708683360, '513'], - [1708683480, '524'], - [1708683540, '535'], - [1708683300, '496'], - [1708683420, '537'], - [1708683600, '551'], - [1708683900, '543'], - [1708683180, '-1157'], - ], - queryName: 'F2', - legend: 'forthLength', - }, + series: [ + { + metric: {}, + values: [ + [1708683840, '6260'], + [1708683240, '6251'], + [1708683780, '6237'], + [1708683660, '6188'], + [1708683720, '6176'], + [1708683360, '6169'], + [1708683480, '6068'], + [1708683540, '6025'], + [1708683300, '6042'], + [1708683420, '6001'], + [1708683600, '5969'], + [1708683900, '5955'], + [1708683180, '4301'], ], - resultType: '', - newResult: { - status: 'success', - data: { - resultType: '', - result: [ - { - queryName: 'A', - series: [ - { - labels: {}, - labelsArray: [], - values: [ - { - timestamp: 1708683240000, - value: '3378', - }, - { - timestamp: 1708683300000, - value: '3269', - }, - { - timestamp: 1708683360000, - value: '3341', - }, - { - timestamp: 1708683420000, - value: '3269', - }, - { - timestamp: 1708683480000, - value: '3296', - }, - { - timestamp: 1708683540000, - value: '3280', - }, - { - timestamp: 1708683600000, - value: '3260', - }, - { - timestamp: 1708683660000, - value: '3351', - }, - { - timestamp: 1708683720000, - value: '3345', - }, - { - timestamp: 1708683780000, - value: '3370', - }, - { - timestamp: 1708683840000, - value: '3382', - }, - { - timestamp: 1708683900000, - value: '3249', - }, - { - timestamp: 1708683960000, - value: '212', - }, - ], - }, - ], - list: null, - }, - { - queryName: 'B', - series: [ - { - labels: {}, - labelsArray: [], - values: [ - { - timestamp: 1708683840000, - value: '2878', - }, - { - timestamp: 1708683240000, - value: '2873', - }, - { - timestamp: 1708683780000, - value: '2867', - }, - { - timestamp: 1708683660000, - value: '2837', - }, - { - timestamp: 1708683720000, - value: '2831', - }, - { - timestamp: 1708683360000, - value: '2828', - }, - { - timestamp: 1708683300000, - value: '2773', - }, - { - timestamp: 1708683480000, - value: '2772', - }, - { - timestamp: 1708683540000, - value: '2745', - }, - { - timestamp: 1708683420000, - value: '2732', - }, - { - timestamp: 1708683180000, - value: '2729', - }, - { - timestamp: 1708683600000, - value: '2709', - }, - { - timestamp: 1708683900000, - value: '2706', - }, - ], - }, - ], - list: null, - }, - { - queryName: 'F2', - series: [ - { - labels: { - F2: 'F2', - }, - values: [ - { - timestamp: 1708683840000, - value: '504', - }, - { - timestamp: 1708683240000, - value: '505', - }, - { - timestamp: 1708683780000, - value: '503', - }, - { - timestamp: 1708683660000, - value: '514', - }, - { - timestamp: 1708683720000, - value: '514', - }, - { - timestamp: 1708683360000, - value: '513', - }, - { - timestamp: 1708683480000, - value: '524', - }, - { - timestamp: 1708683540000, - value: '535', - }, - { - timestamp: 1708683300000, - value: '496', - }, - { - timestamp: 1708683420000, - value: '537', - }, - { - timestamp: 1708683600000, - value: '551', - }, - { - timestamp: 1708683900000, - value: '543', - }, - { - timestamp: 1708683180000, - value: '-1157', - }, - ], - }, - ], - list: null, - }, - { - queryName: 'F1', - series: [ - { - labels: {}, - labelsArray: null, - values: [ - { - timestamp: 1708683840000, - value: '6260', - }, - { - timestamp: 1708683240000, - value: '6251', - }, - { - timestamp: 1708683780000, - value: '6237', - }, - { - timestamp: 1708683660000, - value: '6188', - }, - { - timestamp: 1708683720000, - value: '6176', - }, - { - timestamp: 1708683360000, - value: '6169', - }, - { - timestamp: 1708683480000, - value: '6068', - }, - { - timestamp: 1708683540000, - value: '6025', - }, - { - timestamp: 1708683300000, - value: '6042', - }, - { - timestamp: 1708683420000, - value: '6001', - }, - { - timestamp: 1708683600000, - value: '5969', - }, - { - timestamp: 1708683900000, - value: '5955', - }, - { - timestamp: 1708683180000, - value: '4301', - }, - ], - }, - ], - list: null, - }, - ], - }, - }, + queryName: 'F1', + legend: 'firstLegend', }, - }, + { + metric: {}, + values: [ + [1708683240, '3378'], + [1708683300, '3269'], + [1708683360, '3341'], + [1708683420, '3269'], + [1708683480, '3296'], + [1708683540, '3280'], + [1708683600, '3260'], + [1708683660, '3351'], + [1708683720, '3345'], + [1708683780, '3370'], + [1708683840, '3382'], + [1708683900, '3249'], + [1708683960, '212'], + ], + queryName: 'A', + legend: 'secondLegend', + }, + { + metric: {}, + values: [ + [1708683840, '2878'], + [1708683240, '2873'], + [1708683780, '2867'], + [1708683660, '2837'], + [1708683720, '2831'], + [1708683360, '2828'], + [1708683300, '2773'], + [1708683480, '2772'], + [1708683540, '2745'], + [1708683420, '2732'], + [1708683180, '2729'], + [1708683600, '2709'], + [1708683900, '2706'], + ], + queryName: 'B', + legend: 'thirdLegend', + }, + { + metric: { + F2: 'F2', + }, + values: [ + [1708683840, '504'], + [1708683240, '505'], + [1708683780, '503'], + [1708683660, '514'], + [1708683720, '514'], + [1708683360, '513'], + [1708683480, '524'], + [1708683540, '535'], + [1708683300, '496'], + [1708683420, '537'], + [1708683600, '551'], + [1708683900, '543'], + [1708683180, '-1157'], + ], + queryName: 'F2', + legend: 'forthLength', + }, + ], + widgetMetaData: [ { metric: {}, @@ -886,4 +349,5 @@ export const seriesLineChartData = { ], graphsVisibilityStates: [true, true, true, true, true], panelType: PANEL_TYPES.TIME_SERIES, + isDarkMode: false, } as GetSeriesProps; diff --git a/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts b/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts index 75ee3c7f58..199df6f540 100644 --- a/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts +++ b/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts @@ -27,6 +27,7 @@ describe('Get Series Data', () => { test('Should return seris drawline line chart for panel type time series', () => { const seriesData = getSeries(seriesLineChartData); // @ts-ignore + expect(seriesData[1].drawStyle).toBe('line'); }); }); diff --git a/frontend/src/pages/LogsExplorer/index.tsx b/frontend/src/pages/LogsExplorer/index.tsx index 0cc2c07b4d..d8f5f38804 100644 --- a/frontend/src/pages/LogsExplorer/index.tsx +++ b/frontend/src/pages/LogsExplorer/index.tsx @@ -1,5 +1,6 @@ import './LogsExplorer.styles.scss'; +import * as Sentry from '@sentry/react'; import ExplorerCard from 'components/ExplorerCard/ExplorerCard'; import LogExplorerQuerySection from 'container/LogExplorerQuerySection'; import LogsExplorerViews from 'container/LogsExplorerViews'; @@ -9,7 +10,6 @@ import Toolbar from 'container/Toolbar/Toolbar'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { useEffect, useMemo, useState } from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; import { DataSource } from 'types/common/queryBuilder'; import { WrapperStyled } from './styles'; @@ -70,7 +70,7 @@ function LogsExplorer(): JSX.Element { ); return ( - + }>
- + ); } diff --git a/frontend/src/pages/LogsExplorer/utils.ts b/frontend/src/pages/LogsExplorer/utils.ts index 485aa22eef..0fedaaece4 100644 --- a/frontend/src/pages/LogsExplorer/utils.ts +++ b/frontend/src/pages/LogsExplorer/utils.ts @@ -4,7 +4,7 @@ export const prepareQueryWithDefaultTimestamp = (query: Query): Query => ({ ...query, builder: { ...query.builder, - queryData: query.builder.queryData.map((item) => ({ + queryData: query.builder.queryData?.map((item) => ({ ...item, orderBy: [{ columnName: 'timestamp', order: 'desc' }], })), diff --git a/frontend/src/pages/Pipelines/index.tsx b/frontend/src/pages/Pipelines/index.tsx index 81b3b503f9..a1ae05c30c 100644 --- a/frontend/src/pages/Pipelines/index.tsx +++ b/frontend/src/pages/Pipelines/index.tsx @@ -1,5 +1,6 @@ import './Pipelines.styles.scss'; +import * as Sentry from '@sentry/react'; import type { TabsProps } from 'antd'; import { Tabs } from 'antd'; import getPipeline from 'api/pipeline/get'; @@ -9,7 +10,6 @@ import PipelinePage from 'container/PipelinePage/Layouts/Pipeline'; import { useNotifications } from 'hooks/useNotifications'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { useEffect, useMemo } from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; import { useTranslation } from 'react-i18next'; import { useQuery } from 'react-query'; import { SuccessResponse } from 'types/api'; @@ -82,13 +82,13 @@ function Pipelines(): JSX.Element { } return ( - + }> - + ); } diff --git a/frontend/src/pages/ServiceTopLevelOperations/ServiceTopLevelOperations.styles.scss b/frontend/src/pages/ServiceTopLevelOperations/ServiceTopLevelOperations.styles.scss new file mode 100644 index 0000000000..e7c5dfcda4 --- /dev/null +++ b/frontend/src/pages/ServiceTopLevelOperations/ServiceTopLevelOperations.styles.scss @@ -0,0 +1,26 @@ +.title { + font-weight: 500; + font-size: 14px; + + margin: 16px 0; +} + +.info-alert { + margin: 16px 0; +} + +.top-level-operations-header { + display: flex; + align-items: center; + gap: 8px; +} + +.breadcrumb { + display: inline-flex; + align-items: center; + gap: 8px; +} + +.top-level-operations-list { + margin-top: 16px; +} diff --git a/frontend/src/pages/ServiceTopLevelOperations/index.tsx b/frontend/src/pages/ServiceTopLevelOperations/index.tsx new file mode 100644 index 0000000000..38a2ae2807 --- /dev/null +++ b/frontend/src/pages/ServiceTopLevelOperations/index.tsx @@ -0,0 +1,142 @@ +import './ServiceTopLevelOperations.styles.scss'; + +import { SyncOutlined } from '@ant-design/icons'; +import { Alert, Table, Typography } from 'antd'; +import ROUTES from 'constants/routes'; +import { IServiceName } from 'container/MetricsApplication/Tabs/types'; +import useErrorNotification from 'hooks/useErrorNotification'; +import { useQueryService } from 'hooks/useQueryService'; +import useResourceAttribute from 'hooks/useResourceAttribute'; +import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils'; +import { BarChart2 } from 'lucide-react'; +import { ReactNode, useEffect, useMemo, useState } from 'react'; +import { useSelector } from 'react-redux'; +import { Link, useParams } from 'react-router-dom'; +import { AppState } from 'store/reducers'; +import { GlobalReducer } from 'types/reducer/globalTime'; +import { Tags } from 'types/reducer/trace'; + +export default function ServiceTopLevelOperations(): JSX.Element { + const { servicename: encodedServiceName } = useParams(); + const { maxTime, minTime, selectedTime } = useSelector< + AppState, + GlobalReducer + >((state) => state.globalTime); + const servicename = decodeURIComponent(encodedServiceName); + const { queries } = useResourceAttribute(); + const selectedTags = useMemo( + () => (convertRawQueriesToTraceSelectedTags(queries) as Tags[]) || [], + [queries], + ); + + const [topLevelOperations, setTopLevelOperations] = useState([]); + + const { data, error, isLoading } = useQueryService({ + minTime, + maxTime, + selectedTime, + selectedTags, + }); + + useErrorNotification(error); + + useEffect(() => { + const selectedService = data?.find( + (service) => service.serviceName === servicename, + ); + + setTopLevelOperations(selectedService?.dataWarning?.topLevelOps || []); + }, [servicename, data]); + + const alertDesc = (): ReactNode => ( +
+ SigNoz calculates the RED metrics for a service using the entry-point spans. + For more details, you can check out our + + {' '} + docs + + . We expect the number of unique entry-point operations to be no more than + 2500. The high number of top level operations might be due to an + instrumentation issue in your service. Below table shows the sample top level + operations. Please refer to official docs for span name guidelines{' '} + + {' '} + here + {' '} + and update the instrumentation to to follow the guidelines. If there are any + dynamic IDs in the span name, make sure to use the span attributes instead. + If you have more questions, please reach out to us via support. +
+ ); + + const columns = [ + { + title: 'Top Level Operation', + key: 'top-level-operation', + render: (operation: string): JSX.Element => ( +
+ {operation} +
+ ), + }, + ]; + + return ( +
+ + + + {' '} + services{' '} + + +
/
+ + {servicename} + +
+ +
+ +
+ + {isLoading && ( +
+ + Loading ... + +
+ )} + + {!isLoading && ( +
+ 'Top Level Operations'} + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + dataSource={topLevelOperations} + loading={isLoading} + showHeader={false} + pagination={{ + pageSize: 100, + hideOnSinglePage: true, + showTotal: (total: number, range: number[]): string => + `${range[0]}-${range[1]} of ${total}`, + }} + /> + + )} + + ); +} diff --git a/frontend/src/pages/Support/Support.tsx b/frontend/src/pages/Support/Support.tsx index 96276507f9..2d156a3816 100644 --- a/frontend/src/pages/Support/Support.tsx +++ b/frontend/src/pages/Support/Support.tsx @@ -10,6 +10,8 @@ import { MessageSquare, Slack, } from 'lucide-react'; +import { useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; const { Title, Text } = Typography; @@ -84,11 +86,24 @@ const supportChannels = [ export default function Support(): JSX.Element { const { trackEvent } = useAnalytics(); + const history = useHistory(); const handleChannelWithRedirects = (url: string): void => { window.open(url, '_blank'); }; + useEffect(() => { + if (history?.location?.state) { + const histroyState = history?.location?.state as any; + + if (histroyState && histroyState?.from) { + trackEvent(`Support : From URL : ${histroyState.from}`); + } + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + const handleSlackConnectRequest = (): void => { const recipient = 'support@signoz.io'; const subject = 'Slack Connect Request'; diff --git a/frontend/src/pages/Trace/index.tsx b/frontend/src/pages/Trace/index.tsx index 75bf58f1bd..3d31271c18 100644 --- a/frontend/src/pages/Trace/index.tsx +++ b/frontend/src/pages/Trace/index.tsx @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/react'; import { Card } from 'antd'; import { NotificationInstance } from 'antd/es/notification/interface'; import ROUTES from 'constants/routes'; @@ -11,7 +12,6 @@ import getStep from 'lib/getStep'; import history from 'lib/history'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { MouseEventHandler, useCallback, useEffect, useState } from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; import { connect, useDispatch, useSelector } from 'react-redux'; import { bindActionCreators, Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; @@ -146,7 +146,7 @@ function Trace({ ); return ( - + }>
@@ -169,7 +169,7 @@ function Trace({ - + ); } diff --git a/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts b/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts index ede7615e47..86b52fdbb0 100644 --- a/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts +++ b/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts @@ -328,17 +328,17 @@ export function unionTagFilterItems( ): TagFilterItem[] { const unionMap = new Map(); - items1.forEach((item) => { - const keyOp = `${item?.key?.key}_${item.op}`; + items1?.forEach((item) => { + const keyOp = `${item?.key?.key}_${item?.op}`; unionMap.set(keyOp, item); }); - items2.forEach((item) => { - const keyOp = `${item?.key?.key}_${item.op}`; + items2?.forEach((item) => { + const keyOp = `${item?.key?.key}_${item?.op}`; unionMap.set(keyOp, item); }); - return Array.from(unionMap.values()); + return Array.from(unionMap?.values()); } export interface HandleRunProps { diff --git a/frontend/src/pages/TracesExplorer/index.tsx b/frontend/src/pages/TracesExplorer/index.tsx index 6c4057332f..ab022bfeee 100644 --- a/frontend/src/pages/TracesExplorer/index.tsx +++ b/frontend/src/pages/TracesExplorer/index.tsx @@ -1,15 +1,19 @@ import './TracesExplorer.styles.scss'; import { FilterOutlined } from '@ant-design/icons'; +import * as Sentry from '@sentry/react'; import { Button, Card, Tabs, Tooltip } from 'antd'; import axios from 'axios'; import ExplorerCard from 'components/ExplorerCard/ExplorerCard'; +import { LOCALSTORAGE } from 'constants/localStorage'; import { AVAILABLE_EXPORT_PANEL_TYPES } from 'constants/panelTypes'; import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper'; import ExportPanel from 'container/ExportPanel'; +import { useOptionsMenu } from 'container/OptionsMenu'; import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions'; import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2'; +import { defaultSelectedColumns } from 'container/TracesExplorer/ListView/configs'; import QuerySection from 'container/TracesExplorer/QuerySection'; import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard'; import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils'; @@ -19,10 +23,11 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; +import { cloneDeep, set } from 'lodash-es'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { useCallback, useEffect, useMemo, useState } from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; import { Dashboard } from 'types/api/dashboard/getAll'; +import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { DataSource } from 'types/common/queryBuilder'; import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink'; import { v4 } from 'uuid'; @@ -42,6 +47,15 @@ function TracesExplorer(): JSX.Element { stagedQuery, } = useQueryBuilder(); + const { options } = useOptionsMenu({ + storageKey: LOCALSTORAGE.TRACES_LIST_OPTIONS, + dataSource: DataSource.TRACES, + aggregateOperator: 'noop', + initialOptions: { + selectColumns: defaultSelectedColumns, + }, + }); + const currentPanelType = useGetPanelTypesQueryParam(); const { handleExplorerTabChange } = useHandleExplorerTabChange(); @@ -101,6 +115,18 @@ function TracesExplorer(): JSX.Element { const { mutate: updateDashboard, isLoading } = useUpdateDashboard(); + const getUpdatedQueryForExport = (): Query => { + const updatedQuery = cloneDeep(currentQuery); + + set( + updatedQuery, + 'builder.queryData[0].selectColumns', + options.selectColumns, + ); + + return updatedQuery; + }; + const handleExport = useCallback( (dashboard: Dashboard | null): void => { if (!dashboard || !panelType) return; @@ -111,11 +137,17 @@ function TracesExplorer(): JSX.Element { const widgetId = v4(); + const query = + panelType === PANEL_TYPES.LIST + ? getUpdatedQueryForExport() + : exportDefaultQuery; + const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( dashboard, - exportDefaultQuery, + query, widgetId, panelTypeParam, + options.selectColumns, ); updateDashboard(updatedDashboard, { @@ -144,7 +176,7 @@ function TracesExplorer(): JSX.Element { return; } const dashboardEditView = generateExportToDashboardLink({ - query: exportDefaultQuery, + query, panelType: panelTypeParam, dashboardId: data.payload?.uuid || '', widgetId, @@ -161,6 +193,7 @@ function TracesExplorer(): JSX.Element { }, }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [exportDefaultQuery, notifications, panelType, updateDashboard], ); @@ -185,7 +218,7 @@ function TracesExplorer(): JSX.Element { const [isOpen, setOpen] = useState(true); return ( - + }>
-
+ ); } diff --git a/frontend/src/providers/Dashboard/Dashboard.tsx b/frontend/src/providers/Dashboard/Dashboard.tsx index 0f8307aaa1..6e15b9e3b2 100644 --- a/frontend/src/providers/Dashboard/Dashboard.tsx +++ b/frontend/src/providers/Dashboard/Dashboard.tsx @@ -9,6 +9,7 @@ import dayjs, { Dayjs } from 'dayjs'; import { useDashboardVariablesFromLocalStorage } from 'hooks/dashboard/useDashboardFromLocalStorage'; import useAxiosError from 'hooks/useAxiosError'; import useTabVisibility from 'hooks/useTabFocus'; +import useUrlQuery from 'hooks/useUrlQuery'; import { getUpdatedLayout } from 'lib/dashboard/getUpdatedLayout'; import { defaultTo } from 'lodash-es'; import isEqual from 'lodash-es/isEqual'; @@ -51,6 +52,8 @@ const DashboardContext = createContext({ layouts: [], panelMap: {}, setPanelMap: () => {}, + listSortOrder: { columnKey: 'createdAt', order: 'descend', pagination: '1' }, + setListSortOrder: () => {}, setLayouts: () => {}, setSelectedDashboard: () => {}, updatedTimeRef: {} as React.MutableRefObject, @@ -79,6 +82,17 @@ export function DashboardProvider({ exact: true, }); + const params = useUrlQuery(); + const orderColumnParam = params.get('columnKey'); + const orderQueryParam = params.get('order'); + const paginationParam = params.get('page'); + + const [listSortOrder, setListSortOrder] = useState({ + columnKey: orderColumnParam || 'updatedAt', + order: orderQueryParam || 'descend', + pagination: paginationParam || '1', + }); + const dispatch = useDispatch>(); const globalTime = useSelector( @@ -341,6 +355,8 @@ export function DashboardProvider({ selectedDashboard, dashboardId, layouts, + listSortOrder, + setListSortOrder, panelMap, setLayouts, setPanelMap, @@ -359,6 +375,8 @@ export function DashboardProvider({ selectedDashboard, dashboardId, layouts, + listSortOrder, + setListSortOrder, panelMap, toScrollWidgetId, updateLocalStorageDashboardVariables, diff --git a/frontend/src/providers/Dashboard/types.ts b/frontend/src/providers/Dashboard/types.ts index 6f78d804b1..d72c1839f5 100644 --- a/frontend/src/providers/Dashboard/types.ts +++ b/frontend/src/providers/Dashboard/types.ts @@ -1,4 +1,5 @@ import dayjs from 'dayjs'; +import { Dispatch, SetStateAction } from 'react'; import { Layout } from 'react-grid-layout'; import { UseQueryResult } from 'react-query'; import { Dashboard } from 'types/api/dashboard/getAll'; @@ -14,6 +15,18 @@ export interface IDashboardContext { layouts: Layout[]; panelMap: Record; setPanelMap: React.Dispatch>>; + listSortOrder: { + columnKey: string; + order: string; + pagination: string; + }; + setListSortOrder: Dispatch< + SetStateAction<{ + columnKey: string; + order: string; + pagination: string; + }> + >; setLayouts: React.Dispatch>; setSelectedDashboard: React.Dispatch< React.SetStateAction diff --git a/frontend/src/providers/QueryBuilder.tsx b/frontend/src/providers/QueryBuilder.tsx index 77fa791b14..5e1eda5714 100644 --- a/frontend/src/providers/QueryBuilder.tsx +++ b/frontend/src/providers/QueryBuilder.tsx @@ -148,13 +148,13 @@ export function QueryBuilderProvider({ const prepareQueryBuilderData = useCallback( (query: Query): Query => { const builder: QueryBuilderData = { - queryData: query.builder.queryData.map((item) => ({ + queryData: query.builder.queryData?.map((item) => ({ ...initialQueryBuilderFormValuesMap[ initialDataSource || DataSource.METRICS ], ...item, })), - queryFormulas: query.builder.queryFormulas.map((item) => ({ + queryFormulas: query.builder.queryFormulas?.map((item) => ({ ...initialFormulaBuilderFormValues, ...item, })), @@ -236,7 +236,7 @@ export function QueryBuilderProvider({ const updateAllQueriesOperators = useCallback( (query: Query, panelType: PANEL_TYPES, dataSource: DataSource): Query => { - const queryData = query.builder.queryData.map((item) => + const queryData = query.builder.queryData?.map((item) => getElementWithActualOperator(item, dataSource, panelType), ); @@ -682,7 +682,7 @@ export function QueryBuilderProvider({ : query.queryType; const builder = - !query.builder || query.builder.queryData.length === 0 + !query.builder || query.builder.queryData?.length === 0 ? initialQueryState.builder : query.builder; @@ -752,26 +752,30 @@ export function QueryBuilderProvider({ [], ); - const handleRunQuery = useCallback(() => { - redirectWithQueryBuilderData({ - ...{ - ...currentQuery, - ...updateStepInterval( - { - builder: currentQuery.builder, - clickhouse_sql: currentQuery.clickhouse_sql, - promql: currentQuery.promql, - id: currentQuery.id, - queryType, - unit: currentQuery.unit, - }, - maxTime, - minTime, - ), - }, - queryType, - }); - }, [currentQuery, queryType, maxTime, minTime, redirectWithQueryBuilderData]); + const handleRunQuery = useCallback( + (shallUpdateStepInterval?: boolean) => { + redirectWithQueryBuilderData({ + ...{ + ...currentQuery, + ...updateStepInterval( + { + builder: currentQuery.builder, + clickhouse_sql: currentQuery.clickhouse_sql, + promql: currentQuery.promql, + id: currentQuery.id, + queryType, + unit: currentQuery.unit, + }, + maxTime, + minTime, + !!shallUpdateStepInterval, + ), + }, + queryType, + }); + }, + [currentQuery, queryType, maxTime, minTime, redirectWithQueryBuilderData], + ); useEffect(() => { if (!compositeQueryParam) return; diff --git a/frontend/src/types/api/dashboard/getAll.ts b/frontend/src/types/api/dashboard/getAll.ts index af254e032e..c73884c926 100644 --- a/frontend/src/types/api/dashboard/getAll.ts +++ b/frontend/src/types/api/dashboard/getAll.ts @@ -97,6 +97,7 @@ export interface IBaseWidget { timePreferance: timePreferenceType; stepSize?: number; yAxisUnit?: string; + stackedBarChart?: boolean; bucketCount?: number; bucketWidth?: number; mergeAllActiveQueries?: boolean; diff --git a/frontend/src/types/api/metrics/getQueryRange.ts b/frontend/src/types/api/metrics/getQueryRange.ts index b5dcba2d77..5409eba346 100644 --- a/frontend/src/types/api/metrics/getQueryRange.ts +++ b/frontend/src/types/api/metrics/getQueryRange.ts @@ -18,6 +18,7 @@ export type QueryRangePayload = { promQueries?: Record; queryType: EQueryType; panelType: PANEL_TYPES; + fillGaps?: boolean; }; end: number; start: number; diff --git a/frontend/src/types/api/metrics/getService.ts b/frontend/src/types/api/metrics/getService.ts index bb9d6db941..d931197433 100644 --- a/frontend/src/types/api/metrics/getService.ts +++ b/frontend/src/types/api/metrics/getService.ts @@ -15,6 +15,9 @@ export interface ServicesList { callRate: number; numErrors: number; errorRate: number; + dataWarning?: { + topLevelOps?: string[]; + }; } export type PayloadProps = ServicesList[]; diff --git a/frontend/src/types/api/queryBuilder/queryBuilderData.ts b/frontend/src/types/api/queryBuilder/queryBuilderData.ts index 6a54254617..832bd09411 100644 --- a/frontend/src/types/api/queryBuilder/queryBuilderData.ts +++ b/frontend/src/types/api/queryBuilder/queryBuilderData.ts @@ -74,6 +74,7 @@ export type IBuilderQuery = { legend: string; pageSize?: number; offset?: number; + selectColumns?: BaseAutocompleteData[]; }; export interface IClickHouseQuery { diff --git a/frontend/src/types/common/queryBuilder.ts b/frontend/src/types/common/queryBuilder.ts index 6ba9faf3be..7d566283e6 100644 --- a/frontend/src/types/common/queryBuilder.ts +++ b/frontend/src/types/common/queryBuilder.ts @@ -222,7 +222,7 @@ export type QueryBuilderContextType = { redirectToUrl?: typeof ROUTES[keyof typeof ROUTES], shallStringify?: boolean, ) => void; - handleRunQuery: () => void; + handleRunQuery: (shallUpdateStepInterval?: boolean) => void; resetQuery: (newCurrentQuery?: QueryState) => void; handleOnUnitsChange: (units: Format['id']) => void; updateAllQueriesOperators: ( diff --git a/frontend/src/utils/permission/index.ts b/frontend/src/utils/permission/index.ts index 1c992965d4..44757e3508 100644 --- a/frontend/src/utils/permission/index.ts +++ b/frontend/src/utils/permission/index.ts @@ -97,4 +97,5 @@ export const routePermission: Record = { OLD_LOGS_EXPLORER: [], SHORTCUTS: ['ADMIN', 'EDITOR', 'VIEWER'], INTEGRATIONS: ['ADMIN', 'EDITOR', 'VIEWER'], + SERVICE_TOP_LEVEL_OPERATIONS: ['ADMIN', 'EDITOR', 'VIEWER'], }; diff --git a/go.mod b/go.mod index a8de8d1c41..4a52cead08 100644 --- a/go.mod +++ b/go.mod @@ -6,23 +6,22 @@ require ( github.com/ClickHouse/clickhouse-go/v2 v2.20.0 github.com/DATA-DOG/go-sqlmock v1.5.2 github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd - github.com/SigNoz/signoz-otel-collector v0.88.26 + github.com/SigNoz/signoz-otel-collector v0.102.0 github.com/SigNoz/zap_otlp/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974 github.com/SigNoz/zap_otlp/zap_otlp_sync v0.0.0-20230822164844-1b861a431974 github.com/antonmedv/expr v1.15.3 github.com/auth0/go-jwt-middleware v1.0.1 github.com/cespare/xxhash v1.1.0 - github.com/coreos/go-oidc/v3 v3.4.0 + github.com/coreos/go-oidc/v3 v3.10.0 github.com/dustin/go-humanize v1.0.1 github.com/go-co-op/gocron v1.30.1 - github.com/go-kit/kit v0.13.0 github.com/go-kit/log v0.2.1 github.com/go-redis/redis/v8 v8.11.5 github.com/go-redis/redismock/v8 v8.11.5 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.5.1 - github.com/gorilla/mux v1.8.0 + github.com/gorilla/mux v1.8.1 github.com/gosimple/slug v1.10.0 github.com/jmoiron/sqlx v1.3.4 github.com/json-iterator/go v1.1.12 @@ -30,18 +29,18 @@ require ( github.com/mailru/easyjson v0.7.7 github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/minio/minio-go/v6 v6.0.57 - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 + github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c github.com/oklog/oklog v0.3.2 github.com/open-telemetry/opamp-go v0.5.0 - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.88.0 - github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.88.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0 + github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.102.0 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/posthog/posthog-go v0.0.0-20220817142604-0b0bbf0f9c0f - github.com/prometheus/common v0.44.0 + github.com/prometheus/common v0.54.0 github.com/prometheus/prometheus v2.5.0+incompatible - github.com/rs/cors v1.10.1 + github.com/rs/cors v1.11.0 github.com/russellhaering/gosaml2 v0.9.0 github.com/russellhaering/goxmldsig v1.2.0 github.com/samber/lo v1.38.1 @@ -49,94 +48,91 @@ require ( github.com/smartystreets/goconvey v1.8.1 github.com/soheilhy/cmux v0.1.5 github.com/srikanthccv/ClickHouse-go-mock v0.7.0 - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.88.0 - go.opentelemetry.io/collector/confmap v0.88.0 - go.opentelemetry.io/collector/connector v0.88.0 - go.opentelemetry.io/collector/consumer v0.88.0 - go.opentelemetry.io/collector/exporter v0.88.0 - go.opentelemetry.io/collector/extension v0.88.0 - go.opentelemetry.io/collector/otelcol v0.88.0 - go.opentelemetry.io/collector/pdata v1.3.0 - go.opentelemetry.io/collector/processor v0.88.0 - go.opentelemetry.io/collector/receiver v0.88.0 - go.opentelemetry.io/collector/service v0.88.0 - go.opentelemetry.io/otel v1.24.0 - go.opentelemetry.io/otel/sdk v1.23.1 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.102.1 + go.opentelemetry.io/collector/confmap v0.102.1 + go.opentelemetry.io/collector/confmap/converter/expandconverter v0.102.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.102.0 + go.opentelemetry.io/collector/connector v0.102.0 + go.opentelemetry.io/collector/consumer v0.102.1 + go.opentelemetry.io/collector/exporter v0.102.0 + go.opentelemetry.io/collector/extension v0.102.1 + go.opentelemetry.io/collector/otelcol v0.102.0 + go.opentelemetry.io/collector/pdata v1.9.0 + go.opentelemetry.io/collector/processor v0.102.0 + go.opentelemetry.io/collector/receiver v0.102.0 + go.opentelemetry.io/collector/service v0.102.0 + go.opentelemetry.io/otel v1.27.0 + go.opentelemetry.io/otel/sdk v1.27.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.21.0 - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 - golang.org/x/net v0.23.0 - golang.org/x/oauth2 v0.16.0 - google.golang.org/grpc v1.62.0 - google.golang.org/protobuf v1.33.0 + golang.org/x/crypto v0.24.0 + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 + golang.org/x/net v0.26.0 + golang.org/x/oauth2 v0.21.0 + golang.org/x/text v0.16.0 + google.golang.org/grpc v1.64.0 + google.golang.org/protobuf v1.34.1 gopkg.in/segmentio/analytics-go.v3 v3.1.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/apimachinery v0.28.2 + k8s.io/apimachinery v0.29.3 ) require ( - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - golang.org/x/tools v0.16.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect -) - -require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/ClickHouse/ch-go v0.61.3 // indirect - github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect github.com/andybalholm/brotli v1.1.0 // indirect - github.com/aws/aws-sdk-go v1.45.26 // indirect + github.com/aws/aws-sdk-go v1.53.16 // indirect github.com/beevik/etree v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dennwc/varint v1.0.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/expr-lang/expr v1.16.9 // indirect + github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.7.1 // indirect + github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosimple/unidecode v1.0.0 // indirect - github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/influxdata/go-syslog/v3 v3.0.1-0.20210608084020-ac565dc76ba6 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/klauspost/cpuid v1.2.3 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.1 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/leodido/go-syslog/v4 v4.1.0 // indirect + github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect + github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/minio/md5-simd v1.1.0 // indirect github.com/minio/sha256-simd v0.1.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -146,69 +142,67 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/oklog/run v1.1.0 // indirect - github.com/oklog/ulid v1.3.1 // indirect - github.com/onsi/gomega v1.19.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.88.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.102.0 // indirect github.com/paulmach/orb v0.11.1 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/client_golang v1.17.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect + github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect + github.com/prometheus/procfs v0.15.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/backo-go v1.0.1 // indirect - github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shirou/gopsutil/v3 v3.24.4 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smarty/assertions v1.15.0 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect + github.com/valyala/fastjson v1.6.4 // indirect github.com/vjeantet/grok v1.0.1 // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect - github.com/yusufpapurcu/wmi v1.2.3 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector v0.88.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.88.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 // indirect - go.opentelemetry.io/collector/semconv v0.88.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.20.0 // indirect - go.opentelemetry.io/otel/bridge/opencensus v0.42.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/otlp/otlptrace v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/collector v0.102.1 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.102.1 // indirect + go.opentelemetry.io/collector/confmap/provider/envprovider v0.102.0 // indirect + go.opentelemetry.io/collector/confmap/provider/httpprovider v0.102.0 // indirect + go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.102.0 // indirect + go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.102.0 // indirect + go.opentelemetry.io/collector/featuregate v1.9.0 // indirect + go.opentelemetry.io/collector/semconv v0.102.0 // indirect + go.opentelemetry.io/contrib/config v0.7.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.27.0 // indirect + go.opentelemetry.io/otel/bridge/opencensus v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.49.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect go.uber.org/atomic v1.11.0 // indirect - go.uber.org/goleak v1.3.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect - gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/time v0.5.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect + k8s.io/client-go v0.29.3 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect ) -replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.11.0 +replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.11.1 diff --git a/go.sum b/go.sum index e6d22788a4..cb3f0f902e 100644 --- a/go.sum +++ b/go.sum @@ -13,36 +13,14 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -52,42 +30,30 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/ch-go v0.61.3 h1:MmBwUhXrAOBZK7n/sWBzq6FdIQ01cuF2SaaO8KlDRzI= github.com/ClickHouse/ch-go v0.61.3/go.mod h1:1PqXjMz/7S1ZUaKvwPA3i35W2bz2mAMFeCi6DIXgGwQ= github.com/ClickHouse/clickhouse-go/v2 v2.20.0 h1:bvlLQ31XJfl7MxIqAq2l1G6JhHYzqEXdvfpMeU6bkKc= github.com/ClickHouse/clickhouse-go/v2 v2.20.0/go.mod h1:VQfyA+tCwCRw2G7ogfY8V0fq/r0yJWzy8UDrjiP/Lbs= +github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU= +github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= @@ -96,10 +62,10 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd h1:Bk43AsDYe0fhkbj57eGXx8H3ZJ4zhmQXBnrW523ktj8= github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd/go.mod h1:nxRcH/OEdM8QxzH37xkGzomr1O0JpYBRS6pwjsWW6Pc= -github.com/SigNoz/prometheus v1.11.0 h1:toX7fU2wqY1TnzvPzDglIYx6OxpqrZ0NNlM/H5S5+u8= -github.com/SigNoz/prometheus v1.11.0/go.mod h1:MffmFu2qFILQrOHehx3D0XjYtaZMVfI+Ppeiv98x4Ww= -github.com/SigNoz/signoz-otel-collector v0.88.26 h1:+dbBOzIN6nKWD6DSAbsTtm9fcsUC5dSkhDLk6IfQuxg= -github.com/SigNoz/signoz-otel-collector v0.88.26/go.mod h1:sT1EM9PFDaOJLbAz5npWpgXK6OhpWJ9PpSwyhHWs9rU= +github.com/SigNoz/prometheus v1.11.1 h1:roM8ugYf4UxaeKKujEeBvoX7ybq3IrS+TB26KiRtIJg= +github.com/SigNoz/prometheus v1.11.1/go.mod h1:uv4mQwZQtx7y4GQ6EdHOi8Wsk07uHNn2XHd1zM85m6I= +github.com/SigNoz/signoz-otel-collector v0.102.0 h1:v6ap+gdvrKklMwU+M9FJgrn28vN0YxrINl3kvdcLonA= +github.com/SigNoz/signoz-otel-collector v0.102.0/go.mod h1:kCx5BfzDujq6C0+kotiqLp5COG2ut4Cb039+55rbWE0= github.com/SigNoz/zap_otlp v0.1.0 h1:T7rRcFN87GavY8lDGZj0Z3Xv6OhJA6Pj3I9dNPmqvRc= github.com/SigNoz/zap_otlp v0.1.0/go.mod h1:lcHvbDbRgvDnPxo9lDlaL1JK2PyOyouP/C3ynnYIvyo= github.com/SigNoz/zap_otlp/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974 h1:PKVgdf83Yw+lZJbFtNGBgqXiXNf3+kOXW2qZ7Ms7OaY= @@ -111,8 +77,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs= +github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -127,8 +93,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI github.com/auth0/go-jwt-middleware v1.0.1 h1:/fsQ4vRr4zod1wKReUH+0A3ySRjGiT9G34kypO/EKwI= github.com/auth0/go-jwt-middleware v1.0.1/go.mod h1:YSeUX3z6+TF2H+7padiEqNJ73Zy9vXW72U//IgN0BIM= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.45.26 h1:PJ2NJNY5N/yeobLYe1Y+xLdavBi67ZI8gvph6ftwVCg= -github.com/aws/aws-sdk-go v1.45.26/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.53.16 h1:8oZjKQO/ml1WLUZw5hvF7pvYjPf8o9f57Wldoy/q9Qc= +github.com/aws/aws-sdk-go v1.53.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= @@ -139,6 +105,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72H github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -148,36 +116,29 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 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-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -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-20211001041855-01bcc9b48dfe/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-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= -github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g= -github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= +github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -187,14 +148,12 @@ github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/digitalocean/godo v1.99.0 h1:gUHO7n9bDaZFWvbzOum4bXE0/09ZuYA9yA8idQHX57E= -github.com/digitalocean/godo v1.99.0/go.mod h1:SsS2oXo2rznfM/nORlZ/6JaUJZFhmKTib1YhopUc8NA= +github.com/digitalocean/godo v1.117.0 h1:WVlTe09melDYTd7VCVyvHcNWbgB+uI1O115+5LOtdSw= +github.com/digitalocean/godo v1.117.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ= -github.com/docker/docker v25.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo= +github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -209,32 +168,31 @@ github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr 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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -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.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= +github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8= github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-co-op/gocron v1.30.1 h1:tjWUvJl5KrcwpkEkSXFSQFr4F9h5SfV/m4+RX0cV2fs= github.com/go-co-op/gocron v1.30.1/go.mod h1:39f6KNSGVOU1LO/ZOoZfcSxwlsJDQOKSu8erN0SH48Y= @@ -245,47 +203,46 @@ github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7F github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= +github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= -github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= 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-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= +github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redismock/v8 v8.11.5 h1:RJFIiua58hrBrSpXhnGX3on79AU3S271H4ZhRI1wyVo= github.com/go-redis/redismock/v8 v8.11.5/go.mod h1:UaAU9dEe1C+eGr+FHV5prCWIt0hafyPWbGMEWE0UWdA= -github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g= +github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -294,11 +251,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -311,8 +266,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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= @@ -328,12 +281,10 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD 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.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -353,7 +304,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -364,8 +314,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -373,29 +321,15 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= -github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/gophercloud/gophercloud v1.12.0 h1:Jrz16vPAL93l80q16fp8NplrTCp93y7rZh2P3Q4Yq7g= +github.com/gophercloud/gophercloud v1.12.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= @@ -403,23 +337,23 @@ github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfre github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosimple/slug v1.10.0 h1:3XbiQua1IpCdrvuntWvGBxVm+K99wCSxJjlxkP49GGQ= github.com/gosimple/slug v1.10.0/go.mod h1:MICb3w495l9KNdZm+Xn5b6T2Hn831f9DMxiJ1r+bAjw= github.com/gosimple/unidecode v1.0.0 h1:kPdvM+qy0tnk4/BrnkrbdJ82xe88xn7c9hcaipDz4dQ= github.com/gosimple/unidecode v1.0.0/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= -github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= -github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= +github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc= +github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= @@ -433,8 +367,8 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -456,6 +390,8 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= @@ -465,8 +401,8 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e h1:sr4lujmn9heD030xx/Pd4B/JSmvRhFzuotNXaaV0WLs= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= +github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d h1:KHq+mAzWSkumj4PDoXc5VZbycPGcmYu8tohgVLQ6SIc= +github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= @@ -474,8 +410,8 @@ github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoI github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hetznercloud/hcloud-go/v2 v2.0.0 h1:Sg1DJ+MAKvbYAqaBaq9tPbwXBS2ckPIaMtVdUjKu+4g= -github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= +github.com/hetznercloud/hcloud-go/v2 v2.9.0 h1:s0N6R7Zoi2DPfMtUF5o9VeUBzTtHVY6MIkHOQnfu/AY= +github.com/hetznercloud/hcloud-go/v2 v2.9.0/go.mod h1:qtW/TuU7Bs16ibXl/ktJarWqU2LwHr7eGlwoilHxtgg= github.com/hjson/hjson-go/v4 v4.0.0 h1:wlm6IYYqHjOdXH1gHev4VoXCaW20HdQAGCxdOEEg2cs= github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -485,10 +421,8 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/influxdata/go-syslog/v3 v3.0.1-0.20210608084020-ac565dc76ba6 h1:s9ZL6ZhFF8y6ebnm1FLvobkzoIu5xwDQUcRPk/IEhpM= -github.com/influxdata/go-syslog/v3 v3.0.1-0.20210608084020-ac565dc76ba6/go.mod h1:aXdIdfn2OcGnMhOTojXmwZqXKgC3MU5riiNvzwwG9OY= -github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= -github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= +github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8= +github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -519,14 +453,14 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs= github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -544,15 +478,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 h1:bCiVCRCs1Heq84lurVinUPy19keqGEe4jh5vtK37jcg= -github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg= +github.com/leodido/go-syslog/v4 v4.1.0 h1:Wsl194qyWXr7V6DrGWC3xmxA9Ra6XgWO+toNt2fmCaI= +github.com/leodido/go-syslog/v4 v4.1.0/go.mod h1:eJ8rUfDN5OS6dOkCOBYlg2a+hbAg6pJa99QXXgMrd98= +github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b h1:11UHH39z1RhZ5dc4y4r/4koJo6IYFgTRMe/LlwRTEw0= +github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YUw= -github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/linode/linodego v1.35.0 h1:rIhUeCHBLEDlkoRnOTwzSGzljQ3ksXwLxacmXnrV+Do= +github.com/linode/linodego v1.35.0/go.mod h1:JxuhOEAMfSxun6RU5/MgTKH2GGTmFrhKRj3wL1NFin0= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY= +github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= @@ -567,18 +504,16 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -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/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= -github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= +github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= github.com/minio/minio-go/v6 v6.0.57 h1:ixPkbKkyD7IhnluRgQpGSpHdpvNVaW6OD5R9IAO/9Tw= @@ -598,11 +533,13 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= 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= @@ -637,30 +574,32 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/open-telemetry/opamp-go v0.5.0 h1:2YFbb6G4qBkq3yTRdVb5Nfz9hKHW/ldUyex352e1J7g= github.com/open-telemetry/opamp-go v0.5.0/go.mod h1:IMdeuHGVc5CjKSu5/oNV0o+UmiXuahoHvoZ4GOmAI9M= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.88.0 h1:9gjzrpUlzGC5BebgO1cxb/9KQ9yuIIE6B+6wLySKVCQ= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.88.0/go.mod h1:GXfK9q6RosmltLUcOdrQMS3hF1RYuwIgFTIa4RRR5J4= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.88.0 h1:2HoGcjmHHIDMafd3Uj3flQJrV8TC2FAnUiTKD8FH0G8= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.88.0/go.mod h1:JvXKcDtcOQRkz/Sw1m27K4QA3OwMbUvifoeEX2NQC6k= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.88.0 h1:jqdkgfHXcjvk6L2CyTUv3Rn+whX3TfFWd0Mz4QNAV1c= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.88.0/go.mod h1:5QXLdN4gdjAEcMHNEK/RrDdp+FObca0bS4/pRauyZs8= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.88.0 h1:S1FEVDH5GEMZQuHg8jfv47lCHHDFVjZBpO/Yrb/vKpE= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.88.0/go.mod h1:IJqzjDv6ZFeu7cYGCUzQ5/3CuTPVIo3UAGK3o2jK/Sw= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.88.0 h1:Ezi3FyxGbetZ12yAinyif/aabc9J7VyFdOvdufPCaUU= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.88.0/go.mod h1:6nO6NG5H5V5YGRp5onf9JnitXwhMfNXLSfZNyVwRPuw= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.88.0 h1:meHyTMeWC3xYativnHwYdnT9XwHWtfjioPRqgzaDJXA= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.88.0/go.mod h1:Vhb+pyxTKFjAoLaaJCiYHbJS6o56vQEvnJDhh/ws6yY= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.102.0 h1:7QHxeMnKzMXMw9oh5lnOHakfPpGSglxiZfbYUn6l6yc= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.102.0/go.mod h1:BtKaHa1yDHfhM9qjGUHweb0HgqFGxFSM7AMzwLXVR98= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.102.0 h1:PNLVcz8kJLE9V5kGnbBh277Bvl4WwiVZ+NbFbOB80WY= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.102.0/go.mod h1:cBbjwd8m4rBVgCQksUbAVQX1EoM5IuCyNQw2mzvibEM= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.102.0 h1:qsM5HhWpAfIMg8LdO4u+CHofu4UuCuJwg/M+ySO9uZA= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.102.0/go.mod h1:wBJlGy9Wx6s7AxIMcSne2sGw73e5ZUy1AQ/duYwpFf8= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.102.0 h1:vJL6lDaeI3pVA7ADnWKD3HMpI80BSrZ2UnGc+qkwqoY= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.102.0/go.mod h1:xtE7tds5j8PtI/wMuGb+Em5K9rJH8hm6t28Qe4QrpoU= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.102.0 h1:TvJYcU/DLRFCgHr7nT98k5D+qkZ4syKVxc8OJjv+K4c= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.102.0/go.mod h1:WzD3Ox7tywAQHknxAFpAC1oZJGItMp5mbvgUGjvzNY8= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0 h1:J8GFYxKLWG1360XRukc1tY5K9BF80MFXcO91UpCMgcQ= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0/go.mod h1:GNxigQNap2jyOEPdOedAKqCbh61y576ND4BKn/7i8xY= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.102.0 h1:XOoV42CE0BJUsKJQ7+Fie2jusw0MBzzOc79IoQONJAk= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.102.0/go.mod h1:nCpPHY7XLM+zbJxKxP132IuV0xHCu5E6oa3ZLpmBPl4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM= -github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= +github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI= +github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= @@ -674,8 +613,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -688,45 +627,36 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/posthog/posthog-go v0.0.0-20220817142604-0b0bbf0f9c0f h1:h0p1aZ9F5d6IXOygysob3g4B07b+HuVUQC0VJKD8wA4= github.com/posthog/posthog-go v0.0.0-20220817142604-0b0bbf0f9c0f/go.mod h1:oa2sAs9tGai3VldabTV0eWejt/O4/OOD7azP8GaikqU= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI= +github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -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_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -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/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.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -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.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= +github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -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/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= +github.com/prometheus/procfs v0.15.0 h1:A82kmvXJq2jTu5YUhSGNlYoxh85zLnKgPz4bMZgI5Ek= +github.com/prometheus/procfs v0.15.0/go.mod h1:Y0RJ/Y5g5wJpkTisOtqwDSo4HwhGmLB4VQSw2sQJLHk= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= @@ -735,10 +665,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russellhaering/gosaml2 v0.9.0 h1:CNMnH42z/GirrKjdmNrSS6bAAs47F9bPdl4PfRmVOIk= github.com/russellhaering/gosaml2 v0.9.0/go.mod h1:byViER/1YPUa0Puj9ROZblpoq2jsE7h/CJmitzX0geU= github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg= @@ -750,8 +680,8 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20 h1:a9hSJdJcd16e0HoMsnFvaHvxB3pxSD+SC7+CISp7xY0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LFNcy7yeipBqt9N9mVg= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= @@ -759,8 +689,8 @@ github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N+ github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= -github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= -github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU= +github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -787,8 +717,8 @@ github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/srikanthccv/ClickHouse-go-mock v0.7.0 h1:XhRMX2663xkDGq3DYavw8m75O94s9u76hOIjo9QBl8c= @@ -796,8 +726,9 @@ github.com/srikanthccv/ClickHouse-go-mock v0.7.0/go.mod h1:IJZ/eL1h4cOy/Jo3PzNKX github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -808,9 +739,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= @@ -819,6 +750,8 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/vjeantet/grok v1.0.1 h1:2rhIR7J4gThTgcZ1m2JY4TrJZNgjn985U28kT2wQrJ4= github.com/vjeantet/grok v1.0.1/go.mod h1:ax1aAchzC6/QMXMcyzHQGZWaW1l195+uMYIkCWPCNIo= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -834,9 +767,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= @@ -846,83 +778,94 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/collector v0.88.0 h1:I0lerJK1h88vk7enriSgLV+h7dM099G9FgwkfmIZaf0= -go.opentelemetry.io/collector v0.88.0/go.mod h1:we0quZ+4txHS3Sfb0VdjFv95KYLGmto4ZAThCHiYgGA= -go.opentelemetry.io/collector/component v0.88.0 h1:LU/1ov5D/O/gv9D2Uv88EjNKHn7DHcUCZn1qQsb/zgw= -go.opentelemetry.io/collector/component v0.88.0/go.mod h1:4utKxz4Lilym3SPxNXJHosdaTjT1aQxI+TCmnJO54pU= -go.opentelemetry.io/collector/config/confignet v0.88.0 h1:CbVZQpWC8Bm/BKo3x2mnQZVdQKClU0gCa6SVbRCc930= -go.opentelemetry.io/collector/config/confignet v0.88.0/go.mod h1:cpO8JYWGONaViOygKVw+Hd2UoBcn2cUiyi0WWeFTwJY= -go.opentelemetry.io/collector/config/configtelemetry v0.88.0 h1:54Z9uoSTpbkq3esDwHvJMChoUH8p/nfesG2xJTOXayY= -go.opentelemetry.io/collector/config/configtelemetry v0.88.0/go.mod h1:+LAXM5WFMW/UbTlAuSs6L/W72WC+q8TBJt/6z39FPOU= -go.opentelemetry.io/collector/confmap v0.88.0 h1:tOgY6NXMXAL2hz2+zVDQ0jvBlCUHprSf90bw5ktbdaI= -go.opentelemetry.io/collector/confmap v0.88.0/go.mod h1:CSJlMk1KRZloXAygpiPeCLpuQiLVDEZYbGsGHIKHeUg= -go.opentelemetry.io/collector/connector v0.88.0 h1:hUTSMexixSx4rWExBfr5p3YzDdj9a9+cUveaRK0EdnQ= -go.opentelemetry.io/collector/connector v0.88.0/go.mod h1:vkOHpyWNlHQVFHKUB4Dp1yYCIpAFnouZ2REupkzL/PU= -go.opentelemetry.io/collector/consumer v0.88.0 h1:l8Ty5UHhZ2U6WCp4yHt97uW6vN1vMP0JbFeQEaVnEgY= -go.opentelemetry.io/collector/consumer v0.88.0/go.mod h1:VVoafgyhjpO6fuJu12GqspmuLrn91JCOou0sOtb9GOg= -go.opentelemetry.io/collector/exporter v0.88.0 h1:bDXltsjQslhT7tlObQzKJiHuP5LDPeZHrkpUh4cT6Kk= -go.opentelemetry.io/collector/exporter v0.88.0/go.mod h1:0KQKlbUlYBwNJ9Dfapn6mRLhdhtM3tUlDGgN88oDVug= -go.opentelemetry.io/collector/extension v0.88.0 h1:/WH97pQYypL7ZC5OEccoE0gFs6fjBC/Uh9NuVEYEoZ0= -go.opentelemetry.io/collector/extension v0.88.0/go.mod h1:5wPlOyWtVJcZS9CMhFUnuRvNQ0XIoV/iUSaZWtCjoHA= -go.opentelemetry.io/collector/extension/zpagesextension v0.88.0 h1:cpkwzjhq6jfkVq3ltUl9wdb/8RrWbn0utHTCU3K5Mhc= -go.opentelemetry.io/collector/extension/zpagesextension v0.88.0/go.mod h1:8LPmV8UkQgDAfNaAizQqLzYnYibzQv81eBGKv0Mk6wU= -go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 h1:DtJQalPXMWQqT6jd2LZ1oKrOfLJJRCi+rh2LKnkj4Zo= -go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017/go.mod h1:fLmJMf1AoHttkF8p5oJAc4o5ZpHu8yO5XYJ7gbLCLzo= -go.opentelemetry.io/collector/otelcol v0.88.0 h1:f2eRVLJY66w9WFj5iT1Tg6Qxtlljagov9v8TPStuK2g= -go.opentelemetry.io/collector/otelcol v0.88.0/go.mod h1:F85TtMPt+ySe29HD6DOyvsMFCV3onaB3VJzky7qrtzQ= -go.opentelemetry.io/collector/pdata v1.3.0 h1:JRYN7tVHYFwmtQhIYbxWeiKSa2L1nCohyAs8sYqKFZo= -go.opentelemetry.io/collector/pdata v1.3.0/go.mod h1:t7W0Undtes53HODPdSujPLTnfSR5fzT+WpL+RTaaayo= -go.opentelemetry.io/collector/processor v0.88.0 h1:5BUZaH+RhTpgTVqBZCrBnN/vl0M1CtwQsZ8ek4iH1lc= -go.opentelemetry.io/collector/processor v0.88.0/go.mod h1:2T5KxgBQxXuuyMu9dh+PIBxQ/geCFYcdnjmlWZx8o3E= -go.opentelemetry.io/collector/receiver v0.88.0 h1:MPvVAFOfjl0+Ylka7so8QoK8T2Za2471rv5t3sqbbSY= -go.opentelemetry.io/collector/receiver v0.88.0/go.mod h1:MIZ6jPPZ+I8XibZm6I3RAn9h7Wcy2ZJsPmtXd2BLr60= -go.opentelemetry.io/collector/semconv v0.88.0 h1:8TVP4hYaUC87S6CCLKNoSxsUE0ChldE4vqotvNHHUnE= -go.opentelemetry.io/collector/semconv v0.88.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= -go.opentelemetry.io/collector/service v0.88.0 h1:KSue2w94Tb2xjenlm+SC2y2g87hdhFJeHMT9pEshKAE= -go.opentelemetry.io/collector/service v0.88.0/go.mod h1:+Fov4arJzWl8SBuMonvM7gOrfK72G+d+2WotRjR5c2I= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/contrib/propagators/b3 v1.20.0 h1:Yty9Vs4F3D6/liF1o6FNt0PvN85h/BJJ6DQKJ3nrcM0= -go.opentelemetry.io/contrib/propagators/b3 v1.20.0/go.mod h1:On4VgbkqYL18kbJlWsa18+cMNe6rYpBnPi1ARI/BrsU= -go.opentelemetry.io/contrib/zpages v0.45.0 h1:jIwHHGoWzJoZdbIUtWdErjL85Gni6BignnAFqDtMRL4= -go.opentelemetry.io/contrib/zpages v0.45.0/go.mod h1:4mIdA5hqH6hEx9sZgV50qKfQO8aIYolUZboHmz+G7vw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/bridge/opencensus v0.42.0 h1:QvC+bcZkWMphWPiVqRQygMj6M0/3TOuJEO+erRA7kI8= -go.opentelemetry.io/otel/bridge/opencensus v0.42.0/go.mod h1:XJojP7g5DqYdiyArix/H9i1XzPPlIUc9dGLKtF9copI= -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/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -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/exporters/stdout/stdoutmetric v0.42.0 h1:4jJuoeOo9W6hZnz+r046fyoH5kykZPRvKfUXJVfMpB0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0/go.mod h1:/MtYTE1SfC2QIcE0bDot6fIX+h+WvXjgTqgn9P0LNPE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= -go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= -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.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/collector v0.102.1 h1:M/ciCcReQsSDYG9bJ2Qwqk7pQILDJ2bM/l0MdeCAvJE= +go.opentelemetry.io/collector v0.102.1/go.mod h1:yF1lDRgL/Eksb4/LUnkMjvLvHHpi6wqBVlzp+dACnPM= +go.opentelemetry.io/collector/component v0.102.1 h1:66z+LN5dVCXhvuVKD1b56/3cYLK+mtYSLIwlskYA9IQ= +go.opentelemetry.io/collector/component v0.102.1/go.mod h1:XfkiSeImKYaewT2DavA80l0VZ3JjvGndZ8ayPXfp8d0= +go.opentelemetry.io/collector/config/confignet v0.102.1 h1:nSiAFQMzNCO4sDBztUxY73qFw4Vh0hVePq8+3wXUHtU= +go.opentelemetry.io/collector/config/confignet v0.102.1/go.mod h1:pfOrCTfSZEB6H2rKtx41/3RN4dKs+X2EKQbw3MGRh0E= +go.opentelemetry.io/collector/config/configtelemetry v0.102.1 h1:f/CYcrOkaHd+COIJ2lWnEgBCHfhEycpbow4ZhrGwAlA= +go.opentelemetry.io/collector/config/configtelemetry v0.102.1/go.mod h1:WxWKNVAQJg/Io1nA3xLgn/DWLE/W1QOB2+/Js3ACi40= +go.opentelemetry.io/collector/confmap v0.102.1 h1:wZuH+d/P11Suz8wbp+xQCJ0BPE9m5pybtUe74c+rU7E= +go.opentelemetry.io/collector/confmap v0.102.1/go.mod h1:KgpS7UxH5rkd69CzAzlY2I1heH8Z7eNCZlHmwQBMxNg= +go.opentelemetry.io/collector/confmap/converter/expandconverter v0.102.0 h1:8Ne/oL6M4kMWK0P3FKV9EduQa+1UOGyVAnFHfSo4c1A= +go.opentelemetry.io/collector/confmap/converter/expandconverter v0.102.0/go.mod h1:Xj4Ld/RriP/Bj+5oPpaYJsLNs2wWRDN2TvzX3Lbi6+M= +go.opentelemetry.io/collector/confmap/provider/envprovider v0.102.0 h1:o1iKqN+oM+TZqHoGdnKw1Am2BQlIGCYbxCRzU8T3jbM= +go.opentelemetry.io/collector/confmap/provider/envprovider v0.102.0/go.mod h1:JpCemLtL/sXQ2Rk3Bx7OPPA7Qt/9NVH91q0bR655gSo= +go.opentelemetry.io/collector/confmap/provider/fileprovider v0.102.0 h1:SfASE6lxXjrmYj/UibcWdOiFWvRG0zt4hJgenloEhlY= +go.opentelemetry.io/collector/confmap/provider/fileprovider v0.102.0/go.mod h1:+Ku0Fvdb5f6e9UkfqJXAV5FaUJVxxg6Ykfx7Js8y+V4= +go.opentelemetry.io/collector/confmap/provider/httpprovider v0.102.0 h1:GwJQTXs7pYPUv/fVf+0nBgsJdlrTuY/PfwQ/TRA/sIk= +go.opentelemetry.io/collector/confmap/provider/httpprovider v0.102.0/go.mod h1:PGE3DcRgqYWWC2cq2hYZoET1d3Q8JZyPNmgvqXPFWEU= +go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.102.0 h1:zdYZLiHHtDf4Kk9WU7mW9dW6WAXtBF54I5jmTMRJtiw= +go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.102.0/go.mod h1:yFsgUM0PbUJkPlbpJfOG6da+YiF0Z80tv7YcnL3qwv4= +go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.102.0 h1:Y4H+GaCQl2URp9mEJMV5CYOhw+erONqNyvtFoKQfIoA= +go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.102.0/go.mod h1:g1RjfVD0gHAf/mPOIs3zBoKBeuDsN+rc5x0lZtgA8tI= +go.opentelemetry.io/collector/connector v0.102.0 h1:IvAsVfYRxP0ajmKbUovF8qugkcUtHq6RuYNtjcMa63E= +go.opentelemetry.io/collector/connector v0.102.0/go.mod h1:f4M7wZ/9+XtgTE0fivBFH3WlwntaEd0qFFA0giFkdnY= +go.opentelemetry.io/collector/consumer v0.102.1 h1:0CkgHhxwx4lI/m+hWjh607xyjooW5CObZ8hFQy5vvo0= +go.opentelemetry.io/collector/consumer v0.102.1/go.mod h1:HoXqmrRV13jLnP3/Gg3fYNdRkDPoO7UW58hKiLyFF60= +go.opentelemetry.io/collector/exporter v0.102.0 h1:hvyTyyGVx5FIikA6HzlTeZHILJ62hrIBsoZCoKlpX3A= +go.opentelemetry.io/collector/exporter v0.102.0/go.mod h1:JWE+1qNoSVBSelzhI3Iao/VkYVssY+sXaTPK1JOmpQ0= +go.opentelemetry.io/collector/extension v0.102.1 h1:gAvE3w15q+Vv0Tj100jzcDpeMTyc8dAiemHRtJbspLg= +go.opentelemetry.io/collector/extension v0.102.1/go.mod h1:XBxUOXjZpwYLZYOK5u3GWlbBTOKmzStY5eU1R/aXkIo= +go.opentelemetry.io/collector/extension/zpagesextension v0.102.0 h1:BPq98py8nwzaV7KAsxt4ZZAF9LiSRu7ZjHNGavFNyKo= +go.opentelemetry.io/collector/extension/zpagesextension v0.102.0/go.mod h1:P86HW3x3epDS5F4yP0gAvsZiw4xxP1OupTEx2o6UqjY= +go.opentelemetry.io/collector/featuregate v1.9.0 h1:mC4/HnR5cx/kkG1RKOQAvHxxg5Ktmd9gpFdttPEXQtA= +go.opentelemetry.io/collector/featuregate v1.9.0/go.mod h1:PsOINaGgTiFc+Tzu2K/X2jP+Ngmlp7YKGV1XrnBkH7U= +go.opentelemetry.io/collector/otelcol v0.102.0 h1:HuE+ok4iUjOrmYhQBSWpG5kBTVhcA24ljPL4pBERZ5E= +go.opentelemetry.io/collector/otelcol v0.102.0/go.mod h1:w8pCRu2nM/jAkLlEAS6ccKtJv5ylUQe6Ugl98zzTfyE= +go.opentelemetry.io/collector/pdata v1.9.0 h1:qyXe3HEVYYxerIYu0rzgo1Tx2d1Zs6iF+TCckbHLFOw= +go.opentelemetry.io/collector/pdata v1.9.0/go.mod h1:vk7LrfpyVpGZrRWcpjyy0DDZzL3SZiYMQxfap25551w= +go.opentelemetry.io/collector/pdata/testdata v0.102.1 h1:S3idZaJxy8M7mCC4PG4EegmtiSaOuh6wXWatKIui8xU= +go.opentelemetry.io/collector/pdata/testdata v0.102.1/go.mod h1:JEoSJTMgeTKyGxoMRy48RMYyhkA5vCCq/abJq9B6vXs= +go.opentelemetry.io/collector/processor v0.102.0 h1:JsjTlpBRmoSYxcu3cAbKBchOmL6aNUxLa03ZkWIqZr8= +go.opentelemetry.io/collector/processor v0.102.0/go.mod h1:IaCSDcfy75uQTaOM+LgR1bMf/bUw2eFfzn20uvWYfLQ= +go.opentelemetry.io/collector/receiver v0.102.0 h1:8rHNjWjV90bL0dgvKVc/7D10NCbM7bXCiqpcLRz5jBI= +go.opentelemetry.io/collector/receiver v0.102.0/go.mod h1:bYDwYItMrj7Drx0Pn4wZQ8Ii67lp9Nta62gbau93FhA= +go.opentelemetry.io/collector/semconv v0.102.0 h1:VEOdog9IbSfaGR7yg4AVmT54MwHAgH9lzITH6C33uyc= +go.opentelemetry.io/collector/semconv v0.102.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw= +go.opentelemetry.io/collector/service v0.102.0 h1:B5nfyQZF7eB/y+yucl9G/7VsusbXixYXWingXn7VszM= +go.opentelemetry.io/collector/service v0.102.0/go.mod h1:c+0n0DfQeCjgrdplNHYwYbG/5aupTZVYU/50nMQraoc= +go.opentelemetry.io/contrib/config v0.7.0 h1:b1rK5tGTuhhPirJiMxOcyQfZs76j2VapY6ODn3b2Dbs= +go.opentelemetry.io/contrib/config v0.7.0/go.mod h1:8tdiFd8N5etOi3XzBmAoMxplEzI3TcL8dU5rM5/xcOQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= +go.opentelemetry.io/contrib/propagators/b3 v1.27.0 h1:IjgxbomVrV9za6bRi8fWCNXENs0co37SZedQilP2hm0= +go.opentelemetry.io/contrib/propagators/b3 v1.27.0/go.mod h1:Dv9obQz25lCisDvvs4dy28UPh974CxkahRDUPsY7y9E= +go.opentelemetry.io/contrib/zpages v0.52.0 h1:MPgkMy0Cp3O5EdfVXP0ss3ujhEibysTM4eszx7E7d+E= +go.opentelemetry.io/contrib/zpages v0.52.0/go.mod h1:fqG5AFdoYru3A3DnhibVuaaEfQV2WKxE7fYE1jgDRwk= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/otel/bridge/opencensus v1.27.0 h1:ao9aGGHd+G4YfjBpGs6vbkvt5hoC67STlJA9fCnOAcs= +go.opentelemetry.io/otel/bridge/opencensus v1.27.0/go.mod h1:uRvWtAAXzyVOST0WMPX5JHGBaAvBws+2F8PcC5gMnTk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 h1:bFgvUr3/O4PHj3VQcFEuYKvRZJX1SJDQ+11JXuSB3/w= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0/go.mod h1:xJntEd2KL6Qdg5lwp97HMLQDVeAhrYxmzFseAMDPQ8I= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY= +go.opentelemetry.io/otel/exporters/prometheus v0.49.0 h1:Er5I1g/YhfYv9Affk9nJLfH/+qCCVVg1f2R9AbJfqDQ= +go.opentelemetry.io/otel/exporters/prometheus v0.49.0/go.mod h1:KfQ1wpjf3zsHjzP149P4LyAwWRupc6c7t1ZJ9eXpKQM= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0 h1:/jlt1Y8gXWiHG9FBx6cJaIC5hYx5Fe64nC8w5Cylt/0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0/go.mod h1:bmToOGOBZ4hA9ghphIc1PAf66VA8KOtsuy3+ScStG20= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0 h1:/0YaXu3755A/cFbtXp+21lkXgI0QE5avTWA2HjU9/WE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0/go.mod h1:m7SFxp0/7IxmJPLIY3JhOcU9CoFzDaCPL6xxQIxhA+o= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= +go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -943,10 +886,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -957,8 +899,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -971,7 +913,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -981,12 +922,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1020,54 +958,24 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1079,10 +987,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1129,81 +1035,45 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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= @@ -1247,31 +1117,17 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1288,38 +1144,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1351,60 +1181,11 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1419,28 +1200,11 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 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.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= 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= @@ -1454,10 +1218,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba 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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1475,8 +1237,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/segmentio/analytics-go.v3 v3.1.0 h1:UzxH1uaGZRpMKDhJyBz0pexz6yUoBU3x8bJsRk/HV6U= gopkg.in/segmentio/analytics-go.v3 v3.1.0/go.mod h1:4QqqlTlSSpVlWA9/9nDcPw+FkM2yv1NQoYjUbL9/JAw= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1499,18 +1259,18 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= -k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= +k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/query-service/agentConf/db.go b/pkg/query-service/agentConf/db.go index 04ab780db6..30ec1caef3 100644 --- a/pkg/query-service/agentConf/db.go +++ b/pkg/query-service/agentConf/db.go @@ -4,7 +4,6 @@ import ( "context" "database/sql" "fmt" - "math/rand" "github.com/google/uuid" "github.com/jmoiron/sqlx" @@ -15,10 +14,6 @@ import ( "golang.org/x/exp/slices" ) -func init() { - rand.Seed(2000) -} - // Repo handles DDL and DML ops on ingestion rules type Repo struct { db *sqlx.DB diff --git a/pkg/query-service/app/auth.go b/pkg/query-service/app/auth.go index f771a7cbfe..abdbdc9c9c 100644 --- a/pkg/query-service/app/auth.go +++ b/pkg/query-service/app/auth.go @@ -64,7 +64,7 @@ func (am *AuthMiddleware) EditAccess(f func(http.ResponseWriter, *http.Request)) if !(auth.IsEditor(user) || auth.IsAdmin(user)) { RespondError(w, &model.ApiError{ Typ: model.ErrorForbidden, - Err: errors.New("API is accessible to editors/admins."), + Err: errors.New("API is accessible to editors/admins"), }, nil) return } @@ -88,7 +88,7 @@ func (am *AuthMiddleware) SelfAccess(f func(http.ResponseWriter, *http.Request)) if !(auth.IsSelfAccessRequest(user, id) || auth.IsAdmin(user)) { RespondError(w, &model.ApiError{ Typ: model.ErrorForbidden, - Err: errors.New("API is accessible for self access or to the admins."), + Err: errors.New("API is accessible for self access or to the admins"), }, nil) return } diff --git a/pkg/query-service/app/clickhouseReader/options.go b/pkg/query-service/app/clickhouseReader/options.go index d92b5ee38f..538cef33e5 100644 --- a/pkg/query-service/app/clickhouseReader/options.go +++ b/pkg/query-service/app/clickhouseReader/options.go @@ -42,17 +42,6 @@ const ( defaultEncoding Encoding = EncodingJSON ) -const ( - suffixEnabled = ".enabled" - suffixDatasource = ".datasource" - suffixOperationsTable = ".operations-table" - suffixIndexTable = ".index-table" - suffixSpansTable = ".spans-table" - suffixWriteBatchDelay = ".write-batch-delay" - suffixWriteBatchSize = ".write-batch-size" - suffixEncoding = ".encoding" -) - // NamespaceConfig is Clickhouse's internal configuration data type namespaceConfig struct { namespace string diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index c4a3de87eb..320f7fe5b3 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -27,11 +27,8 @@ import ( "github.com/pkg/errors" "github.com/prometheus/common/promlog" "github.com/prometheus/prometheus/config" - "github.com/prometheus/prometheus/discovery" - sd_config "github.com/prometheus/prometheus/discovery" "github.com/prometheus/prometheus/promql" - "github.com/prometheus/prometheus/scrape" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage/remote" "github.com/prometheus/prometheus/util/stats" @@ -263,14 +260,8 @@ func (r *ClickHouseReader) Start(readerReady chan bool) { configFile: r.promConfigFile, } - // fanoutStorage := remoteStorage fanoutStorage := storage.NewFanout(logger, remoteStorage) - ctxScrape, cancelScrape := context.WithCancel(context.Background()) - discoveryManagerScrape := discovery.NewManager(ctxScrape, log.With(logger, "component", "discovery manager scrape"), discovery.Name("scrape")) - - scrapeManager := scrape.NewManager(nil, log.With(logger, "component", "scrape manager"), fanoutStorage) - opts := promql.EngineOpts{ Logger: log.With(logger, "component", "query engine"), Reg: nil, @@ -287,16 +278,6 @@ func (r *ClickHouseReader) Start(readerReady chan bool) { reloaders := []func(cfg *config.Config) error{ remoteStorage.ApplyConfig, - // The Scrape managers need to reload before the Discovery manager as - // they need to read the most updated config when receiving the new targets list. - scrapeManager.ApplyConfig, - func(cfg *config.Config) error { - c := make(map[string]sd_config.Configs) - for _, v := range cfg.ScrapeConfigs { - c[v.JobName] = v.ServiceDiscoveryConfigs - } - return discoveryManagerScrape.ApplyConfig(c) - }, } // sync.Once is used to make sure we can close the channel at different execution stages(SIGTERM or when the config is loaded). @@ -316,55 +297,11 @@ func (r *ClickHouseReader) Start(readerReady chan bool) { } var g group.Group - { - // Scrape discovery manager. - g.Add( - func() error { - err := discoveryManagerScrape.Run() - level.Info(logger).Log("msg", "Scrape discovery manager stopped") - return err - }, - func(err error) { - level.Info(logger).Log("msg", "Stopping scrape discovery manager...") - cancelScrape() - }, - ) - } - { - // Scrape manager. - g.Add( - func() error { - // When the scrape manager receives a new targets list - // it needs to read a valid config for each job. - // It depends on the config being in sync with the discovery manager so - // we wait until the config is fully loaded. - <-reloadReady.C - - err := scrapeManager.Run(discoveryManagerScrape.SyncCh()) - level.Info(logger).Log("msg", "Scrape manager stopped") - return err - }, - func(err error) { - // Scrape manager needs to be stopped before closing the local TSDB - // so that it doesn't try to write samples to a closed storage. - level.Info(logger).Log("msg", "Stopping scrape manager...") - scrapeManager.Stop() - }, - ) - } { // Initial configuration loading. cancel := make(chan struct{}) g.Add( func() error { - // select { - // case <-dbOpen: - // break - // // In case a shutdown is initiated before the dbOpen is released - // case <-cancel: - // reloadReady.Close() - // return nil - // } var err error r.promConfig, err = reloadConfig(cfg.configFile, logger, reloaders...) if err != nil { @@ -462,7 +399,7 @@ func (r *ClickHouseReader) LoadChannel(channel *model.ChannelItem) *model.ApiErr if response.StatusCode > 299 { responseData, _ := io.ReadAll(response.Body) - err := fmt.Errorf("Error in getting 2xx response in API call to alertmanager/v1/receivers") + err := fmt.Errorf("error in getting 2xx response in API call to alertmanager/v1/receivers") zap.L().Error("Error in getting 2xx response in API call to alertmanager/v1/receivers", zap.String("Status", response.Status), zap.String("Data", string(responseData))) return &model.ApiError{Typ: model.ErrorInternal, Err: err} @@ -547,7 +484,7 @@ func (r *ClickHouseReader) GetChannels() (*[]model.ChannelItem, *model.ApiError) channels := []model.ChannelItem{} - query := fmt.Sprintf("SELECT id, created_at, updated_at, name, type, data data FROM notification_channels") + query := "SELECT id, created_at, updated_at, name, type, data data FROM notification_channels" err := r.localDB.Select(&channels, query) @@ -756,7 +693,7 @@ func (r *ClickHouseReader) GetServicesList(ctx context.Context) (*[]string, erro if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, fmt.Errorf("Error in processing sql query") + return nil, fmt.Errorf("error in processing sql query") } defer rows.Close() @@ -938,7 +875,7 @@ func (r *ClickHouseReader) GetServiceOverview(ctx context.Context, queryParams * } ops, ok := (*topLevelOps)[queryParams.ServiceName] if !ok { - return nil, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf("Service not found")} + return nil, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf("service not found")} } namedArgs := []interface{}{ @@ -1006,7 +943,7 @@ func (r *ClickHouseReader) GetServiceOverview(ctx context.Context, queryParams * if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } m := make(map[int64]int) @@ -1137,7 +1074,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } for _, service := range dBResponse { if service.ServiceName != "" { @@ -1154,7 +1091,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } for _, service := range dBResponse { if service.HttpRoute != "" { @@ -1171,7 +1108,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } for _, service := range dBResponse { if service.HttpUrl != "" { @@ -1188,7 +1125,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } for _, service := range dBResponse { if service.HttpMethod != "" { @@ -1205,7 +1142,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } for _, service := range dBResponse { if service.HttpHost != "" { @@ -1222,7 +1159,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } for _, service := range dBResponse { if service.Operation != "" { @@ -1238,7 +1175,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } finalQuery2 := fmt.Sprintf("SELECT COUNT(*) as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU AND hasError = false", r.TraceDB, r.indexTable) @@ -1249,7 +1186,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } if len(dBResponse) > 0 && len(dBResponse2) > 0 { traceFilterReponse.Status = map[string]uint64{"ok": dBResponse2[0].NumTotal, "error": dBResponse[0].NumTotal} @@ -1273,7 +1210,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode zap.L().Info(finalQuery) if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } if len(dBResponse) > 0 { traceFilterReponse.Duration = map[string]uint64{"minDuration": dBResponse[0].Min, "maxDuration": dBResponse[0].Max} @@ -1289,7 +1226,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } finalQuery = fmt.Sprintf("SELECT durationNano as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.durationTable) @@ -1301,7 +1238,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)} } if len(dBResponse) > 0 { traceFilterReponse.Duration["minDuration"] = dBResponse[0].NumTotal @@ -1460,7 +1397,7 @@ func (r *ClickHouseReader) GetFilteredSpans(ctx context.Context, queryParams *mo if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if queryParams.Order == constants.Descending { query = query + " ORDER BY timestamp DESC" @@ -1498,7 +1435,7 @@ func (r *ClickHouseReader) GetFilteredSpans(ctx context.Context, queryParams *mo if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } getFilterSpansResponse := model.GetFilterSpansResponse{ @@ -1732,7 +1669,7 @@ func (r *ClickHouseReader) GetTagFilters(ctx context.Context, queryParams *model if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } tagFiltersResult := model.TagFilters{ StringTagKeys: make([]string, 0), @@ -1847,7 +1784,7 @@ func (r *ClickHouseReader) GetTagValues(ctx context.Context, queryParams *model. if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } cleanedTagValues := model.TagValues{ @@ -1939,7 +1876,7 @@ func (r *ClickHouseReader) GetUsage(ctx context.Context, queryParams *model.GetU if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, fmt.Errorf("Error in processing sql query") + return nil, fmt.Errorf("error in processing sql query") } for i := range usageItems { @@ -1976,7 +1913,7 @@ func (r *ClickHouseReader) SearchTraces(ctx context.Context, params *model.Searc } telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_MAX_SPANS_ALLOWED_LIMIT_REACHED, data, userEmail, true, false) } - return nil, fmt.Errorf("Max spans allowed in trace limit reached, please contact support for more details") + return nil, fmt.Errorf("max spans allowed in trace limit reached, please contact support for more details") } userEmail, err := auth.GetEmailFromJwt(ctx) @@ -2130,7 +2067,7 @@ func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, query case "sum": aggregation_query = " sum(durationNano) as value " default: - return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("Aggregate type: %s not supported", queryParams.AggregationOption)} + return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("aggregate type: %s not supported", queryParams.AggregationOption)} } } else if queryParams.Dimension == "calls" { aggregation_query = " count(*) as value " @@ -2236,7 +2173,7 @@ func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, query if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } GetFilteredSpansAggregatesResponse := model.GetFilteredSpansAggregatesResponse{ @@ -2306,7 +2243,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context, tableName := getLocalTableName(tableName) statusItem, err := r.checkTTLStatusItem(ctx, tableName) if err != nil { - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing ttl_status check sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing ttl_status check sql query")} } if statusItem.Status == constants.StatusPending { return nil, &model.ApiError{Typ: model.ErrorConflict, Err: fmt.Errorf("TTL is already running")} @@ -2341,7 +2278,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context, } return } - req += fmt.Sprint(" SETTINGS distributed_ddl_task_timeout = -1;") + req += " SETTINGS distributed_ddl_task_timeout = -1;" zap.L().Error("Executing TTL request: ", zap.String("request", req)) statusItem, _ := r.checkTTLStatusItem(ctx, tableName) if err := r.db.Exec(context.Background(), req); err != nil { @@ -2378,13 +2315,18 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context, zap.L().Error("Error in inserting to ttl_status table", zap.Error(dbErr)) return } + timeColumn := "timestamp_ms" + if strings.Contains(tableName, "v4") { + timeColumn = "unix_milli" + } + req := fmt.Sprintf( - "ALTER TABLE %v ON CLUSTER %s MODIFY TTL toDateTime(toUInt32(timestamp_ms / 1000), 'UTC') + "+ - "INTERVAL %v SECOND DELETE", tableName, r.cluster, params.DelDuration) + "ALTER TABLE %v ON CLUSTER %s MODIFY TTL toDateTime(toUInt32(%s / 1000), 'UTC') + "+ + "INTERVAL %v SECOND DELETE", tableName, r.cluster, timeColumn, params.DelDuration) if len(params.ColdStorageVolume) > 0 { - req += fmt.Sprintf(", toDateTime(toUInt32(timestamp_ms / 1000), 'UTC')"+ + req += fmt.Sprintf(", toDateTime(toUInt32(%s / 1000), 'UTC')"+ " + INTERVAL %v SECOND TO VOLUME '%s'", - params.ToColdStorageDuration, params.ColdStorageVolume) + timeColumn, params.ToColdStorageDuration, params.ColdStorageVolume) } err := r.setColdStorage(context.Background(), tableName, params.ColdStorageVolume) if err != nil { @@ -2399,7 +2341,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context, } return } - req += fmt.Sprint(" SETTINGS distributed_ddl_task_timeout = -1") + req += " SETTINGS distributed_ddl_task_timeout = -1" zap.L().Info("Executing TTL request: ", zap.String("request", req)) statusItem, _ := r.checkTTLStatusItem(ctx, tableName) if err := r.db.Exec(ctx, req); err != nil { @@ -2456,7 +2398,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context, } return } - req += fmt.Sprint(" SETTINGS distributed_ddl_task_timeout = -1") + req += " SETTINGS distributed_ddl_task_timeout = -1" zap.L().Info("Executing TTL request: ", zap.String("request", req)) statusItem, _ := r.checkTTLStatusItem(ctx, tableName) if err := r.db.Exec(ctx, req); err != nil { @@ -2512,7 +2454,7 @@ func (r *ClickHouseReader) checkTTLStatusItem(ctx context.Context, tableName str } if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return model.TTLStatusItem{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing ttl_status check sql query")} + return model.TTLStatusItem{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing ttl_status check sql query")} } return statusItem[0], nil } @@ -2528,7 +2470,7 @@ func (r *ClickHouseReader) setTTLQueryStatus(ctx context.Context, tableNameArray return "", nil } if err != nil { - return "", &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing ttl_status check sql query")} + return "", &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing ttl_status check sql query")} } if statusItem.Status == constants.StatusPending && statusItem.UpdatedAt.Unix()-time.Now().Unix() < 3600 { status = constants.StatusPending @@ -2813,7 +2755,7 @@ func (r *ClickHouseReader) ListErrors(ctx context.Context, queryParams *model.Li if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } return &getErrorResponses, nil @@ -2850,7 +2792,7 @@ func (r *ClickHouseReader) CountErrors(ctx context.Context, queryParams *model.C if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return 0, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return 0, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } return errorCount, nil @@ -2872,7 +2814,7 @@ func (r *ClickHouseReader) GetErrorFromErrorID(ctx context.Context, queryParams if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getErrorWithSpanReponse) > 0 { @@ -2896,7 +2838,7 @@ func (r *ClickHouseReader) GetErrorFromGroupID(ctx context.Context, queryParams if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getErrorWithSpanReponse) > 0 { @@ -2944,7 +2886,7 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getNextErrorIDReponse) == 0 { zap.L().Info("NextErrorID not found") @@ -2965,7 +2907,7 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getNextErrorIDReponse) == 0 { var getNextErrorIDReponse []model.NextPrevErrorIDsDBResponse @@ -2979,7 +2921,7 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getNextErrorIDReponse) == 0 { @@ -3013,7 +2955,7 @@ func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getPrevErrorIDReponse) == 0 { zap.L().Info("PrevErrorID not found") @@ -3034,7 +2976,7 @@ func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getPrevErrorIDReponse) == 0 { var getPrevErrorIDReponse []model.NextPrevErrorIDsDBResponse @@ -3048,7 +2990,7 @@ func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *mode if err != nil { zap.L().Error("Error in processing sql query", zap.Error(err)) - return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")} + return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")} } if len(getPrevErrorIDReponse) == 0 { @@ -3077,7 +3019,7 @@ func (r *ClickHouseReader) GetMetricResultEE(ctx context.Context, query string) // GetMetricResult runs the query and returns list of time series func (r *ClickHouseReader) GetMetricResult(ctx context.Context, query string) ([]*model.Series, error) { - defer utils.Elapsed("GetMetricResult")() + defer utils.Elapsed("GetMetricResult", nil)() zap.L().Info("Executing metric result query: ", zap.String("query", query)) @@ -3409,7 +3351,7 @@ func isDashboardWithPanelAndName(data map[string]interface{}) bool { if ok && title != "Sample Title" { isDashboardName = true } - widgets, ok := data["widgets"].(interface{}) + widgets, ok := data["widgets"] if ok && isDashboardName { data, ok := widgets.([]interface{}) if ok && len(data) > 0 { @@ -3424,7 +3366,7 @@ func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo { var logsPanelCount, tracesPanelCount, metricsPanelCount int // totalPanels := 0 if data != nil && data["widgets"] != nil { - widgets, ok := data["widgets"].(interface{}) + widgets, ok := data["widgets"] if ok { data, ok := widgets.([]interface{}) if ok { @@ -3432,9 +3374,9 @@ func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo { sData, ok := widget.(map[string]interface{}) if ok && sData["query"] != nil { // totalPanels++ - query, ok := sData["query"].(interface{}).(map[string]interface{}) + query, ok := sData["query"].(map[string]interface{}) if ok && query["queryType"] == "builder" && query["builder"] != nil { - builderData, ok := query["builder"].(interface{}).(map[string]interface{}) + builderData, ok := query["builder"].(map[string]interface{}) if ok && builderData["queryData"] != nil { builderQueryData, ok := builderData["queryData"].([]interface{}) if ok { @@ -3578,7 +3520,7 @@ func isSelectedField(tableStatement string, field model.LogField) bool { // in case of attributes and resources, if there is a materialized column present then it is selected // TODO: handle partial change complete eg:- index is removed but materialized column is still present name := utils.GetClickhouseColumnName(field.Type, field.DataType, field.Name) - return strings.Contains(tableStatement, fmt.Sprintf("%s", name)) + return strings.Contains(tableStatement, name) } func (r *ClickHouseReader) UpdateLogField(ctx context.Context, field *model.UpdateField) *model.ApiError { @@ -4433,7 +4375,7 @@ func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.Fi } -func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([]string, map[string]string, []map[string]string, v3.Point) { +func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([]string, map[string]string, []map[string]string, *v3.Point) { // Each row will have a value and a timestamp, and an optional list of label values // example: {Timestamp: ..., Value: ...} // The timestamp may also not present in some cases where the time series is reduced to single value @@ -4449,6 +4391,8 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([ // example: {"serviceName": "frontend", "operation": "/fetch"} groupAttributes := make(map[string]string) + isValidPoint := false + for idx, v := range vars { colName := columnNames[idx] switch v := v.(type) { @@ -4477,6 +4421,7 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([ case *time.Time: point.Timestamp = v.UnixMilli() case *float64, *float32: + isValidPoint = true if _, ok := constants.ReservedColumnTargetAliases[colName]; ok || countOfNumberCols == 1 { point.Value = float64(reflect.ValueOf(v).Elem().Float()) } else { @@ -4487,6 +4432,7 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([ groupAttributes[colName] = fmt.Sprintf("%v", reflect.ValueOf(v).Elem().Float()) } case *uint, *uint8, *uint64, *uint16, *uint32: + isValidPoint = true if _, ok := constants.ReservedColumnTargetAliases[colName]; ok || countOfNumberCols == 1 { point.Value = float64(reflect.ValueOf(v).Elem().Uint()) } else { @@ -4497,6 +4443,7 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([ groupAttributes[colName] = fmt.Sprintf("%v", reflect.ValueOf(v).Elem().Uint()) } case *int, *int8, *int16, *int32, *int64: + isValidPoint = true if _, ok := constants.ReservedColumnTargetAliases[colName]; ok || countOfNumberCols == 1 { point.Value = float64(reflect.ValueOf(v).Elem().Int()) } else { @@ -4517,7 +4464,10 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([ zap.L().Error("unsupported var type found in query builder query result", zap.Any("v", v), zap.String("colName", colName)) } } - return groupBy, groupAttributes, groupAttributesArray, point + if isValidPoint { + return groupBy, groupAttributes, groupAttributesArray, &point + } + return groupBy, groupAttributes, groupAttributesArray, nil } func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNames []string, countOfNumberCols int) ([]*v3.Series, error) { @@ -4558,7 +4508,7 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam groupBy, groupAttributes, groupAttributesArray, metricPoint := readRow(vars, columnNames, countOfNumberCols) // skip the point if the value is NaN or Inf // are they ever useful enough to be returned? - if math.IsNaN(metricPoint.Value) || math.IsInf(metricPoint.Value, 0) { + if metricPoint != nil && (math.IsNaN(metricPoint.Value) || math.IsInf(metricPoint.Value, 0)) { continue } sort.Strings(groupBy) @@ -4568,7 +4518,9 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam } seriesToAttrs[key] = groupAttributes labelsArray[key] = groupAttributesArray - seriesToPoints[key] = append(seriesToPoints[key], metricPoint) + if metricPoint != nil { + seriesToPoints[key] = append(seriesToPoints[key], *metricPoint) + } } var seriesList []*v3.Series @@ -4580,26 +4532,27 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam return seriesList, getPersonalisedError(rows.Err()) } -func logComment(ctx context.Context) string { - // Get the key-value pairs from context for log comment - kv := ctx.Value("log_comment") +func logCommentKVs(ctx context.Context) map[string]string { + kv := ctx.Value(common.LogCommentKey) if kv == nil { - return "" + return nil } - logCommentKVs, ok := kv.(map[string]string) if !ok { - return "" + return nil } - - x, _ := json.Marshal(logCommentKVs) - return string(x) + return logCommentKVs } // GetTimeSeriesResultV3 runs the query and returns list of time series func (r *ClickHouseReader) GetTimeSeriesResultV3(ctx context.Context, query string) ([]*v3.Series, error) { - defer utils.Elapsed("GetTimeSeriesResultV3", query, fmt.Sprintf("logComment: %s", logComment(ctx)))() + ctxArgs := map[string]interface{}{"query": query} + for k, v := range logCommentKVs(ctx) { + ctxArgs[k] = v + } + + defer utils.Elapsed("GetTimeSeriesResultV3", ctxArgs)() rows, err := r.db.Query(ctx, query) @@ -4641,7 +4594,12 @@ func (r *ClickHouseReader) GetTimeSeriesResultV3(ctx context.Context, query stri // GetListResultV3 runs the query and returns list of rows func (r *ClickHouseReader) GetListResultV3(ctx context.Context, query string) ([]*v3.Row, error) { - defer utils.Elapsed("GetListResultV3", query, fmt.Sprintf("logComment: %s", logComment(ctx)))() + ctxArgs := map[string]interface{}{"query": query} + for k, v := range logCommentKVs(ctx) { + ctxArgs[k] = v + } + + defer utils.Elapsed("GetListResultV3", ctxArgs)() rows, err := r.db.Query(ctx, query) diff --git a/pkg/query-service/app/clickhouseReader/wrapper.go b/pkg/query-service/app/clickhouseReader/wrapper.go index c21fde0ceb..c575aa7226 100644 --- a/pkg/query-service/app/clickhouseReader/wrapper.go +++ b/pkg/query-service/app/clickhouseReader/wrapper.go @@ -7,6 +7,7 @@ import ( "github.com/ClickHouse/clickhouse-go/v2" "github.com/ClickHouse/clickhouse-go/v2/lib/driver" + "go.signoz.io/signoz/pkg/query-service/common" ) type ClickhouseQuerySettings struct { @@ -65,7 +66,7 @@ func (c clickhouseConnWrapper) addClickHouseSettings(ctx context.Context, query func (c clickhouseConnWrapper) getLogComment(ctx context.Context) string { // Get the key-value pairs from context for log comment - kv := ctx.Value("log_comment") + kv := ctx.Value(common.LogCommentKey) if kv == nil { return "" } diff --git a/pkg/query-service/app/dashboards/model.go b/pkg/query-service/app/dashboards/model.go index 64e4abcf3e..a6c5d35c9e 100644 --- a/pkg/query-service/app/dashboards/model.go +++ b/pkg/query-service/app/dashboards/model.go @@ -706,7 +706,7 @@ func countTraceAndLogsPanel(data map[string]interface{}) (int64, int64) { count := int64(0) totalPanels := int64(0) if data != nil && data["widgets"] != nil { - widgets, ok := data["widgets"].(interface{}) + widgets, ok := data["widgets"] if ok { data, ok := widgets.([]interface{}) if ok { @@ -714,9 +714,9 @@ func countTraceAndLogsPanel(data map[string]interface{}) (int64, int64) { sData, ok := widget.(map[string]interface{}) if ok && sData["query"] != nil { totalPanels++ - query, ok := sData["query"].(interface{}).(map[string]interface{}) + query, ok := sData["query"].(map[string]interface{}) if ok && query["queryType"] == "builder" && query["builder"] != nil { - builderData, ok := query["builder"].(interface{}).(map[string]interface{}) + builderData, ok := query["builder"].(map[string]interface{}) if ok && builderData["queryData"] != nil { builderQueryData, ok := builderData["queryData"].([]interface{}) if ok { @@ -742,7 +742,7 @@ func countTraceAndLogsPanel(data map[string]interface{}) (int64, int64) { func getWidgetIds(data map[string]interface{}) []string { widgetIds := []string{} if data != nil && data["widgets"] != nil { - widgets, ok := data["widgets"].(interface{}) + widgets, ok := data["widgets"] if ok { data, ok := widgets.([]interface{}) if ok { diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go index 6792e58008..1f0769bb08 100644 --- a/pkg/query-service/app/http_handler.go +++ b/pkg/query-service/app/http_handler.go @@ -39,7 +39,6 @@ import ( v3 "go.signoz.io/signoz/pkg/query-service/model/v3" "go.signoz.io/signoz/pkg/query-service/postprocess" - "go.uber.org/multierr" "go.uber.org/zap" "go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline" @@ -66,19 +65,14 @@ func NewRouter() *mux.Router { return mux.NewRouter().UseEncodedPath() } -// APIHandler implements the query service public API by registering routes at httpPrefix +// APIHandler implements the query service public API type APIHandler struct { - // queryService *querysvc.QueryService - // queryParser queryParser - basePath string - apiPrefix string reader interfaces.Reader skipConfig *model.SkipConfig appDao dao.ModelDao alertManager am.Manager ruleManager *rules.Manager featureFlags interfaces.FeatureLookup - ready func(http.HandlerFunc) http.HandlerFunc querier interfaces.Querier querierV2 interfaces.Querier queryBuilder *queryBuilder.QueryBuilder @@ -194,8 +188,6 @@ func NewAPIHandler(opts APIHandlerOpts) (*APIHandler, error) { } aH.queryBuilder = queryBuilder.NewQueryBuilder(builderOpts, aH.featureFlags) - aH.ready = aH.testReady - dashboards.LoadDashboardFiles(aH.featureFlags) // if errReadingDashboards != nil { // return nil, errReadingDashboards @@ -227,32 +219,6 @@ type structuredResponse struct { type structuredError struct { Code int `json:"code,omitempty"` Msg string `json:"msg"` - // TraceID ui.TraceID `json:"traceID,omitempty"` -} - -var corsHeaders = map[string]string{ - "Access-Control-Allow-Headers": "Accept, Authorization, Content-Type, Origin", - "Access-Control-Allow-Methods": "GET, OPTIONS", - "Access-Control-Allow-Origin": "*", - "Access-Control-Expose-Headers": "Date", -} - -// Enables cross-site script calls. -func setCORS(w http.ResponseWriter) { - for h, v := range corsHeaders { - w.Header().Set(h, v) - } -} - -type apiFunc func(r *http.Request) (interface{}, *model.ApiError, func()) - -// Checks if server is ready, calls f if it is, returns 503 if it is not. -func (aH *APIHandler) testReady(f http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - - f(w, r) - - } } type ApiResponse struct { @@ -660,6 +626,9 @@ func (aH *APIHandler) getDashboards(w http.ResponseWriter, r *http.Request) { ic := aH.IntegrationsController installedIntegrationDashboards, err := ic.GetDashboardsForInstalledIntegrations(r.Context()) + if err != nil { + zap.L().Error("failed to get dashboards for installed integrations", zap.Error(err)) + } allDashboards = append(allDashboards, installedIntegrationDashboards...) tagsFromReq, ok := r.URL.Query()["tags"] @@ -761,7 +730,7 @@ func prepareQuery(r *http.Request) (string, error) { for _, op := range notAllowedOps { if strings.Contains(strings.ToLower(query), op) { - return "", fmt.Errorf("Operation %s is not allowed", op) + return "", fmt.Errorf("operation %s is not allowed", op) } } @@ -864,7 +833,6 @@ func (aH *APIHandler) saveAndReturn(w http.ResponseWriter, r *http.Request, sign return } aH.Respond(w, dashboard) - return } func (aH *APIHandler) createDashboardsTransform(w http.ResponseWriter, r *http.Request) { @@ -872,6 +840,11 @@ func (aH *APIHandler) createDashboardsTransform(w http.ResponseWriter, r *http.R defer r.Body.Close() b, err := io.ReadAll(r.Body) + if err != nil { + RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: err}, "Error reading request body") + return + } + var importData model.GrafanaJSON err = json.Unmarshal(b, &importData) @@ -1147,9 +1120,6 @@ func (aH *APIHandler) createRule(w http.ResponseWriter, r *http.Request) { } -func (aH *APIHandler) queryRangeMetricsFromClickhouse(w http.ResponseWriter, r *http.Request) { - -} func (aH *APIHandler) queryRangeMetrics(w http.ResponseWriter, r *http.Request) { query, apiErrorObj := parseQueryRangeRequest(r) @@ -1187,11 +1157,11 @@ func (aH *APIHandler) queryRangeMetrics(w http.ResponseWriter, r *http.Request) if res.Err != nil { switch res.Err.(type) { case promql.ErrQueryCanceled: - RespondError(w, &model.ApiError{model.ErrorCanceled, res.Err}, nil) + RespondError(w, &model.ApiError{Typ: model.ErrorCanceled, Err: res.Err}, nil) case promql.ErrQueryTimeout: - RespondError(w, &model.ApiError{model.ErrorTimeout, res.Err}, nil) + RespondError(w, &model.ApiError{Typ: model.ErrorTimeout, Err: res.Err}, nil) } - RespondError(w, &model.ApiError{model.ErrorExec, res.Err}, nil) + RespondError(w, &model.ApiError{Typ: model.ErrorExec, Err: res.Err}, nil) return } @@ -1242,11 +1212,11 @@ func (aH *APIHandler) queryMetrics(w http.ResponseWriter, r *http.Request) { if res.Err != nil { switch res.Err.(type) { case promql.ErrQueryCanceled: - RespondError(w, &model.ApiError{model.ErrorCanceled, res.Err}, nil) + RespondError(w, &model.ApiError{Typ: model.ErrorCanceled, Err: res.Err}, nil) case promql.ErrQueryTimeout: - RespondError(w, &model.ApiError{model.ErrorTimeout, res.Err}, nil) + RespondError(w, &model.ApiError{Typ: model.ErrorTimeout, Err: res.Err}, nil) } - RespondError(w, &model.ApiError{model.ErrorExec, res.Err}, nil) + RespondError(w, &model.ApiError{Typ: model.ErrorExec, Err: res.Err}, nil) } response_data := &model.QueryData{ @@ -1869,7 +1839,7 @@ func (aH *APIHandler) getUser(w http.ResponseWriter, r *http.Request) { if user == nil { RespondError(w, &model.ApiError{ Typ: model.ErrorInternal, - Err: errors.New("User not found"), + Err: errors.New("user not found"), }, nil) return } @@ -1936,7 +1906,7 @@ func (aH *APIHandler) deleteUser(w http.ResponseWriter, r *http.Request) { if user == nil { RespondError(w, &model.ApiError{ Typ: model.ErrorNotFound, - Err: errors.New("User not found"), + Err: errors.New("no user found"), }, nil) return } @@ -2009,7 +1979,7 @@ func (aH *APIHandler) getRole(w http.ResponseWriter, r *http.Request) { if user == nil { RespondError(w, &model.ApiError{ Typ: model.ErrorNotFound, - Err: errors.New("No user found"), + Err: errors.New("no user found"), }, nil) return } @@ -2058,7 +2028,7 @@ func (aH *APIHandler) editRole(w http.ResponseWriter, r *http.Request) { if len(adminUsers) == 1 { RespondError(w, &model.ApiError{ - Err: errors.New("Cannot demote the last admin"), + Err: errors.New("cannot demote the last admin"), Typ: model.ErrorInternal}, nil) return } @@ -2110,6 +2080,9 @@ func (aH *APIHandler) editOrg(w http.ResponseWriter, r *http.Request) { "organizationName": req.Name, } userEmail, err := auth.GetEmailFromJwt(r.Context()) + if err != nil { + zap.L().Error("failed to get user email from jwt", zap.Error(err)) + } telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_ORG_SETTINGS, data, userEmail, true, false) aH.WriteJSON(w, r, map[string]string{"data": "org updated successfully"}) @@ -2447,7 +2420,7 @@ func (ah *APIHandler) calculateLogsConnectionStatus( }, }, } - queryRes, err, _ := ah.querier.QueryRange( + queryRes, _, err := ah.querier.QueryRange( ctx, qrParams, map[string]v3.AttributeKey{}, ) if err != nil { @@ -2967,185 +2940,6 @@ func (aH *APIHandler) autoCompleteAttributeValues(w http.ResponseWriter, r *http aH.Respond(w, response) } -func (aH *APIHandler) execClickHouseGraphQueries(ctx context.Context, queries map[string]string) ([]*v3.Result, error, map[string]error) { - type channelResult struct { - Series []*v3.Series - Err error - Name string - Query string - } - - ch := make(chan channelResult, len(queries)) - var wg sync.WaitGroup - - for name, query := range queries { - wg.Add(1) - go func(name, query string) { - defer wg.Done() - - seriesList, err := aH.reader.GetTimeSeriesResultV3(ctx, query) - - if err != nil { - ch <- channelResult{Err: fmt.Errorf("error in query-%s: %v", name, err), Name: name, Query: query} - return - } - ch <- channelResult{Series: seriesList, Name: name, Query: query} - }(name, query) - } - - wg.Wait() - close(ch) - - var errs []error - errQuriesByName := make(map[string]error) - res := make([]*v3.Result, 0) - // read values from the channel - for r := range ch { - if r.Err != nil { - errs = append(errs, r.Err) - errQuriesByName[r.Name] = r.Err - continue - } - res = append(res, &v3.Result{ - QueryName: r.Name, - Series: r.Series, - }) - } - if len(errs) != 0 { - return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName - } - return res, nil, nil -} - -func (aH *APIHandler) execClickHouseListQueries(ctx context.Context, queries map[string]string) ([]*v3.Result, error, map[string]error) { - type channelResult struct { - List []*v3.Row - Err error - Name string - Query string - } - - ch := make(chan channelResult, len(queries)) - var wg sync.WaitGroup - - for name, query := range queries { - wg.Add(1) - go func(name, query string) { - defer wg.Done() - rowList, err := aH.reader.GetListResultV3(ctx, query) - - if err != nil { - ch <- channelResult{Err: fmt.Errorf("error in query-%s: %v", name, err), Name: name, Query: query} - return - } - ch <- channelResult{List: rowList, Name: name, Query: query} - }(name, query) - } - - wg.Wait() - close(ch) - - var errs []error - errQuriesByName := make(map[string]error) - res := make([]*v3.Result, 0) - // read values from the channel - for r := range ch { - if r.Err != nil { - errs = append(errs, r.Err) - errQuriesByName[r.Name] = r.Err - continue - } - res = append(res, &v3.Result{ - QueryName: r.Name, - List: r.List, - }) - } - if len(errs) != 0 { - return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName - } - return res, nil, nil -} - -func (aH *APIHandler) execPromQueries(ctx context.Context, metricsQueryRangeParams *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) { - type channelResult struct { - Series []*v3.Series - Err error - Name string - Query string - } - - ch := make(chan channelResult, len(metricsQueryRangeParams.CompositeQuery.PromQueries)) - var wg sync.WaitGroup - - for name, query := range metricsQueryRangeParams.CompositeQuery.PromQueries { - if query.Disabled { - continue - } - wg.Add(1) - go func(name string, query *v3.PromQuery) { - var seriesList []*v3.Series - defer wg.Done() - tmpl := template.New("promql-query") - tmpl, tmplErr := tmpl.Parse(query.Query) - if tmplErr != nil { - ch <- channelResult{Err: fmt.Errorf("error in parsing query-%s: %v", name, tmplErr), Name: name, Query: query.Query} - return - } - var queryBuf bytes.Buffer - tmplErr = tmpl.Execute(&queryBuf, metricsQueryRangeParams.Variables) - if tmplErr != nil { - ch <- channelResult{Err: fmt.Errorf("error in parsing query-%s: %v", name, tmplErr), Name: name, Query: query.Query} - return - } - query.Query = queryBuf.String() - queryModel := model.QueryRangeParams{ - Start: time.UnixMilli(metricsQueryRangeParams.Start), - End: time.UnixMilli(metricsQueryRangeParams.End), - Step: time.Duration(metricsQueryRangeParams.Step * int64(time.Second)), - Query: query.Query, - } - promResult, _, err := aH.reader.GetQueryRangeResult(ctx, &queryModel) - if err != nil { - ch <- channelResult{Err: fmt.Errorf("error in query-%s: %v", name, err), Name: name, Query: query.Query} - return - } - matrix, _ := promResult.Matrix() - for _, v := range matrix { - var s v3.Series - s.Labels = v.Metric.Copy().Map() - for _, p := range v.Floats { - s.Points = append(s.Points, v3.Point{Timestamp: p.T, Value: p.F}) - } - seriesList = append(seriesList, &s) - } - ch <- channelResult{Series: seriesList, Name: name, Query: query.Query} - }(name, query) - } - - wg.Wait() - close(ch) - - var errs []error - errQuriesByName := make(map[string]error) - res := make([]*v3.Result, 0) - // read values from the channel - for r := range ch { - if r.Err != nil { - errs = append(errs, r.Err) - errQuriesByName[r.Name] = r.Err - continue - } - res = append(res, &v3.Result{ - QueryName: r.Name, - Series: r.Series, - }) - } - if len(errs) != 0 { - return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName - } - return res, nil, nil -} - func (aH *APIHandler) getLogFieldsV3(ctx context.Context, queryRangeParams *v3.QueryRangeParamsV3) (map[string]v3.AttributeKey, error) { data := map[string]v3.AttributeKey{} for _, query := range queryRangeParams.CompositeQuery.BuilderQueries { @@ -3254,7 +3048,7 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que } } - result, err, errQuriesByName = aH.querier.QueryRange(ctx, queryRangeParams, spanKeys) + result, errQuriesByName, err = aH.querier.QueryRange(ctx, queryRangeParams, spanKeys) if err != nil { apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err} @@ -3262,6 +3056,7 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que return } + postprocess.ApplyHavingClause(result, queryRangeParams) postprocess.ApplyMetricLimit(result, queryRangeParams) sendQueryResultEvents(r, result, queryRangeParams) @@ -3271,6 +3066,10 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que postprocess.ApplyFunctions(result, queryRangeParams) } + if queryRangeParams.CompositeQuery.FillGaps { + postprocess.FillGaps(result, queryRangeParams) + } + resp := v3.QueryRangeResponse{ Result: result, } @@ -3510,7 +3309,7 @@ func (aH *APIHandler) queryRangeV4(ctx context.Context, queryRangeParams *v3.Que } } - result, err, errQuriesByName = aH.querierV2.QueryRange(ctx, queryRangeParams, spanKeys) + result, errQuriesByName, err = aH.querierV2.QueryRange(ctx, queryRangeParams, spanKeys) if err != nil { apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err} diff --git a/pkg/query-service/app/http_handler_test.go b/pkg/query-service/app/http_handler_test.go index 84782f7cae..6993d37168 100644 --- a/pkg/query-service/app/http_handler_test.go +++ b/pkg/query-service/app/http_handler_test.go @@ -67,7 +67,7 @@ func TestPrepareQuery(t *testing.T) { Query: "ALTER TABLE signoz_table DELETE where true", }, expectedErr: true, - errMsg: "Operation alter table is not allowed", + errMsg: "operation alter table is not allowed", }, { name: "query text produces template exec error", diff --git a/pkg/query-service/app/integrations/builtin.go b/pkg/query-service/app/integrations/builtin.go index 00810cacc1..d8099633ab 100644 --- a/pkg/query-service/app/integrations/builtin.go +++ b/pkg/query-service/app/integrations/builtin.go @@ -27,8 +27,8 @@ func (bi *BuiltInIntegrations) list(ctx context.Context) ( []IntegrationDetails, *model.ApiError, ) { integrations := maps.Values(builtInIntegrations) - slices.SortFunc(integrations, func(i1, i2 IntegrationDetails) bool { - return i1.Id < i2.Id + slices.SortFunc(integrations, func(i1, i2 IntegrationDetails) int { + return strings.Compare(i1.Id, i2.Id) }) return integrations, nil } diff --git a/pkg/query-service/app/integrations/controller.go b/pkg/query-service/app/integrations/controller.go index 8695c4b1cd..530bf40c3c 100644 --- a/pkg/query-service/app/integrations/controller.go +++ b/pkg/query-service/app/integrations/controller.go @@ -108,7 +108,7 @@ func (c *Controller) Uninstall( ) *model.ApiError { if len(req.IntegrationId) < 1 { return model.BadRequest(fmt.Errorf( - "integration_id is required.", + "integration_id is required", )) } diff --git a/pkg/query-service/app/integrations/sqlite_repo.go b/pkg/query-service/app/integrations/sqlite_repo.go index 2c3e9fc699..64c8f58c93 100644 --- a/pkg/query-service/app/integrations/sqlite_repo.go +++ b/pkg/query-service/app/integrations/sqlite_repo.go @@ -11,7 +11,7 @@ import ( func InitSqliteDBIfNeeded(db *sqlx.DB) error { if db == nil { - return fmt.Errorf("db is required.") + return fmt.Errorf("db is required") } createTablesStatements := ` diff --git a/pkg/query-service/app/logparsingpipeline/db.go b/pkg/query-service/app/logparsingpipeline/db.go index 618060d105..318f23a035 100644 --- a/pkg/query-service/app/logparsingpipeline/db.go +++ b/pkg/query-service/app/logparsingpipeline/db.go @@ -177,7 +177,7 @@ func (r *Repo) GetPipeline( if len(pipelines) == 0 { zap.L().Warn("No row found for ingestion pipeline id", zap.String("id", id)) - return nil, model.NotFoundError(fmt.Errorf("No row found for ingestion pipeline id %v", id)) + return nil, model.NotFoundError(fmt.Errorf("no row found for ingestion pipeline id %v", id)) } if len(pipelines) == 1 { diff --git a/pkg/query-service/app/logparsingpipeline/postablePipeline.go b/pkg/query-service/app/logparsingpipeline/postablePipeline.go index 790c8c5915..535f47d989 100644 --- a/pkg/query-service/app/logparsingpipeline/postablePipeline.go +++ b/pkg/query-service/app/logparsingpipeline/postablePipeline.go @@ -93,7 +93,7 @@ func (p *PostablePipeline) IsValid() error { func isValidOperator(op PipelineOperator) error { if op.ID == "" { - return errors.New("PipelineOperator.ID is required.") + return errors.New("PipelineOperator.ID is required") } switch op.Type { @@ -204,7 +204,7 @@ func isValidOperator(op PipelineOperator) error { } validMappingLevels := []string{"trace", "debug", "info", "warn", "error", "fatal"} - for k, _ := range op.SeverityMapping { + for k := range op.SeverityMapping { if !slices.Contains(validMappingLevels, strings.ToLower(k)) { return fmt.Errorf("%s is not a valid severity in processor %s", k, op.ID) } diff --git a/pkg/query-service/app/logparsingpipeline/preview.go b/pkg/query-service/app/logparsingpipeline/preview.go index 8f991ee3da..b37295eb96 100644 --- a/pkg/query-service/app/logparsingpipeline/preview.go +++ b/pkg/query-service/app/logparsingpipeline/preview.go @@ -2,8 +2,8 @@ package logparsingpipeline import ( "context" - "fmt" "sort" + "strings" "time" _ "github.com/SigNoz/signoz-otel-collector/pkg/parser/grok" @@ -74,9 +74,9 @@ func SimulatePipelinesProcessing( timeout, ) if apiErr != nil { - return nil, collectorErrs, model.WrapApiError(apiErr, fmt.Sprintf( + return nil, collectorErrs, model.WrapApiError(apiErr, "could not simulate log pipelines processing.\nCollector errors", - )) + ) } outputSignozLogs := PLogsToSignozLogs(outputPLogs) @@ -91,7 +91,15 @@ func SimulatePipelinesProcessing( delete(sigLog.Attributes_int64, inputOrderAttribute) } - return outputSignozLogs, collectorErrs, nil + for _, log := range collectorErrs { + // if log is empty or log comes from featuregate.go, then remove it + if log == "" || strings.Contains(log, "featuregate.go") { + continue + } + collectorWarnAndErrorLogs = append(collectorWarnAndErrorLogs, log) + } + + return outputSignozLogs, collectorWarnAndErrorLogs, nil } // plog doesn't contain an ID field. diff --git a/pkg/query-service/app/logparsingpipeline/preview_test.go b/pkg/query-service/app/logparsingpipeline/preview_test.go index a9c9f43d2e..0dd421dad4 100644 --- a/pkg/query-service/app/logparsingpipeline/preview_test.go +++ b/pkg/query-service/app/logparsingpipeline/preview_test.go @@ -225,15 +225,15 @@ func makeTestSignozLog( } for k, v := range attributes { - switch v.(type) { + switch v := v.(type) { case bool: - testLog.Attributes_bool[k] = v.(bool) + testLog.Attributes_bool[k] = v case string: - testLog.Attributes_string[k] = v.(string) + testLog.Attributes_string[k] = v case int: - testLog.Attributes_int64[k] = int64(v.(int)) + testLog.Attributes_int64[k] = int64(v) case float64: - testLog.Attributes_float64[k] = v.(float64) + testLog.Attributes_float64[k] = v default: panic(fmt.Sprintf("found attribute value of unsupported type %T in test log", v)) } diff --git a/pkg/query-service/app/metrics/v3/query_builder.go b/pkg/query-service/app/metrics/v3/query_builder.go index 9307363361..bb13937d4e 100644 --- a/pkg/query-service/app/metrics/v3/query_builder.go +++ b/pkg/query-service/app/metrics/v3/query_builder.go @@ -2,11 +2,11 @@ package v3 import ( "fmt" - "math" "strings" "time" "go.signoz.io/signoz/pkg/query-service/app/metrics/v4/helpers" + "go.signoz.io/signoz/pkg/query-service/common" "go.signoz.io/signoz/pkg/query-service/constants" "go.signoz.io/signoz/pkg/query-service/model" v3 "go.signoz.io/signoz/pkg/query-service/model/v3" @@ -332,14 +332,8 @@ func reduceQuery(query string, reduceTo v3.ReduceToOperator, aggregateOperator v // start and end are in milliseconds // step is in seconds func PrepareMetricQuery(start, end int64, queryType v3.QueryType, panelType v3.PanelType, mq *v3.BuilderQuery, options Options) (string, error) { - start = start - (start % (mq.StepInterval * 1000)) - // if the query is a rate query, we adjust the start time by one more step - // so that we can calculate the rate for the first data point - if mq.AggregateOperator.IsRateOperator() && mq.Temporality != v3.Delta { - start -= mq.StepInterval * 1000 - } - adjustStep := int64(math.Min(float64(mq.StepInterval), 60)) - end = end - (end % (adjustStep * 1000)) + + start, end = common.AdjustedMetricTimeRange(start, end, mq.StepInterval, *mq) // if the aggregate operator is a histogram quantile, and user has not forgotten // the le tag in the group by then add the le tag to the group by diff --git a/pkg/query-service/app/metrics/v4/query_builder.go b/pkg/query-service/app/metrics/v4/query_builder.go index bd8813dd3a..380fb44f22 100644 --- a/pkg/query-service/app/metrics/v4/query_builder.go +++ b/pkg/query-service/app/metrics/v4/query_builder.go @@ -19,7 +19,7 @@ import ( // step is in seconds func PrepareMetricQuery(start, end int64, queryType v3.QueryType, panelType v3.PanelType, mq *v3.BuilderQuery, options metricsV3.Options) (string, error) { - start, end = common.AdjustedMetricTimeRange(start, end, mq.StepInterval, mq.TimeAggregation) + start, end = common.AdjustedMetricTimeRange(start, end, mq.StepInterval, *mq) var quantile float64 diff --git a/pkg/query-service/app/metrics/v4/query_builder_test.go b/pkg/query-service/app/metrics/v4/query_builder_test.go index 790fa670c8..08d0f087ff 100644 --- a/pkg/query-service/app/metrics/v4/query_builder_test.go +++ b/pkg/query-service/app/metrics/v4/query_builder_test.go @@ -266,7 +266,7 @@ func TestPrepareMetricQueryDeltaRate(t *testing.T) { TimeAggregation: v3.TimeAggregationRate, SpaceAggregation: v3.SpaceAggregationSum, }, - expectedQueryContains: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 GROUP BY ts ORDER BY ts ASC", + expectedQueryContains: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM signoz_metrics.time_series_v4_6hrs WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650974400000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 GROUP BY ts ORDER BY ts ASC", }, { name: "test time aggregation = rate, space aggregation = sum, temporality = delta, group by service_name", @@ -292,7 +292,7 @@ func TestPrepareMetricQueryDeltaRate(t *testing.T) { TimeAggregation: v3.TimeAggregationRate, SpaceAggregation: v3.SpaceAggregationSum, }, - expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC", + expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM signoz_metrics.time_series_v4_6hrs WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650974400000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC", }, } diff --git a/pkg/query-service/app/opamp/model/agents.go b/pkg/query-service/app/opamp/model/agents.go index e984cafce2..2bedc24d5d 100644 --- a/pkg/query-service/app/opamp/model/agents.go +++ b/pkg/query-service/app/opamp/model/agents.go @@ -43,7 +43,7 @@ func InitDB(qsDB *sqlx.DB) (*sqlx.DB, error) { _, err := db.Exec(tableSchema) if err != nil { - return nil, fmt.Errorf("Error in creating agents table: %s", err.Error()) + return nil, fmt.Errorf("error in creating agents table: %s", err.Error()) } AllAgents = Agents{ diff --git a/pkg/query-service/app/opamp/opamp_server.go b/pkg/query-service/app/opamp/opamp_server.go index 75d8d877be..adc72ccdc1 100644 --- a/pkg/query-service/app/opamp/opamp_server.go +++ b/pkg/query-service/app/opamp/opamp_server.go @@ -14,10 +14,8 @@ import ( var opAmpServer *Server type Server struct { - server server.OpAMPServer - agents *model.Agents - logger *zap.Logger - capabilities int32 + server server.OpAMPServer + agents *model.Agents agentConfigProvider AgentConfigProvider @@ -98,8 +96,7 @@ func (srv *Server) OnMessage(conn types.Connection, msg *protobufs.AgentToServer ) } - var response *protobufs.ServerToAgent - response = &protobufs.ServerToAgent{ + response := &protobufs.ServerToAgent{ InstanceUid: agentID, Capabilities: uint64(capabilities), } diff --git a/pkg/query-service/app/parser.go b/pkg/query-service/app/parser.go index 679b7581aa..47da531d0b 100644 --- a/pkg/query-service/app/parser.go +++ b/pkg/query-service/app/parser.go @@ -21,8 +21,8 @@ import ( "go.signoz.io/signoz/pkg/query-service/app/metrics" "go.signoz.io/signoz/pkg/query-service/app/queryBuilder" "go.signoz.io/signoz/pkg/query-service/auth" - baseconstants "go.signoz.io/signoz/pkg/query-service/constants" "go.signoz.io/signoz/pkg/query-service/common" + baseconstants "go.signoz.io/signoz/pkg/query-service/constants" "go.signoz.io/signoz/pkg/query-service/model" v3 "go.signoz.io/signoz/pkg/query-service/model/v3" "go.signoz.io/signoz/pkg/query-service/postprocess" @@ -32,19 +32,6 @@ import ( var allowedFunctions = []string{"count", "ratePerSec", "sum", "avg", "min", "max", "p50", "p90", "p95", "p99"} -func parseUser(r *http.Request) (*model.User, error) { - - var user model.User - if err := json.NewDecoder(r.Body).Decode(&user); err != nil { - return nil, err - } - if len(user.Email) == 0 { - return nil, fmt.Errorf("email field not found") - } - - return &user, nil -} - func parseGetTopOperationsRequest(r *http.Request) (*model.GetTopOperationsParams, error) { var postData *model.GetTopOperationsParams err := json.NewDecoder(r.Body).Decode(&postData) @@ -394,7 +381,7 @@ func parseFilteredSpanAggregatesRequest(r *http.Request) (*model.GetFilteredSpan return nil, errors.New("function param missing in query") } else { if !DoesExistInSlice(function, allowedFunctions) { - return nil, errors.New(fmt.Sprintf("given function: %s is not allowed in query", function)) + return nil, fmt.Errorf("given function: %s is not allowed in query", function) } } @@ -549,11 +536,11 @@ func parseListErrorsRequest(r *http.Request) (*model.ListErrorsParams, error) { } if len(postData.Order) > 0 && !DoesExistInSlice(postData.Order, allowedOrderDirections) { - return nil, errors.New(fmt.Sprintf("given order: %s is not allowed in query", postData.Order)) + return nil, fmt.Errorf("given order: %s is not allowed in query", postData.Order) } if len(postData.Order) > 0 && !DoesExistInSlice(postData.OrderParam, allowedOrderParams) { - return nil, errors.New(fmt.Sprintf("given orderParam: %s is not allowed in query", postData.OrderParam)) + return nil, fmt.Errorf("given orderParam: %s is not allowed in query", postData.OrderParam) } return postData, nil @@ -659,29 +646,6 @@ func parseTime(param string, r *http.Request) (*time.Time, error) { } -func parseTimeMinusBuffer(param string, r *http.Request) (*time.Time, error) { - - timeStr := r.URL.Query().Get(param) - if len(timeStr) == 0 { - return nil, fmt.Errorf("%s param missing in query", param) - } - - timeUnix, err := strconv.ParseInt(timeStr, 10, 64) - if err != nil || len(timeStr) == 0 { - return nil, fmt.Errorf("%s param is not in correct timestamp format", param) - } - - timeUnixNow := time.Now().UnixNano() - if timeUnix > timeUnixNow-30000000000 { - timeUnix = timeUnix - 30000000000 - } - - timeFmt := time.Unix(0, timeUnix) - - return &timeFmt, nil - -} - func parseTTLParams(r *http.Request) (*model.TTLParams, error) { // make sure either of the query params are present @@ -702,7 +666,7 @@ func parseTTLParams(r *http.Request) (*model.TTLParams, error) { // Validate the TTL duration. durationParsed, err := time.ParseDuration(delDuration) if err != nil || durationParsed.Seconds() <= 0 { - return nil, fmt.Errorf("Not a valid TTL duration %v", delDuration) + return nil, fmt.Errorf("not a valid TTL duration %v", delDuration) } var toColdParsed time.Duration @@ -711,10 +675,10 @@ func parseTTLParams(r *http.Request) (*model.TTLParams, error) { if len(coldStorage) > 0 { toColdParsed, err = time.ParseDuration(toColdDuration) if err != nil || toColdParsed.Seconds() <= 0 { - return nil, fmt.Errorf("Not a valid toCold TTL duration %v", toColdDuration) + return nil, fmt.Errorf("not a valid toCold TTL duration %v", toColdDuration) } if toColdParsed.Seconds() != 0 && toColdParsed.Seconds() >= durationParsed.Seconds() { - return nil, fmt.Errorf("Delete TTL should be greater than cold storage move TTL.") + return nil, fmt.Errorf("delete TTL should be greater than cold storage move TTL") } } @@ -842,15 +806,6 @@ func parseChangePasswordRequest(r *http.Request) (*model.ChangePasswordRequest, return &req, nil } -func parseFilterSet(r *http.Request) (*model.FilterSet, error) { - var filterSet model.FilterSet - err := json.NewDecoder(r.Body).Decode(&filterSet) - if err != nil { - return nil, err - } - return &filterSet, nil -} - func parseAggregateAttributeRequest(r *http.Request) (*v3.AggregateAttributeRequest, error) { var req v3.AggregateAttributeRequest @@ -1003,6 +958,9 @@ func ParseQueryRangeParams(r *http.Request) (*v3.QueryRangeParamsV3, *model.ApiE return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("cannot parse the request body: %v", err)} } + // sanitize the request body + queryRangeParams.CompositeQuery.Sanitize() + // validate the request body if err := validateQueryRangeParamsV3(queryRangeParams); err != nil { return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err} diff --git a/pkg/query-service/app/querier/helper.go b/pkg/query-service/app/querier/helper.go index 71ee5da72d..d65627bd92 100644 --- a/pkg/query-service/app/querier/helper.go +++ b/pkg/query-service/app/querier/helper.go @@ -14,6 +14,7 @@ import ( "go.signoz.io/signoz/pkg/query-service/cache/status" "go.signoz.io/signoz/pkg/query-service/constants" v3 "go.signoz.io/signoz/pkg/query-service/model/v3" + "go.signoz.io/signoz/pkg/query-service/postprocess" "go.uber.org/zap" ) @@ -121,7 +122,7 @@ func (q *querier) runBuilderQuery( cachedData = data } } - misses := q.findMissingTimeRanges(start, end, params.Step, cachedData) + misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData) missedSeries := make([]*v3.Series, 0) cachedSeries := make([]*v3.Series, 0) for _, miss := range misses { @@ -256,7 +257,7 @@ func (q *querier) runBuilderQuery( cachedData = data } } - misses := q.findMissingTimeRanges(start, end, params.Step, cachedData) + misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData) missedSeries := make([]*v3.Series, 0) cachedSeries := make([]*v3.Series, 0) for _, miss := range misses { @@ -358,7 +359,8 @@ func (q *querier) runBuilderExpression( cachedData = data } } - misses := q.findMissingTimeRanges(params.Start, params.End, params.Step, cachedData) + step := postprocess.StepIntervalForFunction(params, queryName) + misses := q.findMissingTimeRanges(params.Start, params.End, step, cachedData) missedSeries := make([]*v3.Series, 0) cachedSeries := make([]*v3.Series, 0) for _, miss := range misses { diff --git a/pkg/query-service/app/querier/querier.go b/pkg/query-service/app/querier/querier.go index d07ee4f60d..7668d401cd 100644 --- a/pkg/query-service/app/querier/querier.go +++ b/pkg/query-service/app/querier/querier.go @@ -284,7 +284,7 @@ func mergeSerieses(cachedSeries, missedSeries []*v3.Series) []*v3.Series { return mergedSeries } -func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) { +func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) { cacheKeys := q.keyGenerator.GenerateKeys(params) @@ -327,10 +327,10 @@ func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangePa err = fmt.Errorf("error in builder queries") } - return results, err, errQueriesByName + return results, errQueriesByName, err } -func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) { +func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) { channelResults := make(chan channelResult, len(params.CompositeQuery.PromQueries)) var wg sync.WaitGroup cacheKeys := q.keyGenerator.GenerateKeys(params) @@ -411,10 +411,10 @@ func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParam err = fmt.Errorf("error in prom queries") } - return results, err, errQueriesByName + return results, errQueriesByName, err } -func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) { +func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) { channelResults := make(chan channelResult, len(params.CompositeQuery.ClickHouseQueries)) var wg sync.WaitGroup for queryName, clickHouseQuery := range params.CompositeQuery.ClickHouseQueries { @@ -451,15 +451,15 @@ func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRang if len(errs) > 0 { err = fmt.Errorf("error in clickhouse queries") } - return results, err, errQueriesByName + return results, errQueriesByName, err } -func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) { +func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) { queries, err := q.builder.PrepareQueries(params, keys) if err != nil { - return nil, err, nil + return nil, nil, err } ch := make(chan channelResult, len(queries)) @@ -498,12 +498,12 @@ func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRan }) } if len(errs) != 0 { - return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName + return nil, errQuriesByName, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)) } return res, nil, nil } -func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) { +func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) { var results []*v3.Result var err error var errQueriesByName map[string]error @@ -511,9 +511,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, switch params.CompositeQuery.QueryType { case v3.QueryTypeBuilder: if params.CompositeQuery.PanelType == v3.PanelTypeList || params.CompositeQuery.PanelType == v3.PanelTypeTrace { - results, err, errQueriesByName = q.runBuilderListQueries(ctx, params, keys) + results, errQueriesByName, err = q.runBuilderListQueries(ctx, params, keys) } else { - results, err, errQueriesByName = q.runBuilderQueries(ctx, params, keys) + results, errQueriesByName, err = q.runBuilderQueries(ctx, params, keys) } // in builder query, the only errors we expose are the ones that exceed the resource limits // everything else is internal error as they are not actionable by the user @@ -523,9 +523,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, } } case v3.QueryTypePromQL: - results, err, errQueriesByName = q.runPromQueries(ctx, params) + results, errQueriesByName, err = q.runPromQueries(ctx, params) case v3.QueryTypeClickHouseSQL: - results, err, errQueriesByName = q.runClickHouseQueries(ctx, params) + results, errQueriesByName, err = q.runClickHouseQueries(ctx, params) default: err = fmt.Errorf("invalid query type") } @@ -540,7 +540,7 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, } } - return results, err, errQueriesByName + return results, errQueriesByName, err } func (q *querier) QueriesExecuted() []string { diff --git a/pkg/query-service/app/querier/querier_test.go b/pkg/query-service/app/querier/querier_test.go index 80a3a07422..a9f8cc4030 100644 --- a/pkg/query-service/app/querier/querier_test.go +++ b/pkg/query-service/app/querier/querier_test.go @@ -579,7 +579,7 @@ func TestQueryRange(t *testing.T) { } for i, param := range params { - _, err, errByName := q.QueryRange(context.Background(), param, nil) + _, errByName, err := q.QueryRange(context.Background(), param, nil) if err != nil { t.Errorf("expected no error, got %s", err) } @@ -688,7 +688,7 @@ func TestQueryRangeValueType(t *testing.T) { } for i, param := range params { - _, err, errByName := q.QueryRange(context.Background(), param, nil) + _, errByName, err := q.QueryRange(context.Background(), param, nil) if err != nil { t.Errorf("expected no error, got %s", err) } @@ -741,7 +741,7 @@ func TestQueryRangeTimeShift(t *testing.T) { expectedTimeRangeInQueryString := fmt.Sprintf("timestamp >= %d AND timestamp <= %d", (1675115596722-86400*1000)*1000000, ((1675115596722+120*60*1000)-86400*1000)*1000000) for i, param := range params { - _, err, errByName := q.QueryRange(context.Background(), param, nil) + _, errByName, err := q.QueryRange(context.Background(), param, nil) if err != nil { t.Errorf("expected no error, got %s", err) } @@ -839,7 +839,7 @@ func TestQueryRangeTimeShiftWithCache(t *testing.T) { } for i, param := range params { - _, err, errByName := q.QueryRange(context.Background(), param, nil) + _, errByName, err := q.QueryRange(context.Background(), param, nil) if err != nil { t.Errorf("expected no error, got %s", err) } @@ -939,7 +939,7 @@ func TestQueryRangeTimeShiftWithLimitAndCache(t *testing.T) { } for i, param := range params { - _, err, errByName := q.QueryRange(context.Background(), param, nil) + _, errByName, err := q.QueryRange(context.Background(), param, nil) if err != nil { t.Errorf("expected no error, got %s", err) } diff --git a/pkg/query-service/app/querier/v2/helper.go b/pkg/query-service/app/querier/v2/helper.go index cc4e83b702..04f798ad1b 100644 --- a/pkg/query-service/app/querier/v2/helper.go +++ b/pkg/query-service/app/querier/v2/helper.go @@ -123,7 +123,7 @@ func (q *querier) runBuilderQuery( cachedData = data } } - misses := q.findMissingTimeRanges(start, end, params.Step, cachedData) + misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData) missedSeries := make([]*v3.Series, 0) cachedSeries := make([]*v3.Series, 0) for _, miss := range misses { @@ -257,7 +257,7 @@ func (q *querier) runBuilderQuery( cachedData = data } } - misses := q.findMissingTimeRanges(start, end, params.Step, cachedData) + misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData) missedSeries := make([]*v3.Series, 0) cachedSeries := make([]*v3.Series, 0) for _, miss := range misses { @@ -322,93 +322,3 @@ func (q *querier) runBuilderQuery( } } } - -func (q *querier) runBuilderExpression( - ctx context.Context, - builderQuery *v3.BuilderQuery, - params *v3.QueryRangeParamsV3, - keys map[string]v3.AttributeKey, - cacheKeys map[string]string, - ch chan channelResult, - wg *sync.WaitGroup, -) { - defer wg.Done() - - queryName := builderQuery.QueryName - - queries, err := q.builder.PrepareQueries(params, keys) - if err != nil { - ch <- channelResult{Err: err, Name: queryName, Query: "", Series: nil} - return - } - - if _, ok := cacheKeys[queryName]; !ok { - query := queries[queryName] - series, err := q.execClickHouseQuery(ctx, query) - ch <- channelResult{Err: err, Name: queryName, Query: query, Series: series} - return - } - - cacheKey := cacheKeys[queryName] - var cachedData []byte - if !params.NoCache && q.cache != nil { - var retrieveStatus status.RetrieveStatus - data, retrieveStatus, err := q.cache.Retrieve(cacheKey, true) - zap.L().Info("cache retrieve status", zap.String("status", retrieveStatus.String())) - if err == nil { - cachedData = data - } - } - misses := q.findMissingTimeRanges(params.Start, params.End, params.Step, cachedData) - missedSeries := make([]*v3.Series, 0) - cachedSeries := make([]*v3.Series, 0) - for _, miss := range misses { - missQueries, _ := q.builder.PrepareQueries(&v3.QueryRangeParamsV3{ - Start: miss.start, - End: miss.end, - Step: params.Step, - NoCache: params.NoCache, - CompositeQuery: params.CompositeQuery, - Variables: params.Variables, - }, keys) - query := missQueries[queryName] - series, err := q.execClickHouseQuery(ctx, query) - if err != nil { - ch <- channelResult{Err: err, Name: queryName, Query: query, Series: nil} - return - } - missedSeries = append(missedSeries, series...) - } - if err := json.Unmarshal(cachedData, &cachedSeries); err != nil && cachedData != nil { - zap.L().Error("error unmarshalling cached data", zap.Error(err)) - } - mergedSeries := mergeSerieses(cachedSeries, missedSeries) - - var mergedSeriesData []byte - missedSeriesLen := len(missedSeries) - var marshallingErr error - if missedSeriesLen > 0 && !params.NoCache && q.cache != nil { - // caching the data - mergedSeriesData, marshallingErr = json.Marshal(mergedSeries) - if marshallingErr != nil { - zap.S().Error("error marshalling merged series", zap.Error(marshallingErr)) - } - } - - // response doesn't need everything - filterCachedPoints(mergedSeries, params.Start, params.End) - - ch <- channelResult{ - Err: nil, - Name: queryName, - Series: mergedSeries, - } - // Cache the seriesList for future queries - if len(missedSeries) > 0 && !params.NoCache && q.cache != nil && marshallingErr == nil { - err = q.cache.Store(cacheKey, mergedSeriesData, time.Hour) - if err != nil { - zap.L().Error("error storing merged series", zap.Error(err)) - return - } - } -} diff --git a/pkg/query-service/app/querier/v2/querier.go b/pkg/query-service/app/querier/v2/querier.go index 6754c03ddc..e6915ef078 100644 --- a/pkg/query-service/app/querier/v2/querier.go +++ b/pkg/query-service/app/querier/v2/querier.go @@ -282,7 +282,7 @@ func mergeSerieses(cachedSeries, missedSeries []*v3.Series) []*v3.Series { return mergedSeries } -func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) { +func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) { cacheKeys := q.keyGenerator.GenerateKeys(params) @@ -320,10 +320,10 @@ func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangePa err = fmt.Errorf("error in builder queries") } - return results, err, errQueriesByName + return results, errQueriesByName, err } -func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) { +func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) { channelResults := make(chan channelResult, len(params.CompositeQuery.PromQueries)) var wg sync.WaitGroup cacheKeys := q.keyGenerator.GenerateKeys(params) @@ -404,10 +404,10 @@ func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParam err = fmt.Errorf("error in prom queries") } - return results, err, errQueriesByName + return results, errQueriesByName, err } -func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) { +func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) { channelResults := make(chan channelResult, len(params.CompositeQuery.ClickHouseQueries)) var wg sync.WaitGroup for queryName, clickHouseQuery := range params.CompositeQuery.ClickHouseQueries { @@ -444,15 +444,15 @@ func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRang if len(errs) > 0 { err = fmt.Errorf("error in clickhouse queries") } - return results, err, errQueriesByName + return results, errQueriesByName, err } -func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) { +func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) { queries, err := q.builder.PrepareQueries(params, keys) if err != nil { - return nil, err, nil + return nil, nil, err } ch := make(chan channelResult, len(queries)) @@ -491,12 +491,12 @@ func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRan }) } if len(errs) != 0 { - return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName + return nil, errQuriesByName, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)) } return res, nil, nil } -func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) { +func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) { var results []*v3.Result var err error var errQueriesByName map[string]error @@ -504,9 +504,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, switch params.CompositeQuery.QueryType { case v3.QueryTypeBuilder: if params.CompositeQuery.PanelType == v3.PanelTypeList || params.CompositeQuery.PanelType == v3.PanelTypeTrace { - results, err, errQueriesByName = q.runBuilderListQueries(ctx, params, keys) + results, errQueriesByName, err = q.runBuilderListQueries(ctx, params, keys) } else { - results, err, errQueriesByName = q.runBuilderQueries(ctx, params, keys) + results, errQueriesByName, err = q.runBuilderQueries(ctx, params, keys) } // in builder query, the only errors we expose are the ones that exceed the resource limits // everything else is internal error as they are not actionable by the user @@ -516,9 +516,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, } } case v3.QueryTypePromQL: - results, err, errQueriesByName = q.runPromQueries(ctx, params) + results, errQueriesByName, err = q.runPromQueries(ctx, params) case v3.QueryTypeClickHouseSQL: - results, err, errQueriesByName = q.runClickHouseQueries(ctx, params) + results, errQueriesByName, err = q.runClickHouseQueries(ctx, params) default: err = fmt.Errorf("invalid query type") } @@ -533,7 +533,7 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, } } - return results, err, errQueriesByName + return results, errQueriesByName, err } func (q *querier) QueriesExecuted() []string { diff --git a/pkg/query-service/app/server.go b/pkg/query-service/app/server.go index 773cd7218d..92b879fcc9 100644 --- a/pkg/query-service/app/server.go +++ b/pkg/query-service/app/server.go @@ -27,6 +27,7 @@ import ( "go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline" "go.signoz.io/signoz/pkg/query-service/app/opamp" opAmpModel "go.signoz.io/signoz/pkg/query-service/app/opamp/model" + "go.signoz.io/signoz/pkg/query-service/common" v3 "go.signoz.io/signoz/pkg/query-service/model/v3" "go.signoz.io/signoz/pkg/query-service/app/explorer" @@ -66,12 +67,8 @@ type ServerOptions struct { // Server runs HTTP, Mux and a grpc server type Server struct { - // logger *zap.Logger - // tracer opentracing.Tracer // TODO make part of flags.Service serverOptions *ServerOptions - conn net.Listener ruleManager *rules.Manager - separatePorts bool // public http router httpConn net.Listener @@ -128,7 +125,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) { go clickhouseReader.Start(readerReady) reader = clickhouseReader } else { - return nil, fmt.Errorf("Storage type: %s is not supported in query service", storage) + return nil, fmt.Errorf("storage type: %s is not supported in query service", storage) } skipConfig := &model.SkipConfig{} if serverOptions.SkipTopLvlOpsPath != "" { @@ -303,7 +300,7 @@ func loggingMiddleware(next http.Handler) http.Handler { path, _ := route.GetPathTemplate() startTime := time.Now() next.ServeHTTP(w, r) - zap.L().Info(path+"\ttimeTaken:"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path)) + zap.L().Info(path, zap.Duration("timeTaken", time.Since(startTime)), zap.String("path", path)) }) } @@ -361,7 +358,7 @@ func LogCommentEnricher(next http.Handler) http.Handler { "servicesTab": tab, } - r = r.WithContext(context.WithValue(r.Context(), "log_comment", kvs)) + r = r.WithContext(context.WithValue(r.Context(), common.LogCommentKey, kvs)) next.ServeHTTP(w, r) }) } @@ -374,7 +371,7 @@ func loggingMiddlewarePrivate(next http.Handler) http.Handler { path, _ := route.GetPathTemplate() startTime := time.Now() next.ServeHTTP(w, r) - zap.L().Info(path+"\tprivatePort: true \ttimeTaken"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path), zap.Bool("tprivatePort", true)) + zap.L().Info(path, zap.Duration("timeTaken", time.Since(startTime)), zap.String("path", path), zap.Bool("privatePort", true)) }) } diff --git a/pkg/query-service/auth/auth.go b/pkg/query-service/auth/auth.go index f0d220df81..6041b3c1af 100644 --- a/pkg/query-service/auth/auth.go +++ b/pkg/query-service/auth/auth.go @@ -22,13 +22,18 @@ import ( "golang.org/x/crypto/bcrypt" ) +type JwtContextKeyType string + +const AccessJwtKey JwtContextKeyType = "accessJwt" +const RefreshJwtKey JwtContextKeyType = "refreshJwt" + const ( opaqueTokenSize = 16 minimumPasswordLength = 8 ) var ( - ErrorInvalidCreds = fmt.Errorf("Invalid credentials") + ErrorInvalidCreds = fmt.Errorf("invalid credentials") ) type InviteEmailData struct { @@ -129,7 +134,6 @@ func inviteEmail(req *model.InviteRequest, au *model.UserPayload, token string) zap.L().Error("failed to send email", zap.Error(err)) return } - return } // RevokeInvite is used to revoke the invitation for the given email. @@ -488,10 +492,7 @@ func PasswordHash(pass string) (string, error) { // Checks if the given password results in the given hash. func passwordMatch(hash, password string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) - if err != nil { - return false - } - return true + return err == nil } func GenerateJWTForUser(user *model.User) (model.UserJwtObject, error) { diff --git a/pkg/query-service/auth/jwt.go b/pkg/query-service/auth/jwt.go index b27d43fb9d..7fe70e2c71 100644 --- a/pkg/query-service/auth/jwt.go +++ b/pkg/query-service/auth/jwt.go @@ -64,11 +64,11 @@ func AttachJwtToContext(ctx context.Context, r *http.Request) context.Context { return ctx } - return context.WithValue(ctx, "accessJwt", token) + return context.WithValue(ctx, AccessJwtKey, token) } func ExtractJwtFromContext(ctx context.Context) (string, bool) { - jwtToken, ok := ctx.Value("accessJwt").(string) + jwtToken, ok := ctx.Value(AccessJwtKey).(string) return jwtToken, ok } diff --git a/pkg/query-service/auth/utils.go b/pkg/query-service/auth/utils.go index a6a639c710..8157bf3f07 100644 --- a/pkg/query-service/auth/utils.go +++ b/pkg/query-service/auth/utils.go @@ -19,8 +19,6 @@ func isValidRole(role string) bool { switch role { case constants.AdminGroup, constants.EditorGroup, constants.ViewerGroup: return true - default: - return false } return false } diff --git a/pkg/query-service/collectorsimulator/collectorsimulator.go b/pkg/query-service/collectorsimulator/collectorsimulator.go index e45c2d168a..cf9e6cbafd 100644 --- a/pkg/query-service/collectorsimulator/collectorsimulator.go +++ b/pkg/query-service/collectorsimulator/collectorsimulator.go @@ -119,12 +119,12 @@ func NewCollectorSimulator( return nil, cleanupFn, model.InternalError(errors.Wrap(err, "could not close tmp simulation config file")) } - fp := fileprovider.New() + fp := fileprovider.NewFactory() confProvider, err := otelcol.NewConfigProvider(otelcol.ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{simulationConfigPath}, - Providers: map[string]confmap.Provider{fp.Scheme(): fp}, - Converters: []confmap.Converter{expandconverter.New()}, + URIs: []string{simulationConfigPath}, + ProviderFactories: []confmap.ProviderFactory{fp}, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, }, }) if err != nil { diff --git a/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go b/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go index 7752693060..6bcc3a1226 100644 --- a/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go +++ b/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go @@ -28,7 +28,7 @@ func createLogsExporter( func NewFactory() exporter.Factory { return exporter.NewFactory( - "memory", + component.MustNewType("memory"), createDefaultConfig, exporter.WithLogs(createLogsExporter, component.StabilityLevelBeta)) } diff --git a/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go b/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go index 9db222cc43..584fbb28fb 100644 --- a/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go +++ b/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go @@ -35,7 +35,7 @@ func createLogsReceiver( // NewFactory creates a new OTLP receiver factory. func NewFactory() receiver.Factory { return receiver.NewFactory( - "memory", + component.MustNewType("memory"), createDefaultConfig, receiver.WithLogs(createLogsReceiver, component.StabilityLevelBeta)) } diff --git a/pkg/query-service/collectorsimulator/logs.go b/pkg/query-service/collectorsimulator/logs.go index dc84e6fe56..d1b4f01abb 100644 --- a/pkg/query-service/collectorsimulator/logs.go +++ b/pkg/query-service/collectorsimulator/logs.go @@ -3,6 +3,7 @@ package collectorsimulator import ( "context" "fmt" + "strings" "time" "github.com/pkg/errors" @@ -68,7 +69,15 @@ func SimulateLogsProcessing( ) } - return result, simulationErrs, nil + for _, log := range simulationErrs { + // if log is empty or log comes from featuregate.go, then remove it + if log == "" || strings.Contains(log, "featuregate.go") { + continue + } + collectorErrs = append(collectorErrs, log) + } + + return result, collectorErrs, nil } func SendLogsToSimulator( diff --git a/pkg/query-service/common/ctx.go b/pkg/query-service/common/ctx.go new file mode 100644 index 0000000000..e1599508da --- /dev/null +++ b/pkg/query-service/common/ctx.go @@ -0,0 +1,5 @@ +package common + +type LogCommentContextKeyType string + +const LogCommentKey LogCommentContextKeyType = "logComment" diff --git a/pkg/query-service/common/metrics.go b/pkg/query-service/common/query_range.go similarity index 56% rename from pkg/query-service/common/metrics.go rename to pkg/query-service/common/query_range.go index 3a14e06439..c119f2d25e 100644 --- a/pkg/query-service/common/metrics.go +++ b/pkg/query-service/common/query_range.go @@ -8,13 +8,16 @@ import ( v3 "go.signoz.io/signoz/pkg/query-service/model/v3" ) -func AdjustedMetricTimeRange(start, end, step int64, aggregaOperator v3.TimeAggregation) (int64, int64) { +func AdjustedMetricTimeRange(start, end, step int64, mq v3.BuilderQuery) (int64, int64) { + // align the start to the step interval start = start - (start % (step * 1000)) // if the query is a rate query, we adjust the start time by one more step // so that we can calculate the rate for the first data point - if aggregaOperator.IsRateOperator() { + if (mq.AggregateOperator.IsRateOperator() || mq.TimeAggregation.IsRateOperator()) && + mq.Temporality != v3.Delta { start -= step * 1000 } + // align the end to the nearest minute adjustStep := int64(math.Min(float64(step), 60)) end = end - (end % (adjustStep * 1000)) return start, end @@ -28,6 +31,32 @@ func PastDayRoundOff() int64 { // start and end are in milliseconds func MinAllowedStepInterval(start, end int64) int64 { step := (end - start) / constants.MaxAllowedPointsInTimeSeries / 1000 + if step < 60 { + return step + } // return the nearest lower multiple of 60 return step - step%60 } + +func GCD(a, b int64) int64 { + for b != 0 { + a, b = b, a%b + } + return a +} + +func LCM(a, b int64) int64 { + return (a * b) / GCD(a, b) +} + +// LCMList computes the LCM of a list of int64 numbers. +func LCMList(nums []int64) int64 { + if len(nums) == 0 { + return 1 + } + result := nums[0] + for _, num := range nums[1:] { + result = LCM(result, num) + } + return result +} diff --git a/pkg/query-service/dao/sqlite/connection.go b/pkg/query-service/dao/sqlite/connection.go index a2545e9531..d7e5ad5de9 100644 --- a/pkg/query-service/dao/sqlite/connection.go +++ b/pkg/query-service/dao/sqlite/connection.go @@ -90,7 +90,7 @@ func InitDB(dataSourceName string) (*ModelDaoSqlite, error) { _, err = db.Exec(table_schema) if err != nil { - return nil, fmt.Errorf("Error in creating tables: %v", err.Error()) + return nil, fmt.Errorf("error in creating tables: %v", err.Error()) } mds := &ModelDaoSqlite{db: db} diff --git a/pkg/query-service/integrations/alertManager/notifier.go b/pkg/query-service/integrations/alertManager/notifier.go index e86cf28c5e..e29879f10a 100644 --- a/pkg/query-service/integrations/alertManager/notifier.go +++ b/pkg/query-service/integrations/alertManager/notifier.go @@ -14,7 +14,7 @@ import ( old_ctx "golang.org/x/net/context" - "github.com/go-kit/kit/log" + "github.com/go-kit/log" "github.com/go-kit/log/level" "go.uber.org/zap" diff --git a/pkg/query-service/interfaces/interface.go b/pkg/query-service/interfaces/interface.go index a0631eb70a..9a5e33e5ff 100644 --- a/pkg/query-service/interfaces/interface.go +++ b/pkg/query-service/interfaces/interface.go @@ -107,7 +107,7 @@ type Reader interface { } type Querier interface { - QueryRange(context.Context, *v3.QueryRangeParamsV3, map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) + QueryRange(context.Context, *v3.QueryRangeParamsV3, map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) // test helpers QueriesExecuted() []string diff --git a/pkg/query-service/migrate/0_47_alerts_custom_step/run.go b/pkg/query-service/migrate/0_47_alerts_custom_step/run.go new file mode 100644 index 0000000000..b25705aaf2 --- /dev/null +++ b/pkg/query-service/migrate/0_47_alerts_custom_step/run.go @@ -0,0 +1,70 @@ +package alertscustomstep + +import ( + "context" + "encoding/json" + "time" + + "github.com/jmoiron/sqlx" + v3 "go.signoz.io/signoz/pkg/query-service/model/v3" + "go.signoz.io/signoz/pkg/query-service/rules" + "go.uber.org/multierr" + "go.uber.org/zap" +) + +var Version = "0.47-alerts-custom-step" + +func Migrate(conn *sqlx.DB) error { + ruleDB := rules.NewRuleDB(conn) + storedRules, err := ruleDB.GetStoredRules(context.Background()) + if err != nil { + return err + } + + for _, storedRule := range storedRules { + parsedRule, errs := rules.ParsePostableRule([]byte(storedRule.Data)) + if len(errs) > 0 { + // this should not happen but if it does, we should not stop the migration + zap.L().Error("Error parsing rule", zap.Error(multierr.Combine(errs...)), zap.Int("rule", storedRule.Id)) + continue + } + zap.L().Info("Rule parsed", zap.Int("rule", storedRule.Id)) + updated := false + if parsedRule.RuleCondition != nil { + if parsedRule.RuleCondition.QueryType() == v3.QueryTypeBuilder { + if parsedRule.EvalWindow <= rules.Duration(6*time.Hour) { + for _, query := range parsedRule.RuleCondition.CompositeQuery.BuilderQueries { + if query.StepInterval > 60 { + updated = true + zap.L().Info("Updating step interval", zap.Int("rule", storedRule.Id), zap.Int64("old", query.StepInterval), zap.Int64("new", 60)) + query.StepInterval = 60 + } + } + } + } + } + + if !updated { + zap.L().Info("Rule not updated", zap.Int("rule", storedRule.Id)) + continue + } + + ruleJSON, jsonErr := json.Marshal(parsedRule) + if jsonErr != nil { + zap.L().Error("Error marshalling rule; skipping rule migration", zap.Error(jsonErr), zap.Int("rule", storedRule.Id)) + continue + } + + stmt, prepareError := conn.PrepareContext(context.Background(), `UPDATE rules SET data=$3 WHERE id=$4;`) + if prepareError != nil { + zap.L().Error("Error in preparing statement for UPDATE to rules", zap.Error(prepareError)) + continue + } + defer stmt.Close() + + if _, err := stmt.Exec(ruleJSON, storedRule.Id); err != nil { + zap.L().Error("Error in Executing prepared statement for UPDATE to rules", zap.Error(err)) + } + } + return nil +} diff --git a/pkg/query-service/migrate/migate.go b/pkg/query-service/migrate/migate.go index f9d15a1567..4fe61764bc 100644 --- a/pkg/query-service/migrate/migate.go +++ b/pkg/query-service/migrate/migate.go @@ -5,6 +5,7 @@ import ( "github.com/jmoiron/sqlx" alertstov4 "go.signoz.io/signoz/pkg/query-service/migrate/0_45_alerts_to_v4" + alertscustomstep "go.signoz.io/signoz/pkg/query-service/migrate/0_47_alerts_custom_step" "go.uber.org/zap" ) @@ -63,5 +64,16 @@ func Migrate(dsn string) error { } } + if m, err := getMigrationVersion(conn, "0.47_alerts_custom_step"); err == nil && m == nil { + if err := alertscustomstep.Migrate(conn); err != nil { + zap.L().Error("failed to migrate 0.47_alerts_custom_step", zap.Error(err)) + } else { + _, err := conn.Exec("INSERT INTO data_migrations (version, succeeded) VALUES ('0.47_alerts_custom_step', true)") + if err != nil { + return err + } + } + } + return nil } diff --git a/pkg/query-service/model/v3/v3.go b/pkg/query-service/model/v3/v3.go index 731a1edcac..2a12c8e1fa 100644 --- a/pkg/query-service/model/v3/v3.go +++ b/pkg/query-service/model/v3/v3.go @@ -400,6 +400,7 @@ type CompositeQuery struct { PanelType PanelType `json:"panelType"` QueryType QueryType `json:"queryType"` Unit string `json:"unit,omitempty"` + FillGaps bool `json:"fillGaps,omitempty"` } func (c *CompositeQuery) EnabledQueries() int { @@ -427,6 +428,16 @@ func (c *CompositeQuery) EnabledQueries() int { return count } +func (c *CompositeQuery) Sanitize() { + // remove groupBy for queries with list panel type + for _, query := range c.BuilderQueries { + if len(query.GroupBy) > 0 && c.PanelType == PanelTypeList { + query.GroupBy = []AttributeKey{} + } + } + +} + func (c *CompositeQuery) Validate() error { if c == nil { return fmt.Errorf("composite query is required") @@ -746,9 +757,9 @@ func (b *BuilderQuery) Validate(panelType PanelType) error { } } if b.GroupBy != nil { - if len(b.GroupBy) > 0 && panelType == PanelTypeList { - return fmt.Errorf("group by is not supported for list panel type") - } + // if len(b.GroupBy) > 0 && panelType == PanelTypeList { + // return fmt.Errorf("group by is not supported for list panel type") + // } for _, groupBy := range b.GroupBy { if err := groupBy.Validate(); err != nil { diff --git a/pkg/query-service/postprocess/gaps.go b/pkg/query-service/postprocess/gaps.go new file mode 100644 index 0000000000..170d77844d --- /dev/null +++ b/pkg/query-service/postprocess/gaps.go @@ -0,0 +1,70 @@ +package postprocess + +import ( + "github.com/SigNoz/govaluate" + "go.signoz.io/signoz/pkg/query-service/common" + v3 "go.signoz.io/signoz/pkg/query-service/model/v3" +) + +func StepIntervalForFunction(params *v3.QueryRangeParamsV3, query string) int64 { + q := params.CompositeQuery.BuilderQueries[query] + if q.QueryName != q.Expression { + expression, _ := govaluate.NewEvaluableExpressionWithFunctions(q.Expression, EvalFuncs()) + steps := []int64{} + for _, v := range expression.Vars() { + steps = append(steps, params.CompositeQuery.BuilderQueries[v].StepInterval) + } + return common.LCMList(steps) + } + return q.StepInterval +} + +func fillGap(series *v3.Series, start, end, step int64) *v3.Series { + v := make(map[int64]float64) + for _, point := range series.Points { + v[point.Timestamp] = point.Value + } + + // For all the values from start to end, find the timestamps + // that don't have value and add zero point + start = start - (start % (step * 1000)) + for i := start; i <= end; i += step * 1000 { + if _, ok := v[i]; !ok { + v[i] = 0 + } + } + newSeries := &v3.Series{ + Labels: series.Labels, + LabelsArray: series.LabelsArray, + Points: make([]v3.Point, 0), + } + for i := start; i <= end; i += step * 1000 { + newSeries.Points = append(newSeries.Points, v3.Point{Timestamp: i, Value: v[i]}) + } + return newSeries +} + +// TODO(srikanthccv): can WITH FILL be perfect substitute for all cases https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier +func FillGaps(results []*v3.Result, params *v3.QueryRangeParamsV3) { + for _, result := range results { + // A `result` item in `results` contains the query result for individual query. + // If there are no series in the result, we add empty series and `fillGap` adds all zeros + if len(result.Series) == 0 { + result.Series = []*v3.Series{ + { + Labels: make(map[string]string), + LabelsArray: make([]map[string]string, 0), + }, + } + } + + builderQueries := params.CompositeQuery.BuilderQueries + if builderQueries != nil { + // The values should be added at the intervals of `step` + step := StepIntervalForFunction(params, result.QueryName) + for idx := range result.Series { + result.Series[idx] = fillGap(result.Series[idx], params.Start, params.End, step) + } + } + } +} diff --git a/pkg/query-service/postprocess/gaps_test.go b/pkg/query-service/postprocess/gaps_test.go new file mode 100644 index 0000000000..999176a830 --- /dev/null +++ b/pkg/query-service/postprocess/gaps_test.go @@ -0,0 +1,166 @@ +package postprocess + +import ( + "testing" + + v3 "go.signoz.io/signoz/pkg/query-service/model/v3" +) + +func TestFillGaps(t *testing.T) { + // Helper function to create a sample series + createSeries := func(points []v3.Point) *v3.Series { + return &v3.Series{ + Points: points, + } + } + + // Helper function to create a sample result + createResult := func(queryName string, series []*v3.Series) *v3.Result { + return &v3.Result{ + QueryName: queryName, + Series: series, + } + } + + // Define test cases + tests := []struct { + name string + results []*v3.Result + params *v3.QueryRangeParamsV3 + expected []*v3.Result + }{ + { + name: "Single series with gaps", + results: []*v3.Result{ + createResult("query1", []*v3.Series{ + createSeries([]v3.Point{ + {Timestamp: 1000, Value: 1.0}, + {Timestamp: 3000, Value: 3.0}, + }), + }), + }, + params: &v3.QueryRangeParamsV3{ + Start: 1000, + End: 5000, + CompositeQuery: &v3.CompositeQuery{ + BuilderQueries: map[string]*v3.BuilderQuery{ + "query1": { + QueryName: "query1", + Expression: "query1", + StepInterval: 1, + }, + }, + }, + }, + expected: []*v3.Result{ + createResult("query1", []*v3.Series{ + createSeries([]v3.Point{ + {Timestamp: 1000, Value: 1.0}, + {Timestamp: 2000, Value: 0.0}, + {Timestamp: 3000, Value: 3.0}, + {Timestamp: 4000, Value: 0.0}, + {Timestamp: 5000, Value: 0.0}, + }), + }), + }, + }, + { + name: "Multiple series with gaps", + results: []*v3.Result{ + createResult("query1", []*v3.Series{ + createSeries([]v3.Point{ + {Timestamp: 1000, Value: 1.0}, + {Timestamp: 3000, Value: 3.0}, + }), + createSeries([]v3.Point{ + {Timestamp: 2000, Value: 2.0}, + {Timestamp: 4000, Value: 4.0}, + }), + }), + }, + params: &v3.QueryRangeParamsV3{ + Start: 1000, + End: 5000, + CompositeQuery: &v3.CompositeQuery{ + BuilderQueries: map[string]*v3.BuilderQuery{ + "query1": { + QueryName: "query1", + Expression: "query1", + StepInterval: 1, + }, + }, + }, + }, + expected: []*v3.Result{ + createResult("query1", []*v3.Series{ + createSeries([]v3.Point{ + {Timestamp: 1000, Value: 1.0}, + {Timestamp: 2000, Value: 0.0}, + {Timestamp: 3000, Value: 3.0}, + {Timestamp: 4000, Value: 0.0}, + {Timestamp: 5000, Value: 0.0}, + }), + createSeries([]v3.Point{ + {Timestamp: 1000, Value: 0.0}, + {Timestamp: 2000, Value: 2.0}, + {Timestamp: 3000, Value: 0.0}, + {Timestamp: 4000, Value: 4.0}, + {Timestamp: 5000, Value: 0.0}, + }), + }), + }, + }, + { + name: "Single series with no data", + results: []*v3.Result{ + createResult("query1", []*v3.Series{ + createSeries([]v3.Point{}), + }), + }, + params: &v3.QueryRangeParamsV3{ + Start: 1000, + End: 5000, + CompositeQuery: &v3.CompositeQuery{ + BuilderQueries: map[string]*v3.BuilderQuery{ + "query1": { + QueryName: "query1", + Expression: "query1", + StepInterval: 1, + }, + }, + }, + }, + expected: []*v3.Result{ + createResult("query1", []*v3.Series{ + createSeries([]v3.Point{ + {Timestamp: 1000, Value: 0.0}, + {Timestamp: 2000, Value: 0.0}, + {Timestamp: 3000, Value: 0.0}, + {Timestamp: 4000, Value: 0.0}, + {Timestamp: 5000, Value: 0.0}, + }), + }), + }, + }, + } + + // Execute test cases + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + FillGaps(tt.results, tt.params) + for i, result := range tt.results { + for j, series := range result.Series { + for k, point := range series.Points { + if point.Timestamp != tt.expected[i].Series[j].Points[k].Timestamp || + point.Value != tt.expected[i].Series[j].Points[k].Value { + t.Errorf("Test %s failed: expected (%v, %v), got (%v, %v)", tt.name, + tt.expected[i].Series[j].Points[k].Timestamp, + tt.expected[i].Series[j].Points[k].Value, + point.Timestamp, point.Value) + } + } + } + } + }) + } +} diff --git a/pkg/query-service/postprocess/having.go b/pkg/query-service/postprocess/having.go index a37ba70379..5c2be7ce8b 100644 --- a/pkg/query-service/postprocess/having.go +++ b/pkg/query-service/postprocess/having.go @@ -6,14 +6,17 @@ import ( v3 "go.signoz.io/signoz/pkg/query-service/model/v3" ) -// applyHavingClause applies the having clause to the result +// ApplyHavingClause applies the having clause to the result // each query has its own having clause // there can be multiple having clauses for each query -func applyHavingClause(result []*v3.Result, queryRangeParams *v3.QueryRangeParamsV3) { +func ApplyHavingClause(result []*v3.Result, queryRangeParams *v3.QueryRangeParamsV3) { for _, result := range result { builderQueries := queryRangeParams.CompositeQuery.BuilderQueries - if builderQueries != nil && (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics) { + // apply having clause for metrics and formula + if builderQueries != nil && + (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics || + builderQueries[result.QueryName].QueryName != builderQueries[result.QueryName].Expression) { havingClause := builderQueries[result.QueryName].Having for i := 0; i < len(result.Series); i++ { @@ -37,46 +40,38 @@ func evaluateHavingClause(having []v3.Having, value float64) bool { return true } + satisfied := true + for _, h := range having { switch h.Operator { case v3.HavingOperatorEqual: - if value == h.Value.(float64) { - return true + if value != h.Value.(float64) { + satisfied = false } case v3.HavingOperatorNotEqual: - if value != h.Value.(float64) { - return true + if value == h.Value.(float64) { + satisfied = false } case v3.HavingOperatorGreaterThan: - if value > h.Value.(float64) { - return true + if value <= h.Value.(float64) { + satisfied = false } case v3.HavingOperatorGreaterThanOrEq: - if value >= h.Value.(float64) { - return true + if value < h.Value.(float64) { + satisfied = false } case v3.HavingOperatorLessThan: - if value < h.Value.(float64) { - return true + if value >= h.Value.(float64) { + satisfied = false } case v3.HavingOperatorLessThanOrEq: - if value <= h.Value.(float64) { - return true + if value > h.Value.(float64) { + satisfied = false } case v3.HavingOperatorIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorIn))): values, ok := h.Value.([]interface{}) if !ok { - return false - } - for _, v := range values { - if value == v.(float64) { - return true - } - } - case v3.HavingOperatorNotIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorNotIn))): - values, ok := h.Value.([]interface{}) - if !ok { - return true + satisfied = false } found := false for _, v := range values { @@ -86,9 +81,24 @@ func evaluateHavingClause(having []v3.Having, value float64) bool { } } if !found { - return true + satisfied = false + } + case v3.HavingOperatorNotIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorNotIn))): + values, ok := h.Value.([]interface{}) + if !ok { + satisfied = false + } + found := false + for _, v := range values { + if value == v.(float64) { + found = true + break + } + } + if found { + satisfied = false } } } - return false + return satisfied } diff --git a/pkg/query-service/postprocess/having_test.go b/pkg/query-service/postprocess/having_test.go index e7e37095fb..90986d14a9 100644 --- a/pkg/query-service/postprocess/having_test.go +++ b/pkg/query-service/postprocess/having_test.go @@ -248,22 +248,86 @@ func TestApplyHavingCaluse(t *testing.T) { }, }, }, + { + name: "test multiple having clause", + results: []*v3.Result{ + { + QueryName: "A", + Series: []*v3.Series{ + { + Points: []v3.Point{ + { + Value: 0.5, + }, + { + Value: 0.4, + }, + { + Value: 0.3, + }, + { + Value: 0.2, + }, + { + Value: 0.1, + }, + }, + }, + }, + }, + }, + params: &v3.QueryRangeParamsV3{ + CompositeQuery: &v3.CompositeQuery{ + BuilderQueries: map[string]*v3.BuilderQuery{ + "A": { + DataSource: v3.DataSourceMetrics, + Having: []v3.Having{ + { + Operator: v3.HavingOperatorGreaterThanOrEq, + Value: 0.3, + }, + { + Operator: v3.HavingOperatorLessThanOrEq, + Value: 0.4, + }, + }, + }, + }, + }, + }, + want: []*v3.Result{ + { + Series: []*v3.Series{ + { + Points: []v3.Point{ + { + Value: 0.4, + }, + { + Value: 0.3, + }, + }, + }, + }, + }, + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - applyHavingClause(tc.results, tc.params) + ApplyHavingClause(tc.results, tc.params) got := tc.results if len(got) != len(tc.want) { - t.Errorf("got %v, want %v", got, tc.want) + t.Errorf("got %v, want %v", len(got), len(tc.want)) } for i := range got { if len(got[i].Series) != len(tc.want[i].Series) { - t.Errorf("got %v, want %v", got, tc.want) + t.Errorf("got %v, want %v", len(got[i].Series), len(tc.want[i].Series)) } for j := range got[i].Series { @@ -273,7 +337,7 @@ func TestApplyHavingCaluse(t *testing.T) { for k := range got[i].Series[j].Points { if got[i].Series[j].Points[k].Value != tc.want[i].Series[j].Points[k].Value { - t.Errorf("got %v, want %v", got, tc.want) + t.Errorf("got %v, want %v", got[i].Series[j].Points[k].Value, tc.want[i].Series[j].Points[k].Value) } } } diff --git a/pkg/query-service/postprocess/limit.go b/pkg/query-service/postprocess/limit.go index 491c91da54..49cd5d04b9 100644 --- a/pkg/query-service/postprocess/limit.go +++ b/pkg/query-service/postprocess/limit.go @@ -17,7 +17,10 @@ func ApplyMetricLimit(results []*v3.Result, queryRangeParams *v3.QueryRangeParam for _, result := range results { builderQueries := queryRangeParams.CompositeQuery.BuilderQueries - if builderQueries != nil && (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics) { + // apply limit for metrics and formula + if builderQueries != nil && + (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics || + builderQueries[result.QueryName].QueryName != builderQueries[result.QueryName].Expression) { limit := builderQueries[result.QueryName].Limit orderByList := builderQueries[result.QueryName].OrderBy diff --git a/pkg/query-service/postprocess/query_range.go b/pkg/query-service/postprocess/process.go similarity index 94% rename from pkg/query-service/postprocess/query_range.go rename to pkg/query-service/postprocess/process.go index b6bd6461f3..fc35b404de 100644 --- a/pkg/query-service/postprocess/query_range.go +++ b/pkg/query-service/postprocess/process.go @@ -18,7 +18,7 @@ func PostProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam // It's not included in the query because it doesn't work nicely with caching // With this change, if you have a query with a having clause, and then you change the having clause // to something else, the query will still be cached. - applyHavingClause(result, queryRangeParams) + ApplyHavingClause(result, queryRangeParams) // We apply the metric limit here because it's not part of the clickhouse query // The limit in the context of the time series query is the number of time series // So for the limit to work, we need to know what series to keep and what to discard @@ -64,6 +64,8 @@ func PostProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam return nil, err } formulaResult.QueryName = query.QueryName + ApplyHavingClause([]*v3.Result{formulaResult}, queryRangeParams) + ApplyMetricLimit([]*v3.Result{formulaResult}, queryRangeParams) result = append(result, formulaResult) } } @@ -81,6 +83,9 @@ func PostProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam if queryRangeParams.CompositeQuery.QueryType == v3.QueryTypeBuilder { result = removeDisabledQueries(result) } + if queryRangeParams.CompositeQuery.FillGaps { + FillGaps(result, queryRangeParams) + } return result, nil } diff --git a/pkg/query-service/postprocess/process_test.go b/pkg/query-service/postprocess/process_test.go new file mode 100644 index 0000000000..5f599f7be0 --- /dev/null +++ b/pkg/query-service/postprocess/process_test.go @@ -0,0 +1,222 @@ +package postprocess + +import ( + "reflect" + "testing" + + v3 "go.signoz.io/signoz/pkg/query-service/model/v3" +) + +func TestPostProcessResult(t *testing.T) { + testCases := []struct { + name string + results []*v3.Result + queryRangeParams *v3.QueryRangeParamsV3 + want []*v3.Result + }{ + { + name: "test1", + results: []*v3.Result{ + { + QueryName: "A", + Series: []*v3.Series{ + { + Labels: map[string]string{ + "service_name": "frontend", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 10, + }, + { + Timestamp: 2, + Value: 20, + }, + }, + }, + { + Labels: map[string]string{ + "service_name": "redis", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 12, + }, + { + Timestamp: 2, + Value: 45, + }, + }, + }, + { + Labels: map[string]string{ + "service_name": "route", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 2, + }, + { + Timestamp: 2, + Value: 45, + }, + }, + }, + }, + }, + { + QueryName: "B", + Series: []*v3.Series{ + { + Labels: map[string]string{ + "service_name": "redis", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 6, + }, + { + Timestamp: 2, + Value: 9, + }, + }, + }, + }, + }, + }, + want: []*v3.Result{ + { + QueryName: "A", + Series: []*v3.Series{ + { + Labels: map[string]string{ + "service_name": "redis", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 12, + }, + { + Timestamp: 2, + Value: 45, + }, + }, + }, + { + Labels: map[string]string{ + "service_name": "route", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 2, + }, + { + Timestamp: 2, + Value: 45, + }, + }, + }, + { + Labels: map[string]string{ + "service_name": "frontend", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 10, + }, + { + Timestamp: 2, + Value: 20, + }, + }, + }, + }, + }, + { + QueryName: "B", + Series: []*v3.Series{ + { + Labels: map[string]string{ + "service_name": "redis", + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 6, + }, + { + Timestamp: 2, + Value: 9, + }, + }, + }, + }, + }, + { + QueryName: "F1", + Series: []*v3.Series{ + { + Labels: map[string]string{ + "service_name": "redis", + }, + LabelsArray: []map[string]string{ + { + "service_name": "redis", + }, + }, + Points: []v3.Point{ + { + Timestamp: 1, + Value: 0.5, + }, + { + Timestamp: 2, + Value: 0.2, + }, + }, + }, + }, + }, + }, + queryRangeParams: &v3.QueryRangeParamsV3{ + CompositeQuery: &v3.CompositeQuery{ + BuilderQueries: map[string]*v3.BuilderQuery{ + "A": { + DataSource: v3.DataSourceMetrics, + QueryName: "A", + Expression: "A", + }, + "B": { + DataSource: v3.DataSourceMetrics, + QueryName: "B", + Expression: "B", + }, + "F1": { + Expression: "B/A", + QueryName: "F1", + Limit: 1, + }, + }, + }, + }, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + got, err := PostProcessResult(tt.results, tt.queryRangeParams) + if err != nil { + t.Errorf("PostProcessResult() error = %v", err) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("PostProcessResult() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/query-service/pqlEngine/engine.go b/pkg/query-service/pqlEngine/engine.go index 99cd4ea6df..0ecb7fc766 100644 --- a/pkg/query-service/pqlEngine/engine.go +++ b/pkg/query-service/pqlEngine/engine.go @@ -8,7 +8,6 @@ import ( "github.com/go-kit/log" pmodel "github.com/prometheus/common/model" "github.com/prometheus/common/promlog" - plog "github.com/prometheus/common/promlog" pconfig "github.com/prometheus/prometheus/config" pql "github.com/prometheus/prometheus/promql" pstorage "github.com/prometheus/prometheus/storage" @@ -40,7 +39,7 @@ func FromReader(ch interfaces.Reader) (*PqlEngine, error) { func NewPqlEngine(config *pconfig.Config) (*PqlEngine, error) { - logLevel := plog.AllowedLevel{} + logLevel := promlog.AllowedLevel{} logLevel.Set("debug") allowedFormat := promlog.AllowedFormat{} @@ -51,7 +50,7 @@ func NewPqlEngine(config *pconfig.Config) (*PqlEngine, error) { Format: &allowedFormat, } - logger := plog.New(&promlogConfig) + logger := promlog.New(&promlogConfig) opts := pql.EngineOpts{ Logger: log.With(logger, "component", "promql evaluator"), diff --git a/pkg/query-service/rules/promRuleTask.go b/pkg/query-service/rules/promRuleTask.go index 57b7a58dc7..13c24ca1fa 100644 --- a/pkg/query-service/rules/promRuleTask.go +++ b/pkg/query-service/rules/promRuleTask.go @@ -10,6 +10,7 @@ import ( "github.com/go-kit/log" opentracing "github.com/opentracing/opentracing-go" plabels "github.com/prometheus/prometheus/model/labels" + "go.signoz.io/signoz/pkg/query-service/common" "go.uber.org/zap" ) @@ -364,7 +365,7 @@ func (g *PromRuleTask) Eval(ctx context.Context, ts time.Time) { "source": "alerts", "client": "query-service", } - ctx = context.WithValue(ctx, "log_comment", kvs) + ctx = context.WithValue(ctx, common.LogCommentKey, kvs) _, err := rule.Eval(ctx, ts, g.opts.Queriers) if err != nil { diff --git a/pkg/query-service/rules/ruleTask.go b/pkg/query-service/rules/ruleTask.go index 577bd453a5..eb657c9f7c 100644 --- a/pkg/query-service/rules/ruleTask.go +++ b/pkg/query-service/rules/ruleTask.go @@ -8,6 +8,7 @@ import ( "time" opentracing "github.com/opentracing/opentracing-go" + "go.signoz.io/signoz/pkg/query-service/common" "go.signoz.io/signoz/pkg/query-service/utils/labels" "go.uber.org/zap" ) @@ -345,7 +346,7 @@ func (g *RuleTask) Eval(ctx context.Context, ts time.Time) { "source": "alerts", "client": "query-service", } - ctx = context.WithValue(ctx, "log_comment", kvs) + ctx = context.WithValue(ctx, common.LogCommentKey, kvs) _, err := rule.Eval(ctx, ts, g.opts.Queriers) if err != nil { diff --git a/pkg/query-service/rules/templates.go b/pkg/query-service/rules/templates.go index 9cc49f787d..5f29621c68 100644 --- a/pkg/query-service/rules/templates.go +++ b/pkg/query-service/rules/templates.go @@ -14,6 +14,8 @@ import ( html_template "html/template" text_template "text/template" + "golang.org/x/text/cases" + "go.signoz.io/signoz/pkg/query-service/utils/times" ) @@ -96,7 +98,7 @@ func NewTemplateExpander( return html_template.HTML(text) }, "match": regexp.MatchString, - "title": strings.Title, + "title": cases.Title, "toUpper": strings.ToUpper, "toLower": strings.ToLower, "sortByLabel": func(label string, v tmplQueryResults) tmplQueryResults { diff --git a/pkg/query-service/rules/thresholdRule.go b/pkg/query-service/rules/thresholdRule.go index 0b8d080bd9..051476e6b8 100644 --- a/pkg/query-service/rules/thresholdRule.go +++ b/pkg/query-service/rules/thresholdRule.go @@ -427,7 +427,6 @@ func (r *ThresholdRule) prepareQueryRange(ts time.Time) *v3.QueryRangeParamsV3 { // 60 seconds (SDK) + 10 seconds (batch) + rest for n/w + serialization + write to disk etc.. start := ts.Add(-time.Duration(r.evalWindow)).UnixMilli() - 2*60*1000 end := ts.UnixMilli() - 2*60*1000 - // round to minute otherwise we could potentially miss data start = start - (start % (60 * 1000)) end = end - (end % (60 * 1000)) @@ -478,10 +477,17 @@ func (r *ThresholdRule) prepareQueryRange(ts time.Time) *v3.QueryRangeParamsV3 { if r.ruleCondition.CompositeQuery != nil && r.ruleCondition.CompositeQuery.BuilderQueries != nil { for _, q := range r.ruleCondition.CompositeQuery.BuilderQueries { - q.StepInterval = int64(math.Max(float64(common.MinAllowedStepInterval(start, end)), 60)) + // If the step interval is less than the minimum allowed step interval, set it to the minimum allowed step interval + if minStep := common.MinAllowedStepInterval(start, end); q.StepInterval < minStep { + q.StepInterval = minStep + } } } + if r.ruleCondition.CompositeQuery.PanelType != v3.PanelTypeGraph { + r.ruleCondition.CompositeQuery.PanelType = v3.PanelTypeGraph + } + // default mode return &v3.QueryRangeParamsV3{ Start: start, @@ -767,9 +773,9 @@ func (r *ThresholdRule) buildAndRunQuery(ctx context.Context, ts time.Time, ch c var errQuriesByName map[string]error if r.version == "v4" { - results, err, errQuriesByName = r.querierV2.QueryRange(ctx, params, map[string]v3.AttributeKey{}) + results, errQuriesByName, err = r.querierV2.QueryRange(ctx, params, map[string]v3.AttributeKey{}) } else { - results, err, errQuriesByName = r.querier.QueryRange(ctx, params, map[string]v3.AttributeKey{}) + results, errQuriesByName, err = r.querier.QueryRange(ctx, params, map[string]v3.AttributeKey{}) } if err != nil { diff --git a/pkg/query-service/rules/thresholdRule_test.go b/pkg/query-service/rules/thresholdRule_test.go index 762666cbf3..115ccddc4c 100644 --- a/pkg/query-service/rules/thresholdRule_test.go +++ b/pkg/query-service/rules/thresholdRule_test.go @@ -797,7 +797,7 @@ func TestThresholdRuleLabelNormalization(t *testing.T) { "service.name": "frontend", }, LabelsArray: []map[string]string{ - map[string]string{ + { "service.name": "frontend", }, }, diff --git a/pkg/query-service/telemetry/telemetry.go b/pkg/query-service/telemetry/telemetry.go index 3625a3c9e2..22be2a8648 100644 --- a/pkg/query-service/telemetry/telemetry.go +++ b/pkg/query-service/telemetry/telemetry.go @@ -197,8 +197,6 @@ func createTelemetry() { telemetry.minRandInt = 0 telemetry.maxRandInt = int(1 / DEFAULT_SAMPLING) - rand.Seed(time.Now().UnixNano()) - telemetry.SetTelemetryEnabled(constants.IsTelemetryEnabled()) ticker := time.NewTicker(HEART_BEAT_DURATION) @@ -207,6 +205,7 @@ func createTelemetry() { rateLimitTicker := time.NewTicker(RATE_LIMIT_CHECK_DURATION) go func() { + //lint:ignore S1000 false positive for { select { case <-rateLimitTicker.C: @@ -461,6 +460,7 @@ func (a *Telemetry) SendEvent(event string, data map[string]interface{}, userEma if userEmail != "" { a.SetUserEmail(userEmail) + a.SetCompanyDomain(userEmail) } if !a.isTelemetryEnabled() { diff --git a/pkg/query-service/tests/auth_test.go b/pkg/query-service/tests/auth_test.go index e5ca9ed4a2..7c7d5277b6 100644 --- a/pkg/query-service/tests/auth_test.go +++ b/pkg/query-service/tests/auth_test.go @@ -31,7 +31,7 @@ func invite(t *testing.T, email string) *model.InviteResponse { } func register(email, password, token string) (string, error) { - q := endpoint + fmt.Sprintf("/api/v1/register") + q := endpoint + "/api/v1/register" req := auth.RegisterRequest{ Email: email, @@ -58,7 +58,7 @@ func register(email, password, token string) (string, error) { } func login(email, password, refreshToken string) (*model.LoginResponse, error) { - q := endpoint + fmt.Sprintf("/api/v1/login") + q := endpoint + "/api/v1/login" req := model.LoginRequest{ Email: email, diff --git a/pkg/query-service/tests/integration/logparsingpipeline_test.go b/pkg/query-service/tests/integration/logparsingpipeline_test.go index 9ef47171a4..93efe30dc2 100644 --- a/pkg/query-service/tests/integration/logparsingpipeline_test.go +++ b/pkg/query-service/tests/integration/logparsingpipeline_test.go @@ -645,6 +645,7 @@ func assertPipelinesRecommendedInRemoteConfig( } _, expectedLogProcessorNames, err := logparsingpipeline.PreparePipelineProcessor(pipelines) + require.NoError(t, err) require.Equal( t, expectedLogProcessorNames, collectorConfLogsPipelineProcNames, "config sent to opamp client doesn't contain expected log pipelines", diff --git a/pkg/query-service/tests/integration/test_utils.go b/pkg/query-service/tests/integration/test_utils.go index ac6e1db7c5..7775171310 100644 --- a/pkg/query-service/tests/integration/test_utils.go +++ b/pkg/query-service/tests/integration/test_utils.go @@ -123,15 +123,15 @@ func makeTestSignozLog( } for k, v := range attributes { - switch v.(type) { + switch v := v.(type) { case bool: - testLog.Attributes_bool[k] = v.(bool) + testLog.Attributes_bool[k] = v case string: - testLog.Attributes_string[k] = v.(string) + testLog.Attributes_string[k] = v case int: - testLog.Attributes_int64[k] = int64(v.(int)) + testLog.Attributes_int64[k] = int64(v) case float64: - testLog.Attributes_float64[k] = v.(float64) + testLog.Attributes_float64[k] = v default: panic(fmt.Sprintf("found attribute value of unsupported type %T in test log", v)) } diff --git a/pkg/query-service/tests/test-deploy/docker-compose.yaml b/pkg/query-service/tests/test-deploy/docker-compose.yaml index 67d6f6d508..1fb37ce2ff 100644 --- a/pkg/query-service/tests/test-deploy/docker-compose.yaml +++ b/pkg/query-service/tests/test-deploy/docker-compose.yaml @@ -192,7 +192,7 @@ services: <<: *db-depend otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.26} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.0} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -205,7 +205,7 @@ services: # condition: service_healthy otel-collector: - image: signoz/signoz-otel-collector:0.88.26 + image: signoz/signoz-otel-collector:0.102.0 container_name: signoz-otel-collector command: [ diff --git a/pkg/query-service/utils/time.go b/pkg/query-service/utils/time.go index 274b032cdb..612da4f4bc 100644 --- a/pkg/query-service/utils/time.go +++ b/pkg/query-service/utils/time.go @@ -1,20 +1,19 @@ package utils import ( - "fmt" "time" "go.uber.org/zap" ) -func Elapsed(funcName string, args ...interface{}) func() { +func Elapsed(funcName string, args map[string]interface{}) func() { start := time.Now() - argsStr := "" - for _, v := range args { - argsStr += fmt.Sprintf("%v, ", v) - } - argsStr = argsStr[:len(argsStr)-2] return func() { - zap.L().Info("Elapsed time", zap.String("func_name", funcName), zap.Duration("duration", time.Since(start)), zap.String("args", argsStr)) + var zapFields []zap.Field + zapFields = append(zapFields, zap.String("func_name", funcName), zap.Duration("duration", time.Since(start))) + for k, v := range args { + zapFields = append(zapFields, zap.Any(k, v)) + } + zap.L().Info("Elapsed time", zapFields...) } }