diff --git a/cmd/pd-server/main.go b/cmd/pd-server/main.go index 50d7ace2b457..f51114c357ad 100644 --- a/cmd/pd-server/main.go +++ b/cmd/pd-server/main.go @@ -24,6 +24,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/log" "github.com/tikv/pd/pkg/dashboard" + "github.com/tikv/pd/pkg/errs" "github.com/tikv/pd/pkg/logutil" "github.com/tikv/pd/pkg/metricutil" "github.com/tikv/pd/pkg/swaggerserver" @@ -53,7 +54,7 @@ func main() { case flag.ErrHelp: exit(0) default: - log.Fatal("parse cmd flags error", zap.Error(err)) + log.Fatal("parse cmd flags error", errs.ZapError(errs.ErrParseFlags)) } if cfg.ConfigCheck { @@ -66,7 +67,7 @@ func main() { if err == nil { log.ReplaceGlobals(cfg.GetZapLogger(), cfg.GetZapLogProperties()) } else { - log.Fatal("initialize logger error", zap.Error(err)) + log.Fatal("initialize logger error", errs.ZapError(err)) } // Flushing any buffered log entries defer log.Sync() @@ -74,7 +75,7 @@ func main() { // The old logger err = logutil.InitLogger(&cfg.Log) if err != nil { - log.Fatal("initialize logger error", zap.Error(err)) + log.Fatal("initialize logger error", errs.ZapError(err)) } server.LogPDInfo() @@ -99,7 +100,7 @@ func main() { serviceBuilders = append(serviceBuilders, dashboard.GetServiceBuilders()...) svr, err := server.CreateServer(ctx, cfg, serviceBuilders...) if err != nil { - log.Fatal("create server failed", zap.Error(err)) + log.Fatal("create server failed", errs.ZapError(err)) } sc := make(chan os.Signal, 1) diff --git a/pkg/errs/errno.go b/pkg/errs/errno.go index cac94bfb7395..3e31d82e00fd 100644 --- a/pkg/errs/errno.go +++ b/pkg/errs/errno.go @@ -16,6 +16,11 @@ package errs import "github.com/pingcap/errors" // The internal error which is generated in PD project. +// main errors +var ( + ErrParseFlags = errors.Normalize("parse flags error", errors.RFCCodeText("PD:main:ErrParseFlags")) +) + // tso errors var ( ErrInvalidTimestamp = errors.Normalize("invalid timestamp", errors.RFCCodeText("PD:tso:ErrInvalidTimestamp")) @@ -41,6 +46,7 @@ var ( // scheduler errors var ( +<<<<<<< HEAD ErrGetSourceStore = errors.Normalize("failed to get the source store", errors.RFCCodeText("PD:scheduler:ErrGetSourceStore")) ErrSchedulerExisted = errors.Normalize("scheduler existed", errors.RFCCodeText("PD:scheduler:ErrSchedulerExisted")) ErrSchedulerNotFound = errors.Normalize("scheduler not found", errors.RFCCodeText("PD:scheduler:ErrSchedulerNotFound")) @@ -48,6 +54,16 @@ var ( ErrSchedulerConfig = errors.Normalize("wrong scheduler config %s", errors.RFCCodeText("PD:scheduler:ErrSchedulerConfig")) ErrCacheOverflow = errors.Normalize("cache overflow", errors.RFCCodeText("PD:scheduler:ErrCacheOverflow")) ErrInternalGrowth = errors.Normalize("unknown interval growth type error", errors.RFCCodeText("PD:scheduler:ErrInternalGrowth")) +======= + ErrSchedulerExisted = errors.Normalize("scheduler existed", errors.RFCCodeText("PD:scheduler:ErrSchedulerExisted")) + ErrSchedulerDuplicated = errors.Normalize("scheduler duplicated", errors.RFCCodeText("PD:scheduler:ErrSchedulerDuplicated")) + ErrSchedulerNotFound = errors.Normalize("scheduler not found", errors.RFCCodeText("PD:scheduler:ErrSchedulerNotFound")) + ErrScheduleConfigNotExist = errors.Normalize("the config does not exist", errors.RFCCodeText("PD:scheduler:ErrScheduleConfigNotExist")) + ErrSchedulerConfig = errors.Normalize("wrong scheduler config %s", errors.RFCCodeText("PD:scheduler:ErrSchedulerConfig")) + ErrCacheOverflow = errors.Normalize("cache overflow", errors.RFCCodeText("PD:scheduler:ErrCacheOverflow")) + ErrInternalGrowth = errors.Normalize("unknown interval growth type error", errors.RFCCodeText("PD:scheduler:ErrInternalGrowth")) + ErrSchedulerCreateFuncNotRegistered = errors.Normalize("create func of %v is not registered", errors.RFCCodeText("PD:scheduler:ErrSchedulerCreateFuncNotRegistered")) +>>>>>>> 67cc378... *: refine the fatal log (#2896) ) // placement errors @@ -60,6 +76,7 @@ var ( // cluster errors var ( +<<<<<<< HEAD ErrPersistStore = errors.Normalize("failed to persist store", errors.RFCCodeText("PD:cluster:ErrPersistStore")) ErrDeleteRegion = errors.Normalize("failed to delete region from storage", errors.RFCCodeText("PD:cluster:ErrDeleteRegion")) ErrSaveRegion = errors.Normalize("failed to save region from storage", errors.RFCCodeText("PD:cluster:ErrSaveRegion")) @@ -67,6 +84,30 @@ var ( ErrDeleteStore = errors.Normalize("failed to delete store", errors.RFCCodeText("PD:cluster:ErrDeleteStore")) ErrPersistClusterVersion = errors.Normalize("persist cluster version meet error", errors.RFCCodeText("PD:cluster:ErrPersistClusterVersion")) ErrGetMembers = errors.Normalize("get members failed", errors.RFCCodeText("PD:cluster:ErrGetMembers")) +======= + ErrNotBootstrapped = errors.Normalize("TiKV cluster not bootstrapped, please start TiKV first", errors.RFCCodeText("PD:cluster:ErrNotBootstrapped")) + ErrStoreIsUp = errors.Normalize("store is still up, please remove store gracefully", errors.RFCCodeText("PD:cluster:ErrStoreIsUp")) +) + +// versioninfo errors +var ( + ErrFeatureNotExisted = errors.Normalize("feature not existed", errors.RFCCodeText("PD:versioninfo:ErrFeatureNotExisted")) +) + +// autoscaling errors +var ( + ErrUnsupportedMetricsType = errors.Normalize("unsupported metrics type %v", errors.RFCCodeText("PD:autoscaling:ErrUnsupportedMetricsType")) + ErrUnsupportedComponentType = errors.Normalize("unsupported component type %v", errors.RFCCodeText("PD:autoscaling:ErrUnsupportedComponentType")) + ErrUnexpectedType = errors.Normalize("unexpected type %v", errors.RFCCodeText("PD:autoscaling:ErrUnexpectedType")) + ErrTypeConversion = errors.Normalize(("type conversion error"), errors.RFCCodeText("PD:autoscaling:ErrTypeConversion")) + ErrEmptyMetricsResponse = errors.Normalize("metrics response from Prometheus is empty", errors.RFCCodeText("PD:autoscaling:ErrEmptyMetricsResponse")) + ErrEmptyMetricsResult = errors.Normalize("result from Prometheus is empty, %s", errors.RFCCodeText("PD:autoscaling:ErrEmptyMetricsResult")) +) + +// apiutil errors +var ( + ErrRedirect = errors.Normalize("redirect failed", errors.RFCCodeText("PD:apiutil:ErrRedirect")) +>>>>>>> 67cc378... *: refine the fatal log (#2896) ) // grpcutil errors @@ -74,6 +115,28 @@ var ( ErrSecurityConfig = errors.Normalize("security config error: %s", errors.RFCCodeText("PD:grpcutil:ErrSecurityConfig")) ) +<<<<<<< HEAD +======= +// server errors +var ( + ErrServiceRegistered = errors.Normalize("service with path [%s] already registered", errors.RFCCodeText("PD:server:ErrServiceRegistered")) + ErrAPIInformationInvalid = errors.Normalize("invalid api information, group %s version %s", errors.RFCCodeText("PD:server:ErrAPIInformationInvalid")) + ErrClientURLEmpty = errors.Normalize("client url empty", errors.RFCCodeText("PD:server:ErrClientEmpty")) + ErrLeaderNil = errors.Normalize("leader is nil", errors.RFCCodeText("PD:server:ErrLeaderNil")) + ErrCancelStartEtcd = errors.Normalize("etcd start canceled", errors.RFCCodeText("PD:server:ErrCancelStartEtcd")) +) + +// logutil errors +var ( + ErrInitFileLog = errors.Normalize("init file log error, %s", errors.RFCCodeText("PD:logutil:ErrInitFileLog")) +) + +// typeutil errors +var ( + ErrBytesToUint64 = errors.Normalize("invalid data, must 8 bytes, but %d", errors.RFCCodeText("PD:typeutil:ErrBytesToUint64")) +) + +>>>>>>> 67cc378... *: refine the fatal log (#2896) // The third-party project error. // url errors var ( @@ -149,3 +212,40 @@ var ( var ( ErrHexDecodingString = errors.Normalize("decode string %s error", errors.RFCCodeText("PD:hex:ErrHexDecodingString")) ) +<<<<<<< HEAD +======= + +// filepath errors +var ( + ErrFilePathAbs = errors.Normalize("failed to convert a path to absolute path", errors.RFCCodeText("PD:filepath:ErrFilePathAbs")) +) + +// plugin errors +var ( + ErrLoadPlugin = errors.Normalize("failed to load plugin", errors.RFCCodeText("PD:plugin:ErrLoadPlugin")) + ErrLookupPluginFunc = errors.Normalize("failed to lookup plugin function", errors.RFCCodeText("PD:plugin:ErrLookupPluginFunc")) +) + +// json errors +var ( + ErrJSONMarshal = errors.Normalize("failed to marshal json", errors.RFCCodeText("PD:json:ErrJSONMarshal")) + ErrJSONUnmarshal = errors.Normalize("failed to unmarshal json", errors.RFCCodeText("PD:json:ErrJSONUnmarshal")) +) + +// leveldb errors +var ( + ErrLevelDBClose = errors.Normalize("close leveldb error", errors.RFCCodeText("PD:leveldb:ErrLevelDBClose")) + ErrLevelDBWrite = errors.Normalize("leveldb write error", errors.RFCCodeText("PD:leveldb:ErrLevelDBWrite")) + ErrLevelDBOpen = errors.Normalize("leveldb open file error", errors.RFCCodeText("PD:leveldb:ErrLevelDBOpen")) +) + +// semver +var ( + ErrSemverNewVersion = errors.Normalize("new version error", errors.RFCCodeText("PD:semver:ErrSemverNewVersion")) +) + +// log +var ( + ErrInitLogger = errors.Normalize("init logger error", errors.RFCCodeText("PD:log:ErrInitLogger")) +) +>>>>>>> 67cc378... *: refine the fatal log (#2896) diff --git a/pkg/logutil/log.go b/pkg/logutil/log.go index 25e74a43ea51..64d26a1de448 100644 --- a/pkg/logutil/log.go +++ b/pkg/logutil/log.go @@ -23,9 +23,9 @@ import ( "sync" "github.com/coreos/pkg/capnslog" - "github.com/pingcap/errors" zaplog "github.com/pingcap/log" log "github.com/sirupsen/logrus" + "github.com/tikv/pd/pkg/errs" "go.etcd.io/etcd/raft" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -217,7 +217,7 @@ func StringToLogFormatter(format string, disableTimestamp bool) log.Formatter { func InitFileLog(cfg *zaplog.FileLogConfig) error { if st, err := os.Stat(cfg.Filename); err == nil { if st.IsDir() { - return errors.New("can't use directory as log file name") + return errs.ErrInitFileLog.FastGenByArgs("can't use directory as log file name") } } if cfg.MaxSize == 0 { diff --git a/pkg/typeutil/convension.go b/pkg/typeutil/convension.go index df869bbc9e4b..cd6944663f71 100644 --- a/pkg/typeutil/convension.go +++ b/pkg/typeutil/convension.go @@ -16,13 +16,13 @@ package typeutil import ( "encoding/binary" - "github.com/pingcap/errors" + "github.com/tikv/pd/pkg/errs" ) // BytesToUint64 converts a byte slice to uint64. func BytesToUint64(b []byte) (uint64, error) { if len(b) != 8 { - return 0, errors.Errorf("invalid data, must 8 bytes, but %d", len(b)) + return 0, errs.ErrBytesToUint64.FastGenByArgs(len(b)) } return binary.BigEndian.Uint64(b), nil diff --git a/server/cluster/version.go b/server/cluster/version.go index a48e9805d7c7..dbb1ebd6455a 100644 --- a/server/cluster/version.go +++ b/server/cluster/version.go @@ -17,6 +17,7 @@ import ( "github.com/coreos/go-semver/semver" "github.com/pingcap/errors" "github.com/pingcap/log" + "github.com/tikv/pd/pkg/errs" "go.uber.org/zap" ) @@ -50,7 +51,7 @@ var featuresDict = map[Feature]string{ func MinSupportedVersion(v Feature) *semver.Version { target, ok := featuresDict[v] if !ok { - log.Fatal("the corresponding version of the feature doesn't exist", zap.Int("feature-number", int(v))) + log.Fatal("the corresponding version of the feature doesn't exist", zap.Int("feature-number", int(v)), errs.ZapError(errs.ErrFeatureNotExisted)) } version := MustParseVersion(target) return version diff --git a/server/config/config.go b/server/config/config.go index 331e5676ef19..45488a764e47 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -26,6 +26,7 @@ import ( "sync" "time" + "github.com/tikv/pd/pkg/errs" "github.com/tikv/pd/pkg/grpcutil" "github.com/tikv/pd/pkg/metricutil" "github.com/tikv/pd/pkg/typeutil" @@ -1088,7 +1089,7 @@ func ParseUrls(s string) ([]url.URL, error) { for _, item := range items { u, err := url.Parse(item) if err != nil { - return nil, errors.WithStack(err) + return nil, errs.ErrURLParse.Wrap(err).GenWithStackByCause() } urls = append(urls, *u) @@ -1101,7 +1102,7 @@ func ParseUrls(s string) ([]url.URL, error) { func (c *Config) SetupLogger() error { lg, p, err := log.InitLogger(&c.Log, zap.AddStacktrace(zapcore.FatalLevel)) if err != nil { - return err + return errs.ErrInitLogger.Wrap(err).FastGenWithCause() } c.logger = lg c.logProps = p diff --git a/server/core/store.go b/server/core/store.go index e65a78d1c8a2..28f3e5f38a46 100644 --- a/server/core/store.go +++ b/server/core/store.go @@ -579,8 +579,13 @@ func (s *StoresInfo) BlockStore(storeID uint64) errcode.ErrorCode { func (s *StoresInfo) UnblockStore(storeID uint64) { store, ok := s.stores[storeID] if !ok { +<<<<<<< HEAD log.Fatal("store is unblocked, but it is not found", zap.Uint64("store-id", storeID)) +======= + log.Fatal("try to clean a store's pause state, but it is not found", + zap.Uint64("store-id", storeID), errs.ZapError(errs.ErrStoreNotFound.FastGenByArgs(storeID))) +>>>>>>> 67cc378... *: refine the fatal log (#2896) } s.stores[storeID] = store.Clone(SetStoreUnBlock()) } diff --git a/server/join/join.go b/server/join/join.go index b34d73c19a67..293b47245ba8 100644 --- a/server/join/join.go +++ b/server/join/join.go @@ -28,7 +28,6 @@ import ( "github.com/tikv/pd/server/config" "go.etcd.io/etcd/clientv3" "go.etcd.io/etcd/embed" - "go.uber.org/zap" ) const ( @@ -93,7 +92,7 @@ func PrepareJoinCluster(cfg *config.Config) error { if _, err := os.Stat(filePath); !os.IsNotExist(err) { s, err := ioutil.ReadFile(filePath) if err != nil { - log.Fatal("read the join config meet error", zap.Error(err)) + log.Fatal("read the join config meet error", errs.ZapError(errs.ErrIORead, err)) } cfg.InitialCluster = strings.TrimSpace(string(s)) cfg.InitialClusterState = embed.ClusterStateFlagExisting diff --git a/server/kv/levedb_kv.go b/server/kv/levedb_kv.go index 034253dcac3c..25b83a6f96d9 100644 --- a/server/kv/levedb_kv.go +++ b/server/kv/levedb_kv.go @@ -30,7 +30,7 @@ type LeveldbKV struct { func NewLeveldbKV(path string) (*LeveldbKV, error) { db, err := leveldb.OpenFile(path, nil) if err != nil { - return nil, errors.WithStack(err) + return nil, errs.ErrLevelDBOpen.Wrap(err).GenWithStackByCause() } return &LeveldbKV{db}, nil } diff --git a/server/region_syncer/history_buffer.go b/server/region_syncer/history_buffer.go index b2984999304c..263588dd9c2f 100644 --- a/server/region_syncer/history_buffer.go +++ b/server/region_syncer/history_buffer.go @@ -141,7 +141,7 @@ func (h *historyBuffer) reload() { if v != "" { h.index, err = strconv.ParseUint(v, 10, 64) if err != nil { - log.Fatal("load history index failed", zap.Error(err)) + log.Fatal("load history index failed", errs.ZapError(errs.ErrStrconvParseUint, err)) } } log.Info("start from history index", zap.Uint64("start-index", h.firstIndex())) diff --git a/server/schedule/scheduler.go b/server/schedule/scheduler.go index 30b3aca60342..c6cb6fd82287 100644 --- a/server/schedule/scheduler.go +++ b/server/schedule/scheduler.go @@ -86,7 +86,7 @@ var schedulerArgsToDecoder = make(map[string]ConfigSliceDecoderBuilder) // func of a package. func RegisterScheduler(typ string, createFn CreateSchedulerFunc) { if _, ok := schedulerMap[typ]; ok { - log.Fatal("duplicated scheduler", zap.String("type", typ)) + log.Fatal("duplicated scheduler", zap.String("type", typ), errs.ZapError(errs.ErrSchedulerDuplicated)) } schedulerMap[typ] = createFn } @@ -95,7 +95,7 @@ func RegisterScheduler(typ string, createFn CreateSchedulerFunc) { // func of package. func RegisterSliceDecoderBuilder(typ string, builder ConfigSliceDecoderBuilder) { if _, ok := schedulerArgsToDecoder[typ]; ok { - log.Fatal("duplicated scheduler", zap.String("type", typ)) + log.Fatal("duplicated scheduler", zap.String("type", typ), errs.ZapError(errs.ErrSchedulerDuplicated)) } schedulerArgsToDecoder[typ] = builder } diff --git a/server/util.go b/server/util.go index 8af33e422855..b30119d864b1 100644 --- a/server/util.go +++ b/server/util.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/pdpb" "github.com/pingcap/log" + "github.com/tikv/pd/pkg/errs" "github.com/tikv/pd/pkg/etcdutil" "github.com/tikv/pd/pkg/typeutil" "github.com/tikv/pd/server/cluster" @@ -101,7 +102,7 @@ func initOrGetClusterID(c *clientv3.Client, key string) (uint64, error) { Else(clientv3.OpGet(key)). Commit() if err != nil { - return 0, errors.WithStack(err) + return 0, errs.ErrEtcdTxn.Wrap(err).GenWithStackByCause() } // Txn commits ok, return the generated cluster ID. @@ -111,12 +112,12 @@ func initOrGetClusterID(c *clientv3.Client, key string) (uint64, error) { // Otherwise, parse the committed cluster ID. if len(resp.Responses) == 0 { - return 0, errors.Errorf("txn returns empty response: %v", resp) + return 0, errs.ErrEtcdTxn.FastGenByArgs() } response := resp.Responses[0].GetResponseRange() if response == nil || len(response.Kvs) != 1 { - return 0, errors.Errorf("txn returns invalid range response: %v", resp) + return 0, errs.ErrEtcdTxn.FastGenByArgs() } return typeutil.BytesToUint64(response.Kvs[0].Value) diff --git a/server/versioninfo/versioninfo.go b/server/versioninfo/versioninfo.go index f04293bd2190..e06af336dc73 100644 --- a/server/versioninfo/versioninfo.go +++ b/server/versioninfo/versioninfo.go @@ -13,6 +13,15 @@ package versioninfo +<<<<<<< HEAD +======= +import ( + "github.com/coreos/go-semver/semver" + "github.com/pingcap/log" + "github.com/tikv/pd/pkg/errs" +) + +>>>>>>> 67cc378... *: refine the fatal log (#2896) const ( // CommunityEdition is the default edition for building. CommunityEdition = "Community" @@ -26,3 +35,39 @@ var ( PDGitBranch = "None" PDEdition = CommunityEdition ) +<<<<<<< HEAD +======= + +// ParseVersion wraps semver.NewVersion and handles compatibility issues. +func ParseVersion(v string) (*semver.Version, error) { + // for compatibility with old version which not support `version` mechanism. + if v == "" { + return semver.New(featuresDict[Base]), nil + } + if v[0] == 'v' { + v = v[1:] + } + ver, err := semver.NewVersion(v) + if err != nil { + return nil, errs.ErrSemverNewVersion.Wrap(err).GenWithStackByCause() + } + return ver, nil +} + +// MustParseVersion wraps ParseVersion and will panic if error is not nil. +func MustParseVersion(v string) *semver.Version { + ver, err := ParseVersion(v) + if err != nil { + log.Fatal("version string is illegal", errs.ZapError(err)) + } + return ver +} + +// IsCompatible checks if the version a is compatible with the version b. +func IsCompatible(a, b semver.Version) bool { + if a.LessThan(b) { + return true + } + return a.Major == b.Major && a.Minor == b.Minor +} +>>>>>>> 67cc378... *: refine the fatal log (#2896)