From bdce97a727c8ff986bcd1899c97c7c37467fea91 Mon Sep 17 00:00:00 2001 From: Pranjul Kalsi Date: Mon, 27 Oct 2025 16:30:18 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20replace=20fmt.Errorf=20with=20signoz/pkg?= =?UTF-8?q?/errors=20and=20update=20golangci-li=E2=80=A6=20(#9373)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fulfills the requirements of #9069 by: - Adding a golangci-lint directive (forbidigo) to disallow all fmt.Errorf usages. - Replacing existing fmt.Errorf instances with structured errors from github.com/SigNoz/signoz/pkg/errors for consistent error classification and lint compliance. - Verified lint and build integrity. --- .golangci.yml | 4 + ee/licensing/config.go | 4 +- ee/zeus/config.go | 8 +- .../alertmanagernotify/msteamsv2/msteamsv2.go | 4 +- pkg/alertmanager/alertmanagerserver/server.go | 10 +- .../nfmanager/nfmanagertest/provider.go | 24 ++--- pkg/config/uri.go | 6 +- pkg/errors/code.go | 3 +- pkg/errors/errors.go | 2 +- pkg/errors/errors_test.go | 6 +- pkg/factory/name.go | 5 +- pkg/factory/named.go | 23 ++++- pkg/http/middleware/response.go | 5 +- pkg/http/server/server.go | 6 +- pkg/instrumentation/metric.go | 4 +- pkg/modules/savedview/implsavedview/module.go | 24 ++--- .../clickhouse_queries_latency_test.go | 34 +++---- .../tracefunnel/clickhouse_queries_test.go | 32 +++---- .../tracefunnel/impltracefunnel/module.go | 4 +- .../tracefunnel/impltracefunnel/store.go | 4 +- .../store_duplicate_names_test.go | 4 +- pkg/modules/tracefunnel/query.go | 4 +- pkg/modules/tracefunnel/query_test.go | 12 +-- pkg/prometheus/clickhouseprometheus/client.go | 5 +- pkg/prometheus/utils.go | 4 +- pkg/querier/postprocess.go | 1 - pkg/querier/querier.go | 10 +- pkg/querier/trace_operator_query.go | 1 - pkg/querybuilder/never_true.go | 5 +- .../resourcefilter/statement_builder.go | 2 +- pkg/signoz/config.go | 6 +- pkg/smtp/client/smtp.go | 44 ++++----- pkg/sqlschema/sqlitesqlschema/ddl.go | 4 +- pkg/sqlstore/sqlstoretest/provider.go | 7 +- pkg/telemetrylogs/condition_builder.go | 5 +- pkg/telemetrylogs/statement_builder.go | 3 +- pkg/telemetrymetadata/metadata_test.go | 4 +- pkg/telemetrytraces/condition_builder.go | 2 +- pkg/telemetrytraces/statement_builder.go | 8 +- .../trace_operator_cte_builder.go | 5 +- pkg/telemetrytraces/trace_time_range.go | 16 ++-- .../trace_time_range_multi_test.go | 36 +++---- pkg/types/alertmanagertypes/template.go | 4 +- pkg/types/integration.go | 29 +++--- pkg/types/licensetypes/license.go | 5 +- pkg/types/pipelinetypes/pipeline.go | 94 ++++++++++--------- pkg/types/pipelinetypes/time_parser.go | 3 +- pkg/types/ruletypes/api_params.go | 3 +- pkg/types/ruletypes/templates.go | 14 +-- pkg/types/telemetrytypes/field_context.go | 6 +- pkg/types/telemetrytypes/field_datatype.go | 6 +- .../telemetrytypestest/load_keys.go | 8 +- pkg/types/tracefunneltypes/utils.go | 13 ++- pkg/variables/clickhouse/processor.go | 4 +- pkg/variables/variable_replace_visitor.go | 7 +- pkg/web/routerweb/provider.go | 12 +-- 56 files changed, 315 insertions(+), 293 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 00643925fd..d40d84f53a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -32,6 +32,10 @@ linters-settings: iface: enable: - identical + forbidigo: + forbid: + - fmt.Errorf + - ^(fmt\.Print.*|print|println)$ issues: exclude-dirs: - "pkg/query-service" diff --git a/ee/licensing/config.go b/ee/licensing/config.go index 598724d8e3..8fc87c0ba1 100644 --- a/ee/licensing/config.go +++ b/ee/licensing/config.go @@ -1,10 +1,10 @@ package licensing import ( - "fmt" "sync" "time" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/licensing" ) @@ -18,7 +18,7 @@ func Config(pollInterval time.Duration, failureThreshold int) licensing.Config { once.Do(func() { config = licensing.Config{PollInterval: pollInterval, FailureThreshold: failureThreshold} if err := config.Validate(); err != nil { - panic(fmt.Errorf("invalid licensing config: %w", err)) + panic(errors.WrapInternalf(err, errors.CodeInternal, "invalid licensing config")) } }) diff --git a/ee/zeus/config.go b/ee/zeus/config.go index 0863f160b3..2a81e55608 100644 --- a/ee/zeus/config.go +++ b/ee/zeus/config.go @@ -1,10 +1,10 @@ package zeus import ( - "fmt" neturl "net/url" "sync" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/zeus" ) @@ -24,17 +24,17 @@ func Config() zeus.Config { once.Do(func() { parsedURL, err := neturl.Parse(url) if err != nil { - panic(fmt.Errorf("invalid zeus URL: %w", err)) + panic(errors.WrapInternalf(err, errors.CodeInternal, "invalid zeus URL")) } deprecatedParsedURL, err := neturl.Parse(deprecatedURL) if err != nil { - panic(fmt.Errorf("invalid zeus deprecated URL: %w", err)) + panic(errors.WrapInternalf(err, errors.CodeInternal, "invalid zeus deprecated URL")) } config = zeus.Config{URL: parsedURL, DeprecatedURL: deprecatedParsedURL} if err := config.Validate(); err != nil { - panic(fmt.Errorf("invalid zeus config: %w", err)) + panic(errors.WrapInternalf(err, errors.CodeInternal, "invalid zeus config")) } }) diff --git a/pkg/alertmanager/alertmanagernotify/msteamsv2/msteamsv2.go b/pkg/alertmanager/alertmanagernotify/msteamsv2/msteamsv2.go index d2be7ed199..257f0a4aa7 100644 --- a/pkg/alertmanager/alertmanagernotify/msteamsv2/msteamsv2.go +++ b/pkg/alertmanager/alertmanagernotify/msteamsv2/msteamsv2.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "log/slog" "net/http" @@ -12,6 +11,7 @@ import ( "slices" "strings" + "github.com/SigNoz/signoz/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -145,7 +145,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) } else { content, err := os.ReadFile(n.conf.WebhookURLFile) if err != nil { - return false, fmt.Errorf("read webhook_url_file: %w", err) + return false, errors.WrapInternalf(err, errors.CodeInternal, "read webhook_url_file") } url = strings.TrimSpace(string(content)) } diff --git a/pkg/alertmanager/alertmanagerserver/server.go b/pkg/alertmanager/alertmanagerserver/server.go index 208a5ee888..457bb34826 100644 --- a/pkg/alertmanager/alertmanagerserver/server.go +++ b/pkg/alertmanager/alertmanagerserver/server.go @@ -2,14 +2,14 @@ package alertmanagerserver import ( "context" - "fmt" - "github.com/prometheus/alertmanager/types" - "golang.org/x/sync/errgroup" "log/slog" "strings" "sync" "time" + "github.com/prometheus/alertmanager/types" + "golang.org/x/sync/errgroup" + "github.com/SigNoz/signoz/pkg/alertmanager/alertmanagernotify" "github.com/SigNoz/signoz/pkg/alertmanager/nfmanager" "github.com/SigNoz/signoz/pkg/errors" @@ -395,7 +395,7 @@ func (server *Server) TestAlert(ctx context.Context, receiversMap map[*alertmana receiver, err := server.alertmanagerConfig.GetReceiver(receiverName) if err != nil { mu.Lock() - errs = append(errs, fmt.Errorf("failed to get receiver %q: %w", receiverName, err)) + errs = append(errs, errors.WrapInternalf(err, errors.CodeInternal, "failed to get receiver %q", receiverName)) mu.Unlock() return nil // Return nil to continue processing other goroutines } @@ -412,7 +412,7 @@ func (server *Server) TestAlert(ctx context.Context, receiversMap map[*alertmana ) if err != nil { mu.Lock() - errs = append(errs, fmt.Errorf("receiver %q test failed: %w", receiverName, err)) + errs = append(errs, errors.WrapInternalf(err, errors.CodeInternal, "receiver %q test failed", receiverName)) mu.Unlock() } return nil // Return nil to continue processing other goroutines diff --git a/pkg/alertmanager/nfmanager/nfmanagertest/provider.go b/pkg/alertmanager/nfmanager/nfmanagertest/provider.go index dfb9304956..f003c4454d 100644 --- a/pkg/alertmanager/nfmanager/nfmanagertest/provider.go +++ b/pkg/alertmanager/nfmanager/nfmanagertest/provider.go @@ -2,9 +2,9 @@ package nfmanagertest import ( "context" - "fmt" "strings" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/types/alertmanagertypes" "github.com/prometheus/common/model" ) @@ -94,7 +94,7 @@ func (m *MockNotificationManager) CreateRoutePolicy(ctx context.Context, orgID s } if route == nil { - return fmt.Errorf("route cannot be nil") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "route cannot be nil") } if err := route.Validate(); err != nil { @@ -116,14 +116,14 @@ func (m *MockNotificationManager) CreateRoutePolicies(ctx context.Context, orgID } if len(routes) == 0 { - return fmt.Errorf("routes cannot be empty") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "routes cannot be empty") } for i, route := range routes { if route == nil { - return fmt.Errorf("route at index %d cannot be nil", i) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "route at index %d cannot be nil", i) } if err := route.Validate(); err != nil { - return fmt.Errorf("route at index %d: %s", i, err.Error()) + return errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "route at index %d", i) } } for _, route := range routes { @@ -142,13 +142,13 @@ func (m *MockNotificationManager) GetRoutePolicyByID(ctx context.Context, orgID } if routeID == "" { - return nil, fmt.Errorf("routeID cannot be empty") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "routeID cannot be empty") } routeKey := getKey(orgID, routeID) route, exists := m.routes[routeKey] if !exists { - return nil, fmt.Errorf("route with ID %s not found", routeID) + return nil, errors.NewNotFoundf(errors.CodeNotFound, "route with ID %s not found", routeID) } return route, nil @@ -161,7 +161,7 @@ func (m *MockNotificationManager) GetAllRoutePolicies(ctx context.Context, orgID } if orgID == "" { - return nil, fmt.Errorf("orgID cannot be empty") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "orgID cannot be empty") } var routes []*alertmanagertypes.RoutePolicy @@ -182,13 +182,13 @@ func (m *MockNotificationManager) DeleteRoutePolicy(ctx context.Context, orgID s } if routeID == "" { - return fmt.Errorf("routeID cannot be empty") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "routeID cannot be empty") } routeKey := getKey(orgID, routeID) route, exists := m.routes[routeKey] if !exists { - return fmt.Errorf("route with ID %s not found", routeID) + return errors.NewNotFoundf(errors.CodeNotFound, "route with ID %s not found", routeID) } delete(m.routes, routeKey) @@ -217,11 +217,11 @@ func (m *MockNotificationManager) DeleteAllRoutePoliciesByName(ctx context.Conte } if orgID == "" { - return fmt.Errorf("orgID cannot be empty") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "orgID cannot be empty") } if name == "" { - return fmt.Errorf("name cannot be empty") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "name cannot be empty") } nameKey := getKey(orgID, name) diff --git a/pkg/config/uri.go b/pkg/config/uri.go index ff1a2fb1ed..99762570ee 100644 --- a/pkg/config/uri.go +++ b/pkg/config/uri.go @@ -1,8 +1,9 @@ package config import ( - "fmt" "regexp" + + "github.com/SigNoz/signoz/pkg/errors" ) var ( @@ -20,8 +21,9 @@ func NewUri(input string) (Uri, error) { submatches := uriRegex.FindStringSubmatch(input) if len(submatches) != 3 { - return Uri{}, fmt.Errorf("invalid uri: %q", input) + return Uri{}, errors.NewInvalidInputf(errors.CodeInvalidInput, "invalid uri: %q", input) } + return Uri{ scheme: submatches[1], value: submatches[2], diff --git a/pkg/errors/code.go b/pkg/errors/code.go index 9b7e74cdd9..cbfa854f6c 100644 --- a/pkg/errors/code.go +++ b/pkg/errors/code.go @@ -1,7 +1,6 @@ package errors import ( - "fmt" "regexp" ) @@ -28,7 +27,7 @@ type Code struct{ s string } func NewCode(s string) (Code, error) { if !codeRegex.MatchString(s) { - return Code{}, fmt.Errorf("invalid code: %v", s) + return Code{}, NewInvalidInputf(CodeInvalidInput, "invalid code: %v", s) } return Code{s: s}, nil diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go index a118fd9816..d7d4bb372b 100644 --- a/pkg/errors/errors.go +++ b/pkg/errors/errors.go @@ -39,7 +39,7 @@ func (b *base) Error() string { return b.e.Error() } - return fmt.Sprintf("%s(%s): %s", b.t.s, b.c, b.m) + return b.m } // New returns a base error. It requires type, code and message as input. diff --git a/pkg/errors/errors_test.go b/pkg/errors/errors_test.go index 831f378e7b..1f04c24f08 100644 --- a/pkg/errors/errors_test.go +++ b/pkg/errors/errors_test.go @@ -17,7 +17,7 @@ func TestNewf(t *testing.T) { typ := typ{"test-error"} err := Newf(typ, MustNewCode("test_code"), "test error info with %s", "string") assert.NotNil(t, err) - assert.Equal(t, "test-error(test_code): test error info with string", err.Error()) + assert.Equal(t, "test error info with string", err.Error()) } func TestWrapf(t *testing.T) { @@ -29,10 +29,10 @@ func TestWrapf(t *testing.T) { func TestError(t *testing.T) { typ := typ{"test-error"} err1 := New(typ, MustNewCode("test_code"), "info for err1") - assert.Equal(t, "test-error(test_code): info for err1", err1.Error()) + assert.Equal(t, "info for err1", err1.Error()) err2 := Wrapf(err1, typ, MustNewCode("test_code"), "info for err2") - assert.Equal(t, "test-error(test_code): info for err1", err2.Error()) + assert.Equal(t, "info for err1", err2.Error()) } func TestUnwrapb(t *testing.T) { diff --git a/pkg/factory/name.go b/pkg/factory/name.go index 6a76f93ad5..c62f0df91a 100644 --- a/pkg/factory/name.go +++ b/pkg/factory/name.go @@ -1,9 +1,10 @@ package factory import ( - "fmt" "log/slog" "regexp" + + "github.com/SigNoz/signoz/pkg/errors" ) var _ slog.LogValuer = (Name{}) @@ -29,7 +30,7 @@ func (n Name) String() string { // NewName creates a new name. func NewName(name string) (Name, error) { if !nameRegex.MatchString(name) { - return Name{}, fmt.Errorf("invalid factory name %q", name) + return Name{}, errors.NewInvalidInputf(errors.CodeInvalidInput, "invalid factory name %q", name) } return Name{name: name}, nil } diff --git a/pkg/factory/named.go b/pkg/factory/named.go index 4a987c9246..32b4a2a2c5 100644 --- a/pkg/factory/named.go +++ b/pkg/factory/named.go @@ -1,6 +1,8 @@ package factory -import "fmt" +import ( + "github.com/SigNoz/signoz/pkg/errors" +) // Named is implemented by all types of factories. type Named interface { @@ -18,7 +20,11 @@ func NewNamedMap[T Named](factories ...T) (NamedMap[T], error) { fmap := make(map[Name]T) for _, factory := range factories { if _, ok := fmap[factory.Name()]; ok { - return NamedMap[T]{}, fmt.Errorf("cannot build factory map, duplicate name %q found", factory.Name()) + return NamedMap[T]{}, errors.NewInvalidInputf( + errors.CodeInvalidInput, + "cannot build factory map, duplicate name %q found", + factory.Name(), + ) } fmap[factory.Name()] = factory @@ -47,7 +53,11 @@ func (n *NamedMap[T]) Get(namestr string) (t T, err error) { factory, ok := n.factories[name] if !ok { - err = fmt.Errorf("factory %q not found or not registered", name) + err = errors.NewNotFoundf( + errors.CodeNotFound, + "factory %q not found or not registered", + name, + ) return } @@ -60,7 +70,12 @@ func (n *NamedMap[T]) Get(namestr string) (t T, err error) { func (n *NamedMap[T]) Add(factory T) (err error) { name := factory.Name() if _, ok := n.factories[name]; ok { - return fmt.Errorf("factory %q already exists", name) + return errors.Newf( + errors.TypeAlreadyExists, + errors.CodeAlreadyExists, + "factory %q already exists", + name, + ) } n.factories[name] = factory diff --git a/pkg/http/middleware/response.go b/pkg/http/middleware/response.go index 8d6f4d068e..8c781db165 100644 --- a/pkg/http/middleware/response.go +++ b/pkg/http/middleware/response.go @@ -2,10 +2,11 @@ package middleware import ( "bufio" - "fmt" "io" "net" "net/http" + + "github.com/SigNoz/signoz/pkg/errors" ) const ( @@ -100,7 +101,7 @@ func (writer *nonFlushingBadResponseLoggingWriter) Hijack() (net.Conn, *bufio.Re if ok { return hj.Hijack() } - return nil, nil, fmt.Errorf("cannot cast underlying response writer to Hijacker") + return nil, nil, errors.NewInternalf(errors.CodeInternal, "cannot cast underlying response writer to Hijacker") } func (writer *nonFlushingBadResponseLoggingWriter) StatusCode() int { diff --git a/pkg/http/server/server.go b/pkg/http/server/server.go index 6d1c5c71a6..0c9d19bc87 100644 --- a/pkg/http/server/server.go +++ b/pkg/http/server/server.go @@ -2,11 +2,11 @@ package server import ( "context" - "fmt" "log/slog" "net/http" "time" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" ) @@ -21,11 +21,11 @@ type Server struct { func New(logger *slog.Logger, cfg Config, handler http.Handler) (*Server, error) { if handler == nil { - return nil, fmt.Errorf("cannot build http server, handler is required") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "cannot build http server, handler is required") } if logger == nil { - return nil, fmt.Errorf("cannot build http server, logger is required") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "cannot build http server, logger is required") } srv := &http.Server{ diff --git a/pkg/instrumentation/metric.go b/pkg/instrumentation/metric.go index c52249cf15..199608c36b 100644 --- a/pkg/instrumentation/metric.go +++ b/pkg/instrumentation/metric.go @@ -40,10 +40,10 @@ func (rws readerWithServer) Shutdown(ctx context.Context) error { func prometheusReaderWithCustomRegistry(ctx context.Context, prometheusConfig *contribsdkconfig.Prometheus, customRegistry *prometheus.Registry) (sdkmetric.Reader, error) { var opts []otelprom.Option if prometheusConfig.Host == nil { - return nil, fmt.Errorf("host must be specified") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "host must be specified") } if prometheusConfig.Port == nil { - return nil, fmt.Errorf("port must be specified") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "port must be specified") } if prometheusConfig.WithoutScopeInfo != nil && *prometheusConfig.WithoutScopeInfo { opts = append(opts, otelprom.WithoutScopeInfo()) diff --git a/pkg/modules/savedview/implsavedview/module.go b/pkg/modules/savedview/implsavedview/module.go index f6fb34dbd5..3ef20ca55d 100644 --- a/pkg/modules/savedview/implsavedview/module.go +++ b/pkg/modules/savedview/implsavedview/module.go @@ -3,10 +3,10 @@ package implsavedview import ( "context" "encoding/json" - "fmt" "strings" "time" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/modules/savedview" v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3" "github.com/SigNoz/signoz/pkg/sqlstore" @@ -32,7 +32,7 @@ func (module *module) GetViewsForFilters(ctx context.Context, orgID string, sour err = module.sqlstore.BunDB().NewSelect().Model(&views).Where("org_id = ? AND source_page = ? AND category LIKE ? AND name LIKE ?", orgID, sourcePage, "%"+category+"%", "%"+name+"%").Scan(ctx) } if err != nil { - return nil, fmt.Errorf("error in getting saved views: %s", err.Error()) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "error in getting saved views") } var savedViews []*v3.SavedView @@ -40,7 +40,7 @@ func (module *module) GetViewsForFilters(ctx context.Context, orgID string, sour var compositeQuery v3.CompositeQuery err = json.Unmarshal([]byte(view.Data), &compositeQuery) if err != nil { - return nil, fmt.Errorf("error in unmarshalling explorer query data: %s", err.Error()) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "error in unmarshalling explorer query data: %s", err.Error()) } savedViews = append(savedViews, &v3.SavedView{ ID: view.ID, @@ -61,7 +61,7 @@ func (module *module) GetViewsForFilters(ctx context.Context, orgID string, sour func (module *module) CreateView(ctx context.Context, orgID string, view v3.SavedView) (valuer.UUID, error) { data, err := json.Marshal(view.CompositeQuery) if err != nil { - return valuer.UUID{}, fmt.Errorf("error in marshalling explorer query data: %s", err.Error()) + return valuer.UUID{}, errors.WrapInternalf(err, errors.CodeInternal, "error in marshalling explorer query data") } uuid := valuer.GenerateUUID() @@ -70,7 +70,7 @@ func (module *module) CreateView(ctx context.Context, orgID string, view v3.Save claims, errv2 := authtypes.ClaimsFromContext(ctx) if errv2 != nil { - return valuer.UUID{}, fmt.Errorf("error in getting email from context") + return valuer.UUID{}, errors.NewInternalf(errors.CodeInternal, "error in getting email from context") } createBy := claims.Email @@ -99,7 +99,7 @@ func (module *module) CreateView(ctx context.Context, orgID string, view v3.Save _, err = module.sqlstore.BunDB().NewInsert().Model(&dbView).Exec(ctx) if err != nil { - return valuer.UUID{}, fmt.Errorf("error in creating saved view: %s", err.Error()) + return valuer.UUID{}, errors.WrapInternalf(err, errors.CodeInternal, "error in creating saved view") } return uuid, nil } @@ -108,13 +108,13 @@ func (module *module) GetView(ctx context.Context, orgID string, uuid valuer.UUI var view types.SavedView err := module.sqlstore.BunDB().NewSelect().Model(&view).Where("org_id = ? AND id = ?", orgID, uuid.StringValue()).Scan(ctx) if err != nil { - return nil, fmt.Errorf("error in getting saved view: %s", err.Error()) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "error in getting saved view") } var compositeQuery v3.CompositeQuery err = json.Unmarshal([]byte(view.Data), &compositeQuery) if err != nil { - return nil, fmt.Errorf("error in unmarshalling explorer query data: %s", err.Error()) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "error in unmarshalling explorer query data") } return &v3.SavedView{ ID: view.ID, @@ -134,12 +134,12 @@ func (module *module) GetView(ctx context.Context, orgID string, uuid valuer.UUI func (module *module) UpdateView(ctx context.Context, orgID string, uuid valuer.UUID, view v3.SavedView) error { data, err := json.Marshal(view.CompositeQuery) if err != nil { - return fmt.Errorf("error in marshalling explorer query data: %s", err.Error()) + return errors.WrapInternalf(err, errors.CodeInternal, "error in marshalling explorer query data") } claims, errv2 := authtypes.ClaimsFromContext(ctx) if errv2 != nil { - return fmt.Errorf("error in getting email from context") + return errors.NewInternalf(errors.CodeInternal, "error in getting email from context") } updatedAt := time.Now() @@ -153,7 +153,7 @@ func (module *module) UpdateView(ctx context.Context, orgID string, uuid valuer. Where("org_id = ?", orgID). Exec(ctx) if err != nil { - return fmt.Errorf("error in updating saved view: %s", err.Error()) + return errors.WrapInternalf(err, errors.CodeInternal, "error in updating saved view") } return nil } @@ -165,7 +165,7 @@ func (module *module) DeleteView(ctx context.Context, orgID string, uuid valuer. Where("org_id = ?", orgID). Exec(ctx) if err != nil { - return fmt.Errorf("error in deleting explorer query: %s", err.Error()) + return errors.WrapInternalf(err, errors.CodeInternal, "error in deleting explorer query") } return nil } diff --git a/pkg/modules/tracefunnel/clickhouse_queries_latency_test.go b/pkg/modules/tracefunnel/clickhouse_queries_latency_test.go index 7f3b2f629c..8aa0d24bf9 100644 --- a/pkg/modules/tracefunnel/clickhouse_queries_latency_test.go +++ b/pkg/modules/tracefunnel/clickhouse_queries_latency_test.go @@ -15,9 +15,9 @@ func TestBuildFunnelOverviewQuery_WithLatencyPointer(t *testing.T) { LatencyPointer string Clause string } - startTs int64 - endTs int64 - wantContains []string + startTs int64 + endTs int64 + wantContains []string wantNotContains []string }{ { @@ -86,13 +86,13 @@ func TestBuildFunnelOverviewQuery_WithLatencyPointer(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { query := BuildFunnelOverviewQuery(tt.steps, tt.startTs, tt.endTs) - + for _, want := range tt.wantContains { if !strings.Contains(query, want) { t.Errorf("Query missing expected content: %s", want) } } - + for _, notWant := range tt.wantNotContains { if strings.Contains(query, notWant) { t.Errorf("Query contains unexpected content: %s", notWant) @@ -142,7 +142,7 @@ func TestBuildFunnelStepOverviewQuery_WithLatencyPointer(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { query := BuildFunnelStepOverviewQuery(tt.steps, 1000000000, 2000000000, tt.stepStart, tt.stepEnd) - + for _, want := range tt.wantContains { if !strings.Contains(query, want) { t.Errorf("Query missing expected content: %s", want) @@ -154,10 +154,10 @@ func TestBuildFunnelStepOverviewQuery_WithLatencyPointer(t *testing.T) { func TestBuildFunnelTopSlowTracesQuery_WithLatencyPointer(t *testing.T) { tests := []struct { - name string - latencyPointerT1 string - latencyPointerT2 string - wantContains []string + name string + latencyPointerT1 string + latencyPointerT2 string + wantContains []string }{ { name: "both steps with end latency", @@ -199,7 +199,7 @@ func TestBuildFunnelTopSlowTracesQuery_WithLatencyPointer(t *testing.T) { tt.latencyPointerT1, tt.latencyPointerT2, ) - + for _, want := range tt.wantContains { if !strings.Contains(query, want) { t.Errorf("Query missing expected content: %s", want) @@ -211,10 +211,10 @@ func TestBuildFunnelTopSlowTracesQuery_WithLatencyPointer(t *testing.T) { func TestBuildFunnelTopSlowErrorTracesQuery_WithLatencyPointer(t *testing.T) { tests := []struct { - name string - latencyPointerT1 string - latencyPointerT2 string - wantContains []string + name string + latencyPointerT1 string + latencyPointerT2 string + wantContains []string }{ { name: "both steps with end latency", @@ -247,7 +247,7 @@ func TestBuildFunnelTopSlowErrorTracesQuery_WithLatencyPointer(t *testing.T) { tt.latencyPointerT1, tt.latencyPointerT2, ) - + for _, want := range tt.wantContains { if !strings.Contains(query, want) { t.Errorf("Query missing expected content: %s", want) @@ -255,4 +255,4 @@ func TestBuildFunnelTopSlowErrorTracesQuery_WithLatencyPointer(t *testing.T) { } }) } -} \ No newline at end of file +} diff --git a/pkg/modules/tracefunnel/clickhouse_queries_test.go b/pkg/modules/tracefunnel/clickhouse_queries_test.go index 1726735904..b2273a1c0d 100644 --- a/pkg/modules/tracefunnel/clickhouse_queries_test.go +++ b/pkg/modules/tracefunnel/clickhouse_queries_test.go @@ -7,8 +7,8 @@ import ( func TestBuildFunnelValidationQuery(t *testing.T) { tests := []struct { - name string - steps []struct { + name string + steps []struct { ServiceName string SpanName string ContainsError int @@ -90,7 +90,7 @@ func TestBuildFunnelValidationQuery(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := BuildFunnelValidationQuery(tt.steps, tt.startTs, tt.endTs) - + for _, want := range tt.wantContains { if !strings.Contains(got, want) { t.Errorf("BuildFunnelValidationQuery() missing expected string: %q", want) @@ -103,8 +103,8 @@ func TestBuildFunnelValidationQuery(t *testing.T) { func TestBuildFunnelOverviewQuery(t *testing.T) { tests := []struct { - name string - steps []struct { + name string + steps []struct { ServiceName string SpanName string ContainsError int @@ -168,7 +168,7 @@ func TestBuildFunnelOverviewQuery(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := BuildFunnelOverviewQuery(tt.steps, tt.startTs, tt.endTs) - + for _, want := range tt.wantContains { if !strings.Contains(got, want) { t.Errorf("BuildFunnelOverviewQuery() missing expected string: %q", want) @@ -181,8 +181,8 @@ func TestBuildFunnelOverviewQuery(t *testing.T) { func TestBuildFunnelCountQuery(t *testing.T) { tests := []struct { - name string - steps []struct { + name string + steps []struct { ServiceName string SpanName string ContainsError int @@ -241,7 +241,7 @@ func TestBuildFunnelCountQuery(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := BuildFunnelCountQuery(tt.steps, tt.startTs, tt.endTs) - + for _, want := range tt.wantContains { if !strings.Contains(got, want) { t.Errorf("BuildFunnelCountQuery() missing expected string: %q", want) @@ -254,8 +254,8 @@ func TestBuildFunnelCountQuery(t *testing.T) { func TestBuildFunnelStepOverviewQuery(t *testing.T) { tests := []struct { - name string - steps []struct { + name string + steps []struct { ServiceName string SpanName string ContainsError int @@ -347,14 +347,14 @@ func TestBuildFunnelStepOverviewQuery(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := BuildFunnelStepOverviewQuery(tt.steps, tt.startTs, tt.endTs, tt.stepStart, tt.stepEnd) - + for _, want := range tt.wantContains { if !strings.Contains(got, want) { t.Errorf("BuildFunnelStepOverviewQuery() missing expected string: %q", want) t.Logf("Got query:\n%s", got) } } - + if tt.wantFallback && !strings.Contains(got, "SELECT 0 AS conversion_rate") { t.Errorf("BuildFunnelStepOverviewQuery() expected fallback query for invalid step range") } @@ -376,17 +376,17 @@ func TestTemporalOrderingLogic(t *testing.T) { {ServiceName: "s3", SpanName: "sp3", ContainsError: 0, LatencyPointer: "start", Clause: ""}, {ServiceName: "s4", SpanName: "sp4", ContainsError: 0, LatencyPointer: "start", Clause: ""}, }, 1000000000, 2000000000) - + // Check that each step has proper temporal ordering (cumulative format) temporalChecks := []string{ "t2_time > t1_time", "t2_time > t1_time AND t3_time > t2_time", "t2_time > t1_time AND t3_time > t2_time AND t4_time > t3_time", } - + for _, check := range temporalChecks { if !strings.Contains(query, check) { t.Errorf("Missing temporal ordering check: %s", check) } } -} \ No newline at end of file +} diff --git a/pkg/modules/tracefunnel/impltracefunnel/module.go b/pkg/modules/tracefunnel/impltracefunnel/module.go index 21232ae855..dfb3bd4b6d 100644 --- a/pkg/modules/tracefunnel/impltracefunnel/module.go +++ b/pkg/modules/tracefunnel/impltracefunnel/module.go @@ -2,9 +2,9 @@ package impltracefunnel import ( "context" - "fmt" "time" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/modules/tracefunnel" "github.com/SigNoz/signoz/pkg/types" traceFunnels "github.com/SigNoz/signoz/pkg/types/tracefunneltypes" @@ -76,7 +76,7 @@ func (module *module) Update(ctx context.Context, funnel *traceFunnels.StorableF func (module *module) List(ctx context.Context, orgID valuer.UUID) ([]*traceFunnels.StorableFunnel, error) { funnels, err := module.store.List(ctx, orgID) if err != nil { - return nil, fmt.Errorf("failed to list funnels: %v", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "failed to list funnels") } return funnels, nil diff --git a/pkg/modules/tracefunnel/impltracefunnel/store.go b/pkg/modules/tracefunnel/impltracefunnel/store.go index 0bb48e788e..4d0ec8818a 100644 --- a/pkg/modules/tracefunnel/impltracefunnel/store.go +++ b/pkg/modules/tracefunnel/impltracefunnel/store.go @@ -110,12 +110,12 @@ func (store *store) Update(ctx context.Context, funnel *traceFunnels.StorableFun if err != nil { return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to update funnel") } - + err = tx.Commit() if err != nil { return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to commit transaction") } - + return nil } diff --git a/pkg/modules/tracefunnel/impltracefunnel/store_duplicate_names_test.go b/pkg/modules/tracefunnel/impltracefunnel/store_duplicate_names_test.go index 6be8c47a0f..fe82a01118 100644 --- a/pkg/modules/tracefunnel/impltracefunnel/store_duplicate_names_test.go +++ b/pkg/modules/tracefunnel/impltracefunnel/store_duplicate_names_test.go @@ -46,7 +46,7 @@ func TestModule_Update_DuplicateNameValidation(t *testing.T) { userID := valuer.GenerateUUID() orgID := valuer.GenerateUUID() funnelName := "Duplicate Name" - + funnel := &traceFunnels.StorableFunnel{ Name: funnelName, OrgID: orgID, @@ -93,4 +93,4 @@ func (m *MockStore) Update(ctx context.Context, funnel *traceFunnels.StorableFun func (m *MockStore) Delete(ctx context.Context, uuid valuer.UUID, orgID valuer.UUID) error { args := m.Called(ctx, uuid, orgID) return args.Error(0) -} \ No newline at end of file +} diff --git a/pkg/modules/tracefunnel/query.go b/pkg/modules/tracefunnel/query.go index 17fd81b576..3ced1bc205 100644 --- a/pkg/modules/tracefunnel/query.go +++ b/pkg/modules/tracefunnel/query.go @@ -1,9 +1,9 @@ package tracefunnel import ( - "fmt" "strings" + "github.com/SigNoz/signoz/pkg/errors" tracev4 "github.com/SigNoz/signoz/pkg/query-service/app/traces/v4" v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3" "github.com/SigNoz/signoz/pkg/types/tracefunneltypes" @@ -113,7 +113,7 @@ func GetFunnelAnalytics(funnel *tracefunneltypes.StorableFunnel, timeRange trace func GetFunnelStepAnalytics(funnel *tracefunneltypes.StorableFunnel, timeRange tracefunneltypes.TimeRange, stepStart, stepEnd int64) (*v3.ClickHouseQuery, error) { if stepStart == stepEnd { - return nil, fmt.Errorf("step start and end cannot be the same for /step/overview") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "step start and end cannot be the same for /step/overview") } funnelSteps := funnel.Steps diff --git a/pkg/modules/tracefunnel/query_test.go b/pkg/modules/tracefunnel/query_test.go index c9a44f72f4..369b2e46ca 100644 --- a/pkg/modules/tracefunnel/query_test.go +++ b/pkg/modules/tracefunnel/query_test.go @@ -74,7 +74,7 @@ func TestValidateTracesMultipleSteps(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := ValidateTraces(tt.funnel, tt.timeRange) - + if tt.expectError && err == nil { t.Errorf("ValidateTraces() expected error but got none") } @@ -150,7 +150,7 @@ func TestGetFunnelAnalyticsMultipleSteps(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := GetFunnelAnalytics(tt.funnel, tt.timeRange) - + if tt.expectError && err == nil { t.Errorf("GetFunnelAnalytics() expected error but got none") } @@ -177,14 +177,14 @@ func TestGetStepAnalyticsMultipleSteps(t *testing.T) { {ServiceName: "s5", SpanName: "sp5", HasErrors: true, Filters: &v3.FilterSet{}}, }, } - + timeRange := tracefunneltypes.TimeRange{ StartTime: 1000000000, EndTime: 2000000000, } result, err := GetStepAnalytics(funnel, timeRange) - + if err != nil { t.Errorf("GetStepAnalytics() unexpected error: %v", err) } @@ -246,7 +246,7 @@ func TestGetFunnelStepAnalyticsMultipleSteps(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := GetFunnelStepAnalytics(tt.funnel, tt.timeRange, tt.stepStart, tt.stepEnd) - + if tt.expectError && err == nil { t.Errorf("GetFunnelStepAnalytics() expected error but got none") } @@ -268,4 +268,4 @@ func init() { // This would normally be handled by the actual implementation // For testing purposes, we'll assume it returns an empty string _ = tracev4.BuildTracesFilterQuery -} \ No newline at end of file +} diff --git a/pkg/prometheus/clickhouseprometheus/client.go b/pkg/prometheus/clickhouseprometheus/client.go index d8387898a5..4cc10d3a4c 100644 --- a/pkg/prometheus/clickhouseprometheus/client.go +++ b/pkg/prometheus/clickhouseprometheus/client.go @@ -3,12 +3,13 @@ package clickhouseprometheus import ( "context" "fmt" - "github.com/SigNoz/signoz/pkg/query-service/constants" "math" "strconv" "strings" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" + "github.com/SigNoz/signoz/pkg/query-service/constants" "github.com/SigNoz/signoz/pkg/telemetrystore" promValue "github.com/prometheus/prometheus/model/value" "github.com/prometheus/prometheus/prompb" @@ -122,7 +123,7 @@ func (client *client) queryToClickhouseQuery(_ context.Context, query *prompb.Qu case prompb.LabelMatcher_NRE: conditions = append(conditions, fmt.Sprintf("not match(JSONExtractString(labels, $%d), $%d)", argCount+2, argCount+3)) default: - return "", nil, fmt.Errorf("unexpected matcher found in query: %s", m.Type.String()) + return "", nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported or invalid matcher type: %s", m.Type.String()) } args = append(args, m.Name, m.Value) argCount += 2 diff --git a/pkg/prometheus/utils.go b/pkg/prometheus/utils.go index 8f29c4ae14..9ce8d75453 100644 --- a/pkg/prometheus/utils.go +++ b/pkg/prometheus/utils.go @@ -1,7 +1,7 @@ package prometheus import ( - "fmt" + "github.com/SigNoz/signoz/pkg/errors" "github.com/prometheus/prometheus/promql" ) @@ -43,7 +43,7 @@ func RemoveExtraLabels(res *promql.Result, labelsToRemove ...string) error { case promql.Scalar: return nil default: - return fmt.Errorf("rule result is not a vector or scalar or matrix") + return errors.NewInternalf(errors.CodeInternal, "rule result is not a vector or scalar or matrix") } return nil } diff --git a/pkg/querier/postprocess.go b/pkg/querier/postprocess.go index 21763a242a..a3a65112af 100644 --- a/pkg/querier/postprocess.go +++ b/pkg/querier/postprocess.go @@ -237,7 +237,6 @@ func postProcessTraceOperator( return result } - // applyMetricReduceTo applies reduce to operation using the metric's ReduceTo field func (q *querier) applyMetricReduceTo(result *qbtypes.Result, reduceOp qbtypes.ReduceTo) *qbtypes.Result { tsData, ok := result.Value.(*qbtypes.TimeSeriesData) diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index f0ae4abb08..66b2f279c5 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -140,7 +140,7 @@ func (q *querier) QueryRange(ctx context.Context, orgID valuer.UUID, req *qbtype if spec, ok := query.Spec.(qbtypes.QueryBuilderTraceOperator); ok { // Parse expression to find dependencies if err := spec.ParseExpression(); err != nil { - return nil, fmt.Errorf("failed to parse trace operator expression: %w", err) + return nil, err } deps := spec.CollectReferencedQueries(spec.ParsedExpression) @@ -652,7 +652,7 @@ func (q *querier) executeWithCache(ctx context.Context, orgID valuer.UUID, query // Execute queries for missing ranges with bounded parallelism freshResults := make([]*qbtypes.Result, len(missingRanges)) - errors := make([]error, len(missingRanges)) + errs := make([]error, len(missingRanges)) totalStats := qbtypes.ExecStats{} q.logger.DebugContext(ctx, "executing queries for missing ranges", @@ -673,14 +673,14 @@ func (q *querier) executeWithCache(ctx context.Context, orgID valuer.UUID, query // Create a new query with the missing time range rangedQuery := q.createRangedQuery(query, *tr) if rangedQuery == nil { - errors[idx] = fmt.Errorf("failed to create ranged query for range %d-%d", tr.From, tr.To) + errs[idx] = errors.NewInternalf(errors.CodeInternal, "failed to create ranged query for range %d-%d", tr.From, tr.To) return } // Execute the ranged query result, err := rangedQuery.Execute(ctx) if err != nil { - errors[idx] = err + errs[idx] = err return } @@ -692,7 +692,7 @@ func (q *querier) executeWithCache(ctx context.Context, orgID valuer.UUID, query wg.Wait() // Check for errors - for _, err := range errors { + for _, err := range errs { if err != nil { // If any query failed, fall back to full execution q.logger.ErrorContext(ctx, "parallel query execution failed", "error", err) diff --git a/pkg/querier/trace_operator_query.go b/pkg/querier/trace_operator_query.go index 762b34691b..e776f22cb0 100644 --- a/pkg/querier/trace_operator_query.go +++ b/pkg/querier/trace_operator_query.go @@ -87,4 +87,3 @@ func (q *traceOperatorQuery) executeWithContext(ctx context.Context, query strin }, }, nil } - diff --git a/pkg/querybuilder/never_true.go b/pkg/querybuilder/never_true.go index 24def0a80c..b818fad420 100644 --- a/pkg/querybuilder/never_true.go +++ b/pkg/querybuilder/never_true.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" + "github.com/SigNoz/signoz/pkg/errors" grammar "github.com/SigNoz/signoz/pkg/parser/grammar" qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5" "github.com/antlr4-go/antlr/v4" @@ -54,7 +55,7 @@ func DetectContradictions(query string) ([]string, error) { // Check for syntax errors if len(parserErrorListener.SyntaxErrors) > 0 { - return nil, fmt.Errorf("syntax errors: %v", parserErrorListener.SyntaxErrors) + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "syntax errors: %v", parserErrorListener.SyntaxErrors) } // Create detector and visit tree @@ -856,7 +857,7 @@ func parseNumericValue(value interface{}) (float64, error) { case string: return strconv.ParseFloat(v, 64) default: - return 0, fmt.Errorf("not a numeric value") + return 0, errors.NewInvalidInputf(errors.CodeInvalidInput, "not a numeric value") } } diff --git a/pkg/querybuilder/resourcefilter/statement_builder.go b/pkg/querybuilder/resourcefilter/statement_builder.go index 315d227b27..880f14f54e 100644 --- a/pkg/querybuilder/resourcefilter/statement_builder.go +++ b/pkg/querybuilder/resourcefilter/statement_builder.go @@ -119,7 +119,7 @@ func (b *resourceFilterStatementBuilder[T]) Build( ) (*qbtypes.Statement, error) { config, exists := signalConfigs[b.signal] if !exists { - return nil, fmt.Errorf("%w: %s", ErrUnsupportedSignal, b.signal) + return nil, errors.WrapInvalidInputf(ErrUnsupportedSignal, errors.CodeInvalidInput, "unsupported signal: %s", b.signal) } q := sqlbuilder.NewSelectBuilder() diff --git a/pkg/signoz/config.go b/pkg/signoz/config.go index 2b4222eafe..22c08c81e3 100644 --- a/pkg/signoz/config.go +++ b/pkg/signoz/config.go @@ -2,7 +2,6 @@ package signoz import ( "context" - "fmt" "log/slog" "net/url" "os" @@ -16,6 +15,7 @@ import ( "github.com/SigNoz/signoz/pkg/cache" "github.com/SigNoz/signoz/pkg/config" "github.com/SigNoz/signoz/pkg/emailing" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" "github.com/SigNoz/signoz/pkg/gateway" "github.com/SigNoz/signoz/pkg/instrumentation" @@ -182,11 +182,11 @@ func validateConfig(config Config) error { for i := 0; i < rvConfig.NumField(); i++ { factoryConfig, ok := rvConfig.Field(i).Interface().(factory.Config) if !ok { - return fmt.Errorf("%q is not of type \"factory.Config\"", rvConfig.Type().Field(i).Name) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "%q is not of type \"factory.Config\"", rvConfig.Type().Field(i).Name) } if err := factoryConfig.Validate(); err != nil { - return fmt.Errorf("failed to validate config %q: %w", rvConfig.Type().Field(i).Tag.Get("mapstructure"), err) + return errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to validate config %q", rvConfig.Type().Field(i).Tag.Get("mapstructure")) } } diff --git a/pkg/smtp/client/smtp.go b/pkg/smtp/client/smtp.go index a97b5bb7c2..faff35e623 100644 --- a/pkg/smtp/client/smtp.go +++ b/pkg/smtp/client/smtp.go @@ -117,7 +117,7 @@ func (c *Client) Do(ctx context.Context, tos []*mail.Address, subject string, co if c.hello != "" { err = smtpClient.Hello(c.hello) if err != nil { - return fmt.Errorf("failed to send EHLO command: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to send EHLO command") } } @@ -125,7 +125,7 @@ func (c *Client) Do(ctx context.Context, tos []*mail.Address, subject string, co if !c.tls.Enabled { if ok, _ := smtpClient.Extension("STARTTLS"); ok { if err := smtpClient.StartTLS(c.tlsConfig); err != nil { - return fmt.Errorf("failed to send STARTTLS command: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to send STARTTLS command") } } } @@ -136,32 +136,32 @@ func (c *Client) Do(ctx context.Context, tos []*mail.Address, subject string, co if c.auth.Username != "" { auth, err := c.smtpAuth(ctx, mech) if err != nil { - return fmt.Errorf("failed to find auth mechanism: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to find auth mechanism") } // Send the AUTH command. if err := smtpClient.Auth(auth); err != nil { - return fmt.Errorf("failed to auth: %T: %w", auth, err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to auth: %T", auth) } } } // Send the MAIL command. if err = smtpClient.Mail(c.from.Address); err != nil { - return fmt.Errorf("failed to send MAIL command: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to send MAIL command") } // Send the RCPT command for each recipient. for _, addr := range tos { if err = smtpClient.Rcpt(addr.Address); err != nil { - return fmt.Errorf("failed to send RCPT command: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to send RCPT command") } } // Send the email headers and body. message, err := smtpClient.Data() if err != nil { - return fmt.Errorf("failed to send DATA command: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to send DATA command") } closeOnce := sync.OnceValue(func() error { @@ -200,7 +200,7 @@ func (c *Client) Do(ctx context.Context, tos []*mail.Address, subject string, co _, err = message.Write(buffer.Bytes()) if err != nil { - return fmt.Errorf("failed to write headers: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to write headers") } // Text template @@ -210,17 +210,17 @@ func (c *Client) Do(ctx context.Context, tos []*mail.Address, subject string, co "Content-Type": {"text/plain; charset=UTF-8"}, }) if err != nil { - return fmt.Errorf("failed to create part for text template: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to create part for text template") } qw := quotedprintable.NewWriter(w) _, err = qw.Write([]byte(body)) if err != nil { - return fmt.Errorf("failed to write text part: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to write text part") } err = qw.Close() if err != nil { - return fmt.Errorf("failed to close text part: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to close text part") } } @@ -233,33 +233,33 @@ func (c *Client) Do(ctx context.Context, tos []*mail.Address, subject string, co "Content-Type": {"text/html; charset=UTF-8"}, }) if err != nil { - return fmt.Errorf("failed to create part for html template: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to create part for html template") } qw := quotedprintable.NewWriter(w) _, err = qw.Write([]byte(body)) if err != nil { - return fmt.Errorf("failed to write HTML part: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to write HTML part") } err = qw.Close() if err != nil { - return fmt.Errorf("failed to close HTML part: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to close HTML part") } } err = multipartWriter.Close() if err != nil { - return fmt.Errorf("failed to close multipartWriter: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to close multipartWriter") } _, err = message.Write(multipartBuffer.Bytes()) if err != nil { - return fmt.Errorf("failed to write body buffer: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to write body buffer") } // Complete the message and await response. if err = closeOnce(); err != nil { - return fmt.Errorf("failed to deliver: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "failed to deliver") } success = true @@ -317,7 +317,7 @@ func (c *Client) dial(ctx context.Context) (net.Conn, error) { if c.tls.Enabled || c.port == "465" { conn, err = tls.Dial("tcp", c.address, c.tlsConfig) if err != nil { - return nil, fmt.Errorf("failed to establish TLS connection to server: %w", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "failed to establish TLS connection to server") } return conn, nil @@ -326,7 +326,7 @@ func (c *Client) dial(ctx context.Context) (net.Conn, error) { var d net.Dialer conn, err = d.DialContext(ctx, "tcp", c.address) if err != nil { - return nil, fmt.Errorf("failed to establish connection to server: %w", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "failed to establish connection to server") } return conn, nil @@ -341,7 +341,7 @@ func newTLSConfig(config TLS, serverName string) (*tls.Config, error) { if config.CertFilePath != "" { cert, err := tls.LoadX509KeyPair(config.CertFilePath, config.KeyFilePath) if err != nil { - return nil, fmt.Errorf("failed to load cert or key file: %w", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "failed to load cert or key file") } tlsConfig.Certificates = []tls.Certificate{cert} } @@ -349,11 +349,11 @@ func newTLSConfig(config TLS, serverName string) (*tls.Config, error) { if config.CAFilePath != "" { ca, err := os.ReadFile(config.CAFilePath) if err != nil { - return nil, fmt.Errorf("failed to load CA file: %w", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "failed to load CA file") } tlsConfig.RootCAs = x509.NewCertPool() if !tlsConfig.RootCAs.AppendCertsFromPEM(ca) { - return nil, fmt.Errorf("failed to append CA file: %s", config.CAFilePath) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "failed to append CA file: %s", config.CAFilePath) } } diff --git a/pkg/sqlschema/sqlitesqlschema/ddl.go b/pkg/sqlschema/sqlitesqlschema/ddl.go index d07864797a..fb5792064c 100644 --- a/pkg/sqlschema/sqlitesqlschema/ddl.go +++ b/pkg/sqlschema/sqlitesqlschema/ddl.go @@ -251,7 +251,7 @@ func parseAllColumns(in string) ([]sqlschema.ColumnName, error) { quote = ']' continue } else if s[i] == ')' { - return columns, fmt.Errorf("unexpected token: %s", string(s[i])) + return columns, errors.NewInternalf(ErrCodeInvalidDDL, "unexpected token: %s", string(s[i])) } state = parseAllColumnsState_ReadingRawName name = append(name, s[i]) @@ -267,7 +267,7 @@ func parseAllColumns(in string) ([]sqlschema.ColumnName, error) { columns = append(columns, sqlschema.ColumnName(name)) } if isQuote(s[i]) { - return nil, fmt.Errorf("unexpected token: %s", string(s[i])) + return nil, errors.NewInternalf(ErrCodeInvalidDDL, "unexpected token: %s", string(s[i])) } if isSpace(s[i]) { state = parseAllColumnsState_EndOfName diff --git a/pkg/sqlstore/sqlstoretest/provider.go b/pkg/sqlstore/sqlstoretest/provider.go index a04624a52b..b008471506 100644 --- a/pkg/sqlstore/sqlstoretest/provider.go +++ b/pkg/sqlstore/sqlstoretest/provider.go @@ -3,7 +3,6 @@ package sqlstoretest import ( "context" "database/sql" - "fmt" "github.com/DATA-DOG/go-sqlmock" "github.com/SigNoz/signoz/pkg/errors" @@ -35,7 +34,7 @@ func New(config sqlstore.Config, matcher sqlmock.QueryMatcher) *Provider { } else if config.Provider == "postgres" { bunDB = bun.NewDB(db, pgdialect.New()) } else { - panic(fmt.Errorf("provider %q is not supported", config.Provider)) + panic(errors.NewInvalidInputf(errors.CodeInvalidInput, "provider %q is not supported", config.Provider)) } return &Provider{ @@ -71,9 +70,9 @@ func (provider *Provider) RunInTxCtx(ctx context.Context, opts *sql.TxOptions, c } func (provider *Provider) WrapNotFoundErrf(err error, code errors.Code, format string, args ...any) error { - return fmt.Errorf(format, args...) + return errors.WrapNotFoundf(err, code, format, args...) } func (provider *Provider) WrapAlreadyExistsErrf(err error, code errors.Code, format string, args ...any) error { - return fmt.Errorf(format, args...) + return errors.Wrapf(err, errors.TypeAlreadyExists, code, format, args...) } diff --git a/pkg/telemetrylogs/condition_builder.go b/pkg/telemetrylogs/condition_builder.go index a5af55f932..30027da4db 100644 --- a/pkg/telemetrylogs/condition_builder.go +++ b/pkg/telemetrylogs/condition_builder.go @@ -7,6 +7,7 @@ import ( "strings" schema "github.com/SigNoz/signoz-otel-collector/cmd/signozschemamigrator/schema_migrator" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/querybuilder" qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5" "github.com/SigNoz/signoz/pkg/types/telemetrytypes" @@ -205,10 +206,10 @@ func (c *conditionBuilder) conditionFor( return sb.NE(leftOperand, true), nil } default: - return "", fmt.Errorf("exists operator is not supported for column type %s", column.Type) + return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "exists operator is not supported for column type %s", column.Type) } } - return "", fmt.Errorf("unsupported operator: %v", operator) + return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported operator: %v", operator) } func (c *conditionBuilder) ConditionFor( diff --git a/pkg/telemetrylogs/statement_builder.go b/pkg/telemetrylogs/statement_builder.go index 491e25ee64..e8df04a3ea 100644 --- a/pkg/telemetrylogs/statement_builder.go +++ b/pkg/telemetrylogs/statement_builder.go @@ -6,6 +6,7 @@ import ( "log/slog" "strings" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" "github.com/SigNoz/signoz/pkg/querybuilder" qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5" @@ -87,7 +88,7 @@ func (b *logQueryStatementBuilder) Build( return b.buildScalarQuery(ctx, q, query, start, end, keys, false, variables) } - return nil, fmt.Errorf("unsupported request type: %s", requestType) + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported request type: %s", requestType) } func getKeySelectors(query qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]) []*telemetrytypes.FieldKeySelector { diff --git a/pkg/telemetrymetadata/metadata_test.go b/pkg/telemetrymetadata/metadata_test.go index a63fc0991a..d9850da199 100644 --- a/pkg/telemetrymetadata/metadata_test.go +++ b/pkg/telemetrymetadata/metadata_test.go @@ -2,10 +2,10 @@ package telemetrymetadata import ( "context" - "fmt" "regexp" "testing" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest" "github.com/SigNoz/signoz/pkg/telemetrylogs" "github.com/SigNoz/signoz/pkg/telemetrymeter" @@ -28,7 +28,7 @@ func (m *regexMatcher) Match(expectedSQL, actualSQL string) error { return err } if !re.MatchString(actualSQL) { - return fmt.Errorf("expected query to contain %s, got %s", expectedSQL, actualSQL) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "expected query to contain %s, got %s", expectedSQL, actualSQL) } return nil } diff --git a/pkg/telemetrytraces/condition_builder.go b/pkg/telemetrytraces/condition_builder.go index cec1e63e97..f23ac9158e 100644 --- a/pkg/telemetrytraces/condition_builder.go +++ b/pkg/telemetrytraces/condition_builder.go @@ -211,7 +211,7 @@ func (c *conditionBuilder) conditionFor( return sb.NE(leftOperand, true), nil } default: - return "", fmt.Errorf("exists operator is not supported for column type %s", column.Type) + return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "exists operator is not supported for column type %s", column.Type) } } return "", nil diff --git a/pkg/telemetrytraces/statement_builder.go b/pkg/telemetrytraces/statement_builder.go index 539726e87b..879d53a0ee 100644 --- a/pkg/telemetrytraces/statement_builder.go +++ b/pkg/telemetrytraces/statement_builder.go @@ -82,9 +82,9 @@ func (b *traceQueryStatementBuilder) Build( if found && len(traceIDs) > 0 { finder := NewTraceTimeRangeFinder(b.telemetryStore) - traceStart, traceEnd, err := finder.GetTraceTimeRangeMulti(ctx, traceIDs) - if err != nil { - b.logger.DebugContext(ctx, "failed to get trace time range", "trace_ids", traceIDs, "error", err) + traceStart, traceEnd, ok := finder.GetTraceTimeRangeMulti(ctx, traceIDs) + if !ok { + b.logger.DebugContext(ctx, "failed to get trace time range", "trace_ids", traceIDs) } else if traceStart > 0 && traceEnd > 0 { start = uint64(traceStart) end = uint64(traceEnd) @@ -107,7 +107,7 @@ func (b *traceQueryStatementBuilder) Build( return b.buildTraceQuery(ctx, q, query, start, end, keys, variables) } - return nil, fmt.Errorf("unsupported request type: %s", requestType) + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported request type: %s", requestType) } func getKeySelectors(query qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]) []*telemetrytypes.FieldKeySelector { diff --git a/pkg/telemetrytraces/trace_operator_cte_builder.go b/pkg/telemetrytraces/trace_operator_cte_builder.go index a5cb9471d8..f2a27765bb 100644 --- a/pkg/telemetrytraces/trace_operator_cte_builder.go +++ b/pkg/telemetrytraces/trace_operator_cte_builder.go @@ -3,12 +3,13 @@ package telemetrytraces import ( "context" "fmt" + "strings" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/querybuilder" qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5" "github.com/SigNoz/signoz/pkg/types/telemetrytypes" "github.com/huandu/go-sqlbuilder" - "strings" ) type cteNode struct { @@ -402,7 +403,7 @@ func (b *traceOperatorCTEBuilder) buildFinalQuery(ctx context.Context, selectFro case qbtypes.RequestTypeScalar: return b.buildScalarQuery(ctx, selectFromCTE) default: - return nil, fmt.Errorf("unsupported request type: %s", requestType) + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported request type: %s", requestType) } } diff --git a/pkg/telemetrytraces/trace_time_range.go b/pkg/telemetrytraces/trace_time_range.go index 07799cb388..7dfc36404c 100644 --- a/pkg/telemetrytraces/trace_time_range.go +++ b/pkg/telemetrytraces/trace_time_range.go @@ -2,7 +2,6 @@ package telemetrytraces import ( "context" - "database/sql" "fmt" "strings" @@ -19,14 +18,14 @@ func NewTraceTimeRangeFinder(telemetryStore telemetrystore.TelemetryStore) *Trac } } -func (f *TraceTimeRangeFinder) GetTraceTimeRange(ctx context.Context, traceID string) (startNano, endNano int64, err error) { +func (f *TraceTimeRangeFinder) GetTraceTimeRange(ctx context.Context, traceID string) (startNano, endNano int64, ok bool) { traceIDs := []string{traceID} return f.GetTraceTimeRangeMulti(ctx, traceIDs) } -func (f *TraceTimeRangeFinder) GetTraceTimeRangeMulti(ctx context.Context, traceIDs []string) (startNano, endNano int64, err error) { +func (f *TraceTimeRangeFinder) GetTraceTimeRangeMulti(ctx context.Context, traceIDs []string) (startNano, endNano int64, ok bool) { if len(traceIDs) == 0 { - return 0, 0, fmt.Errorf("no trace IDs provided") + return 0, 0, false } cleanedIDs := make([]string, len(traceIDs)) @@ -51,12 +50,9 @@ func (f *TraceTimeRangeFinder) GetTraceTimeRangeMulti(ctx context.Context, trace row := f.telemetryStore.ClickhouseDB().QueryRow(ctx, query, args...) - err = row.Scan(&startNano, &endNano) + err := row.Scan(&startNano, &endNano) if err != nil { - if err == sql.ErrNoRows { - return 0, 0, fmt.Errorf("traces not found: %v", cleanedIDs) - } - return 0, 0, fmt.Errorf("failed to query trace time range: %w", err) + return 0, 0, false } if startNano > 1_000_000_000 { @@ -64,5 +60,5 @@ func (f *TraceTimeRangeFinder) GetTraceTimeRangeMulti(ctx context.Context, trace } endNano += 1_000_000_000 - return startNano, endNano, nil + return startNano, endNano, true } diff --git a/pkg/telemetrytraces/trace_time_range_multi_test.go b/pkg/telemetrytraces/trace_time_range_multi_test.go index a7cdf9f28c..262c2f5977 100644 --- a/pkg/telemetrytraces/trace_time_range_multi_test.go +++ b/pkg/telemetrytraces/trace_time_range_multi_test.go @@ -12,29 +12,29 @@ func TestGetTraceTimeRangeMulti(t *testing.T) { ctx := context.Background() tests := []struct { - name string - traceIDs []string - expectErr bool + name string + traceIDs []string + expectOK bool }{ { - name: "single trace ID", - traceIDs: []string{"trace1"}, - expectErr: false, + name: "single trace ID", + traceIDs: []string{"trace1"}, + expectOK: true, }, { - name: "multiple trace IDs", - traceIDs: []string{"trace1", "trace2", "trace3"}, - expectErr: false, + name: "multiple trace IDs", + traceIDs: []string{"trace1", "trace2", "trace3"}, + expectOK: true, }, { - name: "empty trace IDs", - traceIDs: []string{}, - expectErr: true, + name: "empty trace IDs", + traceIDs: []string{}, + expectOK: false, }, { - name: "trace IDs with quotes", - traceIDs: []string{"'trace1'", `"trace2"`, "trace3"}, - expectErr: false, + name: "trace IDs with quotes", + traceIDs: []string{"'trace1'", `"trace2"`, "trace3"}, + expectOK: true, }, } @@ -42,9 +42,9 @@ func TestGetTraceTimeRangeMulti(t *testing.T) { t.Run(tt.name, func(t *testing.T) { finder := &TraceTimeRangeFinder{telemetryStore: nil} - if tt.expectErr { - _, _, err := finder.GetTraceTimeRangeMulti(ctx, tt.traceIDs) - assert.Error(t, err) + if !tt.expectOK { + _, _, ok := finder.GetTraceTimeRangeMulti(ctx, tt.traceIDs) + assert.False(t, ok) } }) } diff --git a/pkg/types/alertmanagertypes/template.go b/pkg/types/alertmanagertypes/template.go index 8767eb7bd8..673a902b2d 100644 --- a/pkg/types/alertmanagertypes/template.go +++ b/pkg/types/alertmanagertypes/template.go @@ -2,8 +2,8 @@ package alertmanagertypes import ( "bytes" - "fmt" + "github.com/SigNoz/signoz/pkg/errors" alertmanagertemplate "github.com/prometheus/alertmanager/template" ) @@ -23,7 +23,7 @@ func FromGlobs(paths []string) (*alertmanagertemplate.Template, error) { {{ define "__alertmanagerURL" }}{{ .ExternalURL }}/alerts{{ template "__ruleIdPath" . }}{{ end }} {{ define "msteamsv2.default.titleLink" }}{{ template "__alertmanagerURL" . }}{{ end }} `))); err != nil { - return nil, fmt.Errorf("error parsing alertmanager templates: %w", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "error parsing alertmanager templates") } return t, nil diff --git a/pkg/types/integration.go b/pkg/types/integration.go index 43d29c4b56..0d29fc91d3 100644 --- a/pkg/types/integration.go +++ b/pkg/types/integration.go @@ -3,10 +3,9 @@ package types import ( "database/sql/driver" "encoding/json" - "fmt" "time" - "github.com/pkg/errors" + "github.com/SigNoz/signoz/pkg/errors" "github.com/uptrace/bun" ) @@ -45,7 +44,7 @@ func (c *InstalledIntegrationConfig) Scan(src interface{}) error { case string: data = []byte(v) default: - return fmt.Errorf("tried to scan from %T instead of string or bytes", src) + return errors.NewInternalf(errors.CodeInternal, "tried to scan from %T instead of string or bytes", src) } return json.Unmarshal(data, c) @@ -55,7 +54,7 @@ func (c *InstalledIntegrationConfig) Scan(src interface{}) error { func (c *InstalledIntegrationConfig) Value() (driver.Value, error) { filterSetJson, err := json.Marshal(c) if err != nil { - return nil, errors.Wrap(err, "could not serialize integration config to JSON") + return nil, errors.WrapInternalf(err, errors.CodeInternal, "could not serialize integration config to JSON") } return filterSetJson, nil } @@ -136,7 +135,7 @@ func (c *AccountConfig) Scan(src any) error { case string: data = []byte(v) default: - return fmt.Errorf("tried to scan from %T instead of string or bytes", src) + return errors.NewInternalf(errors.CodeInternal, "tried to scan from %T instead of string or bytes", src) } return json.Unmarshal(data, c) @@ -145,12 +144,12 @@ func (c *AccountConfig) Scan(src any) error { // For serializing to db func (c *AccountConfig) Value() (driver.Value, error) { if c == nil { - return nil, fmt.Errorf("cloud account config is nil") + return nil, errors.NewInternalf(errors.CodeInternal, "cloud account config is nil") } serialized, err := json.Marshal(c) if err != nil { - return nil, fmt.Errorf("couldn't serialize cloud account config to JSON: %w", err) + return nil, errors.WrapInternalf(err, errors.CodeInternal, "couldn't serialize cloud account config to JSON") } return serialized, nil } @@ -169,7 +168,7 @@ func (r *AgentReport) Scan(src any) error { case string: data = []byte(v) default: - return fmt.Errorf("tried to scan from %T instead of string or bytes", src) + return errors.NewInternalf(errors.CodeInternal, "tried to scan from %T instead of string or bytes", src) } return json.Unmarshal(data, r) @@ -178,13 +177,13 @@ func (r *AgentReport) Scan(src any) error { // For serializing to db func (r *AgentReport) Value() (driver.Value, error) { if r == nil { - return nil, fmt.Errorf("agent report is nil") + return nil, errors.NewInternalf(errors.CodeInternal, "agent report is nil") } serialized, err := json.Marshal(r) if err != nil { - return nil, fmt.Errorf( - "couldn't serialize agent report to JSON: %w", err, + return nil, errors.WrapInternalf( + err, errors.CodeInternal, "couldn't serialize agent report to JSON", ) } return serialized, nil @@ -223,7 +222,7 @@ func (c *CloudServiceConfig) Scan(src any) error { case string: data = []byte(src) default: - return fmt.Errorf("tried to scan from %T instead of string or bytes", src) + return errors.NewInternalf(errors.CodeInternal, "tried to scan from %T instead of string or bytes", src) } return json.Unmarshal(data, c) @@ -232,13 +231,13 @@ func (c *CloudServiceConfig) Scan(src any) error { // For serializing to db func (c *CloudServiceConfig) Value() (driver.Value, error) { if c == nil { - return nil, fmt.Errorf("cloud service config is nil") + return nil, errors.NewInternalf(errors.CodeInternal, "cloud service config is nil") } serialized, err := json.Marshal(c) if err != nil { - return nil, fmt.Errorf( - "couldn't serialize cloud service config to JSON: %w", err, + return nil, errors.WrapInternalf( + err, errors.CodeInternal, "couldn't serialize cloud service config to JSON", ) } return serialized, nil diff --git a/pkg/types/licensetypes/license.go b/pkg/types/licensetypes/license.go index fea61f26d0..39b8f5de99 100644 --- a/pkg/types/licensetypes/license.go +++ b/pkg/types/licensetypes/license.go @@ -3,7 +3,6 @@ package licensetypes import ( "context" "encoding/json" - "fmt" "reflect" "time" @@ -113,9 +112,9 @@ func extractKeyFromMapStringInterface[T any](data map[string]interface{}, key st if value, ok := val.(T); ok { return value, nil } - return zeroValue, fmt.Errorf("%s key is not a valid %s", key, reflect.TypeOf(zeroValue)) + return zeroValue, errors.NewInvalidInputf(errors.CodeInvalidInput, "%s key is not a valid %s", key, reflect.TypeOf(zeroValue)) } - return zeroValue, fmt.Errorf("%s key is missing", key) + return zeroValue, errors.NewInvalidInputf(errors.CodeInvalidInput, "%s key is missing", key) } func NewLicense(data []byte, organizationID valuer.UUID) (*License, error) { diff --git a/pkg/types/pipelinetypes/pipeline.go b/pkg/types/pipelinetypes/pipeline.go index 31fff6e7f4..ac235846f8 100644 --- a/pkg/types/pipelinetypes/pipeline.go +++ b/pkg/types/pipelinetypes/pipeline.go @@ -2,15 +2,14 @@ package pipelinetypes import ( "encoding/json" - "fmt" "regexp" "slices" "strings" + "github.com/SigNoz/signoz/pkg/errors" v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3" "github.com/SigNoz/signoz/pkg/query-service/queryBuilderToExpr" "github.com/SigNoz/signoz/pkg/types" - "github.com/pkg/errors" "github.com/uptrace/bun" ) @@ -66,7 +65,7 @@ func (i *GettablePipeline) ParseRawConfig() error { c := []PipelineOperator{} err := json.Unmarshal([]byte(i.ConfigJSON), &c) if err != nil { - return errors.Wrap(err, "failed to parse ingestion rule config") + return errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to parse ingestion rule config") } i.Config = c return nil @@ -76,7 +75,7 @@ func (i *GettablePipeline) ParseFilter() error { f := v3.FilterSet{} err := json.Unmarshal([]byte(i.FilterString), &f) if err != nil { - return errors.Wrap(err, "failed to parse filter") + return errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to parse filter") } i.Filter = &f return nil @@ -208,20 +207,20 @@ type PostablePipeline struct { // IsValid checks if postable pipeline has all the required params func (p *PostablePipeline) IsValid() error { if p.OrderID == 0 { - return fmt.Errorf("orderId with value > 1 is required") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "orderId with value > 1 is required") } if p.Name == "" { - return fmt.Errorf("pipeline name is required") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "pipeline name is required") } if p.Alias == "" { - return fmt.Errorf("pipeline alias is required") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "pipeline alias is required") } // check the filter _, err := queryBuilderToExpr.Parse(p.Filter) if err != nil { - return fmt.Errorf("filter for pipeline %v is not correct: %v", p.Name, err.Error()) + return errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "filter for pipeline %v is not correct", p.Name) } idUnique := map[string]struct{}{} @@ -230,30 +229,30 @@ func (p *PostablePipeline) IsValid() error { l := len(p.Config) for i, op := range p.Config { if op.OrderId == 0 { - return fmt.Errorf("orderId with value > 1 is required in operator") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "orderId with value > 1 is required in operator") } if op.ID == "" { - return fmt.Errorf("id of an operator cannot be empty") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "id of an operator cannot be empty") } if op.Type == "" { - return fmt.Errorf("type of an operator cannot be empty") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "type of an operator cannot be empty") } if i != (l-1) && op.Output == "" { - return fmt.Errorf("output of operator %s cannot be nil", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "output of operator %s cannot be nil", op.ID) } if i == (l-1) && op.Output != "" { - return fmt.Errorf("output of operator %s should be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "output of operator %s should be empty", op.ID) } if _, ok := idUnique[op.ID]; ok { - return fmt.Errorf("duplicate id cannot be present") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "duplicate id cannot be present") } if _, ok := outputUnique[op.Output]; ok { - return fmt.Errorf("duplicate output cannot be present") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "duplicate output cannot be present") } if op.ID == op.Output { - return fmt.Errorf("id and output cannot be same") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "id and output cannot be same") } err := isValidOperator(op) @@ -269,31 +268,31 @@ func (p *PostablePipeline) IsValid() error { func isValidOperator(op PipelineOperator) error { if op.ID == "" { - return errors.New("PipelineOperator.ID is required") + return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "PipelineOperator.ID is required") } switch op.Type { case "json_parser": if op.ParseFrom == "" && op.ParseTo == "" { - return fmt.Errorf("parse from and parse to of %s json operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "parse from and parse to of %s json operator cannot be empty", op.ID) } for k := range op.Mapping { if !slices.Contains(validMappingVariableTypes, strings.ToLower(k)) { - return fmt.Errorf("%s is not a valid mapping type in processor %s", k, op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "%s is not a valid mapping type in processor %s", k, op.ID) } } case "grok_parser": if op.Pattern == "" { - return fmt.Errorf("pattern of %s grok operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "pattern of %s grok operator cannot be empty", op.ID) } case "regex_parser": if op.Regex == "" { - return fmt.Errorf("regex of %s regex operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "regex of %s regex operator cannot be empty", op.ID) } r, err := regexp.Compile(op.Regex) if err != nil { - return fmt.Errorf("error compiling regex expression of %s regex operator", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "error compiling regex expression of %s regex operator", op.ID) } namedCaptureGroups := 0 for _, groupName := range r.SubexpNames() { @@ -302,27 +301,27 @@ func isValidOperator(op PipelineOperator) error { } } if namedCaptureGroups == 0 { - return fmt.Errorf("no capture groups in regex expression of %s regex operator", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "no capture groups in regex expression of %s regex operator", op.ID) } case "copy": if op.From == "" || op.To == "" { - return fmt.Errorf("from or to of %s copy operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "from or to of %s copy operator cannot be empty", op.ID) } case "move": if op.From == "" || op.To == "" { - return fmt.Errorf("from or to of %s move operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "from or to of %s move operator cannot be empty", op.ID) } case "add": if op.Field == "" || op.Value == "" { - return fmt.Errorf("field or value of %s add operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "field or value of %s add operator cannot be empty", op.ID) } case "remove": if op.Field == "" { - return fmt.Errorf("field of %s remove operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "field of %s remove operator cannot be empty", op.ID) } case "trace_parser": if op.TraceParser == nil { - return fmt.Errorf("field of %s remove operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "field of %s remove operator cannot be empty", op.ID) } hasTraceIdParseFrom := (op.TraceParser.TraceId != nil && op.TraceParser.TraceId.ParseFrom != "") @@ -330,42 +329,40 @@ func isValidOperator(op PipelineOperator) error { hasTraceFlagsParseFrom := (op.TraceParser.TraceFlags != nil && op.TraceParser.TraceFlags.ParseFrom != "") if !(hasTraceIdParseFrom || hasSpanIdParseFrom || hasTraceFlagsParseFrom) { - return fmt.Errorf("one of trace_id, span_id, trace_flags of %s trace_parser operator must be present", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "one of trace_id, span_id, trace_flags of %s trace_parser operator must be present", op.ID) } if hasTraceIdParseFrom && !isValidOtelValue(op.TraceParser.TraceId.ParseFrom) { - return fmt.Errorf("trace id can't be parsed from %s", op.TraceParser.TraceId.ParseFrom) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "trace id can't be parsed from %s", op.TraceParser.TraceId.ParseFrom) } if hasSpanIdParseFrom && !isValidOtelValue(op.TraceParser.SpanId.ParseFrom) { - return fmt.Errorf("span id can't be parsed from %s", op.TraceParser.SpanId.ParseFrom) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "span id can't be parsed from %s", op.TraceParser.SpanId.ParseFrom) } if hasTraceFlagsParseFrom && !isValidOtelValue(op.TraceParser.TraceFlags.ParseFrom) { - return fmt.Errorf("trace flags can't be parsed from %s", op.TraceParser.TraceFlags.ParseFrom) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "trace flags can't be parsed from %s", op.TraceParser.TraceFlags.ParseFrom) } case "retain": if len(op.Fields) == 0 { - return fmt.Errorf("fields of %s retain operator cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "fields of %s retain operator cannot be empty", op.ID) } case "time_parser": if op.ParseFrom == "" { - return fmt.Errorf("parse from of time parsing processor %s cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "parse from of time parsing processor %s cannot be empty", op.ID) } if op.LayoutType != "epoch" && op.LayoutType != "strptime" { // TODO(Raj): Maybe add support for gotime format - return fmt.Errorf( - "invalid format type '%s' of time parsing processor %s", op.LayoutType, op.ID, - ) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "invalid format type '%s' of time parsing processor %s", op.LayoutType, op.ID) } if op.Layout == "" { - return fmt.Errorf("format can not be empty for time parsing processor %s", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "format can not be empty for time parsing processor %s", op.ID) } validEpochLayouts := []string{"s", "ms", "us", "ns", "s.ms", "s.us", "s.ns"} if op.LayoutType == "epoch" && !slices.Contains(validEpochLayouts, op.Layout) { - return fmt.Errorf( - "invalid epoch format '%s' of time parsing processor %s", op.LayoutType, op.ID, + return errors.NewInvalidInputf( + errors.CodeInvalidInput, "invalid epoch format '%s' of time parsing processor %s", op.LayoutType, op.ID, ) } @@ -374,23 +371,30 @@ func isValidOperator(op PipelineOperator) error { if op.LayoutType == "strptime" { _, err := RegexForStrptimeLayout(op.Layout) if err != nil { - return fmt.Errorf("invalid strptime format '%s' of time parsing processor %s: %w", op.LayoutType, op.ID, err) + return errors.WrapInvalidInputf( + err, errors.CodeInvalidInput, "invalid strptime format '%s' of time parsing processor %s", + op.LayoutType, op.ID, + ) } } case "severity_parser": if op.ParseFrom == "" { - return fmt.Errorf("parse from of severity parsing processor %s cannot be empty", op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "parse from of severity parsing processor %s cannot be empty", op.ID) } for k := range op.Mapping { if !slices.Contains(validMappingLevels, strings.ToLower(k)) { - return fmt.Errorf("%s is not a valid severity in processor %s", k, op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "%s is not a valid severity in processor %s", k, op.ID) } } default: - return fmt.Errorf("operator type %s not supported for %s, use one of (grok_parser, regex_parser, copy, move, add, remove, trace_parser, retain)", op.Type, op.ID) + return errors.NewInvalidInputf( + errors.CodeInvalidInput, + "operator type %s not supported for %s, use one of (grok_parser, regex_parser, copy, move, add, remove, trace_parser, retain)", + op.Type, op.ID, + ) } if !isValidOtelValue(op.ParseFrom) || @@ -399,7 +403,7 @@ func isValidOperator(op PipelineOperator) error { !isValidOtelValue(op.To) || !isValidOtelValue(op.Field) { valueErrStr := "value should have prefix of body, attributes, resource" - return fmt.Errorf("%s for operator Id %s", valueErrStr, op.ID) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "%s for operator Id %s", valueErrStr, op.ID) } return nil } diff --git a/pkg/types/pipelinetypes/time_parser.go b/pkg/types/pipelinetypes/time_parser.go index eaa80c1db2..072d7ee7e6 100644 --- a/pkg/types/pipelinetypes/time_parser.go +++ b/pkg/types/pipelinetypes/time_parser.go @@ -1,7 +1,6 @@ package pipelinetypes import ( - "fmt" "regexp" "strings" @@ -114,7 +113,7 @@ func RegexForStrptimeLayout(layout string) (string, error) { strptimeDirectiveRegexp := regexp.MustCompile(`%.`) layoutRegex = strptimeDirectiveRegexp.ReplaceAllStringFunc(layoutRegex, replaceStrptimeDirectiveWithRegex) if len(errs) != 0 { - return "", fmt.Errorf("couldn't generate regex for ctime format: %v", errs) + return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "couldn't generate regex for ctime format: %v", errs) } return layoutRegex, nil diff --git a/pkg/types/ruletypes/api_params.go b/pkg/types/ruletypes/api_params.go index 2ca74f178c..f206b64860 100644 --- a/pkg/types/ruletypes/api_params.go +++ b/pkg/types/ruletypes/api_params.go @@ -173,7 +173,8 @@ func (ns *NotificationSettings) UnmarshalJSON(data []byte) error { // Validate states after unmarshaling for _, state := range ns.Renotify.AlertStates { if state != model.StateFiring && state != model.StateNoData { - return fmt.Errorf("invalid alert state: %s", state) + return signozError.NewInvalidInputf(signozError.CodeInvalidInput, "invalid alert state: %s", state) + } } return nil diff --git a/pkg/types/ruletypes/templates.go b/pkg/types/ruletypes/templates.go index e698986eed..aaa9d611fd 100644 --- a/pkg/types/ruletypes/templates.go +++ b/pkg/types/ruletypes/templates.go @@ -290,7 +290,7 @@ func (te TemplateExpander) Expand() (result string, resultErr error) { var ok bool resultErr, ok = r.(error) if !ok { - resultErr = fmt.Errorf("panic expanding template %v: %v", te.name, r) + resultErr = errors.NewInternalf(errors.CodeInternal, "panic expanding template %v: %v", te.name, r) } } }() @@ -299,12 +299,12 @@ func (te TemplateExpander) Expand() (result string, resultErr error) { tmpl, err := text_template.New(te.name).Funcs(te.funcMap).Option("missingkey=zero").Parse(te.text) if err != nil { - return "", fmt.Errorf("error parsing template %v: %v", te.name, err) + return "", errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "error parsing template %v", te.name) } var buffer bytes.Buffer err = tmpl.Execute(&buffer, te.data) if err != nil { - return "", fmt.Errorf("error executing template %v: %v", te.name, err) + return "", errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "error executing template %v", te.name) } return buffer.String(), nil } @@ -316,7 +316,7 @@ func (te TemplateExpander) ExpandHTML(templateFiles []string) (result string, re var ok bool resultErr, ok = r.(error) if !ok { - resultErr = fmt.Errorf("panic expanding template %v: %v", te.name, r) + resultErr = errors.NewInternalf(errors.CodeInternal, "panic expanding template %v: %v", te.name, r) } } }() @@ -332,18 +332,18 @@ func (te TemplateExpander) ExpandHTML(templateFiles []string) (result string, re }) tmpl, err := tmpl.Parse(te.text) if err != nil { - return "", fmt.Errorf("error parsing template %v: %v", te.name, err) + return "", errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "error parsing template %v", te.name) } if len(templateFiles) > 0 { _, err = tmpl.ParseFiles(templateFiles...) if err != nil { - return "", fmt.Errorf("error parsing template files for %v: %v", te.name, err) + return "", errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "error parsing template files for %v", te.name) } } var buffer bytes.Buffer err = tmpl.Execute(&buffer, te.data) if err != nil { - return "", fmt.Errorf("error executing template %v: %v", te.name, err) + return "", errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "error executing template %v", te.name) } return buffer.String(), nil } diff --git a/pkg/types/telemetrytypes/field_context.go b/pkg/types/telemetrytypes/field_context.go index b3e05c1625..3ec90bde08 100644 --- a/pkg/types/telemetrytypes/field_context.go +++ b/pkg/types/telemetrytypes/field_context.go @@ -2,9 +2,9 @@ package telemetrytypes import ( "encoding/json" - "fmt" "strings" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/valuer" ) @@ -98,7 +98,7 @@ func (f *FieldContext) UnmarshalJSON(data []byte) error { // Scan implements the sql.Scanner interface func (f *FieldContext) Scan(value interface{}) error { if f == nil { - return fmt.Errorf("fieldcontext: nil receiver") + return errors.NewInternalf(errors.CodeInternal, "fieldcontext: nil receiver") } if value == nil { @@ -108,7 +108,7 @@ func (f *FieldContext) Scan(value interface{}) error { str, ok := value.(string) if !ok { - return fmt.Errorf("fieldcontext: expected string, got %T", value) + return errors.NewInternalf(errors.CodeInternal, "fieldcontext: expected string, got %T", value) } // Normalize the string diff --git a/pkg/types/telemetrytypes/field_datatype.go b/pkg/types/telemetrytypes/field_datatype.go index f6232d32ce..3ff46e8a6b 100644 --- a/pkg/types/telemetrytypes/field_datatype.go +++ b/pkg/types/telemetrytypes/field_datatype.go @@ -2,9 +2,9 @@ package telemetrytypes import ( "encoding/json" - "fmt" "strings" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/valuer" ) @@ -123,7 +123,7 @@ func (f *FieldDataType) UnmarshalJSON(data []byte) error { // Scan implements the sql.Scanner interface func (f *FieldDataType) Scan(value interface{}) error { if f == nil { - return fmt.Errorf("fielddatatype: nil receiver") + return errors.NewInternalf(errors.CodeInternal, "fielddatatype: nil receiver") } if value == nil { @@ -133,7 +133,7 @@ func (f *FieldDataType) Scan(value interface{}) error { str, ok := value.(string) if !ok { - return fmt.Errorf("fielddatatype: expected string, got %T", value) + return errors.NewInternalf(errors.CodeInternal, "fielddatatype: expected string, got %T", value) } // Normalize the string diff --git a/pkg/types/telemetrytypes/telemetrytypestest/load_keys.go b/pkg/types/telemetrytypes/telemetrytypestest/load_keys.go index 6207a24fc7..1b2f56ff23 100644 --- a/pkg/types/telemetrytypes/telemetrytypestest/load_keys.go +++ b/pkg/types/telemetrytypes/telemetrytypestest/load_keys.go @@ -2,9 +2,9 @@ package telemetrytypestest import ( "encoding/json" - "fmt" "os" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/types/telemetrytypes" ) @@ -12,12 +12,12 @@ import ( func LoadFieldKeysFromJSON(filePath string) (map[string][]*telemetrytypes.TelemetryFieldKey, error) { jsonData, err := os.ReadFile(filePath) if err != nil { - return nil, fmt.Errorf("failed to read JSON file: %w", err) + return nil, errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to read JSON file") } var result map[string][]*telemetrytypes.TelemetryFieldKey if err := json.Unmarshal(jsonData, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal JSON: %w", err) + return nil, errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to unmarshal JSON") } return result, nil @@ -27,7 +27,7 @@ func LoadFieldKeysFromJSON(filePath string) (map[string][]*telemetrytypes.Teleme func LoadFieldKeysFromJSONString(jsonStr string) (map[string][]*telemetrytypes.TelemetryFieldKey, error) { var result map[string][]*telemetrytypes.TelemetryFieldKey if err := json.Unmarshal([]byte(jsonStr), &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal JSON: %w", err) + return nil, errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to unmarshal JSON") } return result, nil diff --git a/pkg/types/tracefunneltypes/utils.go b/pkg/types/tracefunneltypes/utils.go index 8fb3e4bac2..c839d2500f 100644 --- a/pkg/types/tracefunneltypes/utils.go +++ b/pkg/types/tracefunneltypes/utils.go @@ -1,7 +1,6 @@ package tracefunneltypes import ( - "fmt" "sort" "time" @@ -13,10 +12,10 @@ import ( // ValidateTimestamp validates a timestamp func ValidateTimestamp(timestamp int64, fieldName string) error { if timestamp == 0 { - return fmt.Errorf("%s is required", fieldName) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "%s is required", fieldName) } if timestamp < 0 { - return fmt.Errorf("%s must be positive", fieldName) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "%s must be positive", fieldName) } return nil } @@ -28,18 +27,18 @@ func ValidateTimestampIsMilliseconds(timestamp int64) bool { func ValidateFunnelSteps(steps []*FunnelStep) error { if len(steps) < 2 { - return fmt.Errorf("funnel must have at least 2 steps") + return errors.NewInvalidInputf(errors.CodeInvalidInput, "funnel must have at least 2 steps") } for i, step := range steps { if step.ServiceName == "" { - return fmt.Errorf("step %d: service name is required", i+1) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "step %d: service name is required", i+1) } if step.SpanName == "" { - return fmt.Errorf("step %d: span name is required", i+1) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "step %d: span name is required", i+1) } if step.Order < 0 { - return fmt.Errorf("step %d: order must be non-negative", i+1) + return errors.NewInvalidInputf(errors.CodeInvalidInput, "step %d: order must be non-negative", i+1) } } diff --git a/pkg/variables/clickhouse/processor.go b/pkg/variables/clickhouse/processor.go index 3f843ebfc2..c630e4121f 100644 --- a/pkg/variables/clickhouse/processor.go +++ b/pkg/variables/clickhouse/processor.go @@ -1,10 +1,10 @@ package clickhouse import ( - "fmt" "strings" "github.com/AfterShip/clickhouse-sql-parser/parser" + "github.com/SigNoz/signoz/pkg/errors" ) // FilterAction represents what to do with a filter containing a variable @@ -37,7 +37,7 @@ func (qp *QueryProcessor) ProcessQuery(query string, transformer FilterTransform p := parser.NewParser(query) stmts, err := p.ParseStmts() if err != nil { - return "", fmt.Errorf("failed to parse query: %w", err) + return "", errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "failed to parse query") } if len(stmts) == 0 { diff --git a/pkg/variables/variable_replace_visitor.go b/pkg/variables/variable_replace_visitor.go index 6b4cbe016e..c31660b34e 100644 --- a/pkg/variables/variable_replace_visitor.go +++ b/pkg/variables/variable_replace_visitor.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" + "github.com/SigNoz/signoz/pkg/errors" grammar "github.com/SigNoz/signoz/pkg/parser/grammar" qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5" "github.com/antlr4-go/antlr/v4" @@ -26,7 +27,7 @@ func NewErrorListener() *ErrorListener { // SyntaxError is called when a syntax error is encountered func (e *ErrorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol any, line, column int, msg string, ex antlr.RecognitionException) { - e.SyntaxErrors = append(e.SyntaxErrors, fmt.Errorf("line %d:%d %s", line, column, msg)) + e.SyntaxErrors = append(e.SyntaxErrors, errors.NewInvalidInputf(errors.CodeInvalidInput, "line %d:%d %s", line, column, msg)) } // variableReplacementVisitor implements the visitor interface @@ -62,13 +63,13 @@ func ReplaceVariablesInExpression(expression string, variables map[string]qbtype tree := parser.Query() if len(parserErrorListener.SyntaxErrors) > 0 { - return "", fmt.Errorf("syntax errors in expression: %v", parserErrorListener.SyntaxErrors) + return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "syntax errors in expression: %v", parserErrorListener.SyntaxErrors) } result := visitor.Visit(tree).(string) if len(visitor.errors) > 0 { - return "", fmt.Errorf("errors processing expression: %v", visitor.errors) + return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "errors processing expression: %v", visitor.errors) } // If the entire expression should be skipped, return empty string diff --git a/pkg/web/routerweb/provider.go b/pkg/web/routerweb/provider.go index 9ec07da85b..6bc3899714 100644 --- a/pkg/web/routerweb/provider.go +++ b/pkg/web/routerweb/provider.go @@ -2,11 +2,11 @@ package routerweb import ( "context" - "fmt" "net/http" "os" "path/filepath" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" "github.com/SigNoz/signoz/pkg/http/middleware" "github.com/SigNoz/signoz/pkg/web" @@ -28,21 +28,21 @@ func NewFactory() factory.ProviderFactory[web.Web, web.Config] { func New(ctx context.Context, settings factory.ProviderSettings, config web.Config) (web.Web, error) { fi, err := os.Stat(config.Directory) if err != nil { - return nil, fmt.Errorf("cannot access web directory: %w", err) + return nil, errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "cannot access web directory") } ok := fi.IsDir() if !ok { - return nil, fmt.Errorf("web directory is not a directory") + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "web directory is not a directory") } fi, err = os.Stat(filepath.Join(config.Directory, indexFileName)) if err != nil { - return nil, fmt.Errorf("cannot access %q in web directory: %w", indexFileName, err) + return nil, errors.WrapInvalidInputf(err, errors.CodeInvalidInput, "cannot access %q in web directory", indexFileName) } if os.IsNotExist(err) || fi.IsDir() { - return nil, fmt.Errorf("%q does not exist", indexFileName) + return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "%q does not exist", indexFileName) } return &provider{ @@ -60,7 +60,7 @@ func (provider *provider) AddToRouter(router *mux.Router) error { ), ).GetError() if err != nil { - return fmt.Errorf("unable to add web to router: %w", err) + return errors.WrapInternalf(err, errors.CodeInternal, "unable to add web to router") } return nil