diff --git a/.travis.yml b/.travis.yml index 64bb794db..81282e580 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ before_script: - echo $TRAVIS_SECURE_ENV_VARS script: - bash build.sh - - go test -v -race $(go list ./... | grep -v "/vendor/") -coverprofile cover.out + - go test -v -race -failfast -parallel 16 $(go list ./... | grep -v "/vendor/") -coverprofile cover.out - cd rpc && go test -test.bench ^BenchmarkPersistentCaller_Call$ -test.run ^$ && cd - - gocovmerge cover.out $(find cmd -name "*.cover.out") > coverage.txt && rm -f cover.out - bash <(curl -s https://codecov.io/bash) diff --git a/cmd/cql-minerd/integration_test.go b/cmd/cql-minerd/integration_test.go index 61fbf14e5..60024948c 100644 --- a/cmd/cql-minerd/integration_test.go +++ b/cmd/cql-minerd/integration_test.go @@ -49,13 +49,6 @@ var nodeCmds []*utils.CMD var FJ = filepath.Join -func TestBuild(t *testing.T) { - Convey("build", t, func() { - log.SetLevel(log.DebugLevel) - So(utils.Build(), ShouldBeNil) - }) -} - func startNodes() { ctx := context.Background() @@ -90,7 +83,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./integration/node_1/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-minerd/follower1.cover.out"), }, - "follower1", testWorkingDir, logDir, true, + "follower1", testWorkingDir, logDir, false, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -101,7 +94,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./integration/node_2/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-minerd/follower2.cover.out"), }, - "follower2", testWorkingDir, logDir, true, + "follower2", testWorkingDir, logDir, false, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -114,7 +107,7 @@ func startNodes() { 3122, 3121, 3120, - }, time.Millisecond*200) + }, time.Second) if err != nil { log.Fatalf("wait for port ready timeout: %v", err) @@ -154,7 +147,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./integration/node_miner_1/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-minerd/miner1.cover.out"), }, - "miner1", testWorkingDir, logDir, true, + "miner1", testWorkingDir, logDir, false, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -167,7 +160,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./integration/node_miner_2/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-minerd/miner2.cover.out"), }, - "miner2", testWorkingDir, logDir, true, + "miner2", testWorkingDir, logDir, false, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -324,15 +317,9 @@ func TestFullProcess(t *testing.T) { startNodes() defer stopNodes() var err error - err = utils.WaitToConnect(context.Background(), "127.0.0.1", []int{ - 2144, - 2145, - 2146, - 3122, - 3121, - 3120, - }, time.Millisecond*200) - time.Sleep(2 * time.Second) + + time.Sleep(10 * time.Second) + So(err, ShouldBeNil) err = client.Init(FJ(testWorkingDir, "./integration/node_c/config.yaml"), []byte("")) @@ -506,7 +493,7 @@ func benchMiner(b *testing.B, minerCount uint16, bypassSign bool) { 3122, 3121, 3120, - }, time.Millisecond*200) + }, 2*time.Second) time.Sleep(time.Second) } diff --git a/cmd/cql-minerd/main.go b/cmd/cql-minerd/main.go index 6fe9c0be9..1da8ac364 100644 --- a/cmd/cql-minerd/main.go +++ b/cmd/cql-minerd/main.go @@ -34,7 +34,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/metric" - "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils" @@ -118,7 +117,7 @@ func initLogs() { func main() { // set random rand.Seed(time.Now().UnixNano()) - log.SetLevel(log.InfoLevel) + log.SetLevel(log.DebugLevel) flag.Parse() if showVersion { @@ -216,45 +215,6 @@ func main() { } }() - // start block producer pinger - go func() { - var localNodeID proto.NodeID - var err error - - // get local node id - if localNodeID, err = kms.GetLocalNodeID(); err != nil { - return - } - - // get local node info - var localNodeInfo *proto.Node - if localNodeInfo, err = kms.GetNodeInfo(localNodeID); err != nil { - return - } - - log.WithField("node", localNodeInfo).Debug("construct local node info") - - go func() { - for { - select { - case <-time.After(time.Second): - case <-stopCh: - return - } - - // send ping requests to block producer - bpNodeIDs := route.GetBPs() - - for _, bpNodeID := range bpNodeIDs { - err := rpc.PingBP(localNodeInfo, bpNodeID) - if err == nil { - return - } - } - } - }() - }() - // start dbms var dbms *worker.DBMS if dbms, err = startDBMS(server); err != nil { diff --git a/cmd/cql-minerd/node.go b/cmd/cql-minerd/node.go index c28a31164..2b7808e0a 100644 --- a/cmd/cql-minerd/node.go +++ b/cmd/cql-minerd/node.go @@ -19,13 +19,18 @@ package main import ( "fmt" "os" + "strings" "syscall" + "time" "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/kayak" + "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils/log" + "github.com/pkg/errors" "golang.org/x/crypto/ssh/terminal" ) @@ -51,6 +56,11 @@ func initNode() (server *rpc.Server, err error) { // init kms routing route.InitKMS(conf.GConf.PubKeyStoreFile) + err = registerNodeToBP(15 * time.Second) + if err != nil { + log.Fatalf("register node to BP failed: %v", err) + } + // init server if server, err = createServer( conf.GConf.PrivateKeyFile, conf.GConf.PubKeyStoreFile, masterKey, conf.GConf.ListenAddr); err != nil { @@ -73,3 +83,53 @@ func createServer(privateKeyPath, pubKeyStorePath string, masterKey []byte, list return } + +func registerNodeToBP(timeout time.Duration) (err error) { + // get local node id + localNodeID, err := kms.GetLocalNodeID() + if err != nil { + err = errors.Wrap(err, "register node to BP") + return + } + + // get local node info + localNodeInfo, err := kms.GetNodeInfo(localNodeID) + if err != nil { + err = errors.Wrap(err, "register node to BP") + return + } + + log.WithField("node", localNodeInfo).Debug("construct local node info") + + pingWaitCh := make(chan proto.NodeID) + bpNodeIDs := route.GetBPs() + for _, bpNodeID := range bpNodeIDs { + go func(ch chan proto.NodeID, id proto.NodeID) { + for { + err := rpc.PingBP(localNodeInfo, id) + if err == nil { + log.Infof("ping BP succeed: %v", localNodeInfo) + ch <- id + return + } + if strings.Contains(err.Error(), kayak.ErrNotLeader.Error()) { + log.Debug("stop ping non leader BP node") + return + } + + log.Warnf("ping BP failed: %v", err) + time.Sleep(3 * time.Second) + } + }(pingWaitCh, bpNodeID) + } + + select { + case bp := <-pingWaitCh: + close(pingWaitCh) + log.WithField("BP", bp).Infof("ping BP succeed") + case <-time.After(timeout): + return errors.New("ping BP timeout") + } + + return +} diff --git a/cmd/cql-observer/observation_test.go b/cmd/cql-observer/observation_test.go index 4db8dc2d9..a0be43d42 100644 --- a/cmd/cql-observer/observation_test.go +++ b/cmd/cql-observer/observation_test.go @@ -52,13 +52,6 @@ var nodeCmds []*utils.CMD var FJ = filepath.Join -func TestBuild(t *testing.T) { - Convey("build", t, func() { - log.SetLevel(log.DebugLevel) - So(utils.Build(), ShouldBeNil) - }) -} - func startNodes() { // wait for ports to be available var err error @@ -80,7 +73,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./observation/node_0/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-observer/leader.cover.out"), }, - "leader", testWorkingDir, logDir, false, + "leader", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -115,7 +108,7 @@ func startNodes() { 4120, 4121, 4122, - }, time.Millisecond*200) + }, time.Second) if err != nil { log.Fatalf("wait for port ready timeout: %v", err) } @@ -233,11 +226,12 @@ func TestFullProcess(t *testing.T) { log.SetLevel(log.DebugLevel) Convey("test full process", t, func() { + var err error startNodes() defer stopNodes() + time.Sleep(10 * time.Second) - var err error err = client.Init(FJ(testWorkingDir, "./observation/node_c/config.yaml"), []byte("")) So(err, ShouldBeNil) diff --git a/cmd/cqld/bench_test.go b/cmd/cqld/bench_test.go index e3a0dd453..0ead03fe0 100644 --- a/cmd/cqld/bench_test.go +++ b/cmd/cqld/bench_test.go @@ -32,7 +32,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" - . "github.com/smartystreets/goconvey/convey" ) var ( @@ -43,13 +42,6 @@ var ( var FJ = filepath.Join -func TestBuild(t *testing.T) { - Convey("build", t, func() { - log.SetLevel(log.DebugLevel) - So(utils.Build(), ShouldBeNil) - }) -} - func start3BPs() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) defer cancel() @@ -97,7 +89,7 @@ func TestStartBP_CallRPC(t *testing.T) { 2122, 2121, 2120, - }, time.Millisecond*200) + }, time.Second) if err != nil { log.Fatalf("wait for port ready timeout: %v", err) } diff --git a/cmd/cqld/bootstrap.go b/cmd/cqld/bootstrap.go index 9a62c7edb..e885e5d3a 100644 --- a/cmd/cqld/bootstrap.go +++ b/cmd/cqld/bootstrap.go @@ -157,7 +157,7 @@ func runNode(nodeID proto.NodeID, listenAddr string) (err error) { peers, nodeID, 2*time.Second, - 100*time.Millisecond, + 900*time.Millisecond, ) chain, err := bp.NewChain(chainConfig) if err != nil { @@ -242,38 +242,6 @@ func initDBService(kvServer *KayakKVServer, metricService *metric.CollectServer) return } -//FIXME(auxten): clean up ugly periodicPingBlockProducer -func periodicPingBlockProducer() { - var localNodeID proto.NodeID - var err error - - // get local node id - if localNodeID, err = kms.GetLocalNodeID(); err != nil { - return - } - - // get local node info - var localNodeInfo *proto.Node - if localNodeInfo, err = kms.GetNodeInfo(localNodeID); err != nil { - return - } - - log.WithField("node", localNodeInfo).Debug("construct local node info") - - go func() { - for { - time.Sleep(time.Second) - - // send ping requests to block producer - bpNodeIDs := route.GetBPs() - - for _, bpNodeID := range bpNodeIDs { - rpc.PingBP(localNodeInfo, bpNodeID) - } - } - }() -} - func loadGenesis() *types.Block { genesisInfo := conf.GConf.BP.BPGenesis log.WithField("config", genesisInfo).Info("load genesis config") diff --git a/conf/config.go b/conf/config.go index 29ae8f1da..59e4a8e0c 100644 --- a/conf/config.go +++ b/conf/config.go @@ -177,5 +177,14 @@ func LoadConfig(configPath string) (config *Config, err error) { if config.Miner != nil && !path.IsAbs(config.Miner.RootDir) { config.Miner.RootDir = path.Join(configDir, config.Miner.RootDir) } + /* + The `go test -race` makes BP catch up block too slow, so let's make + genesis block just one day ago in test mode + */ + if config.IsTestMode { + if config.BP != nil { + config.BP.BPGenesis.Timestamp = time.Now().AddDate(0, 0, -1) + } + } return } diff --git a/utils/log/entrylogwrapper.go b/utils/log/entrylogwrapper.go new file mode 100644 index 000000000..125c05b74 --- /dev/null +++ b/utils/log/entrylogwrapper.go @@ -0,0 +1,159 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package log + +import ( + "time" + + "github.com/sirupsen/logrus" +) + +type Entry logrus.Entry + +func NewEntry(logger *Logger) *Entry { + return &Entry{ + Logger: (*logrus.Logger)(logger), + // Default is five fields, give a little extra room + Data: make(logrus.Fields, 5), + } +} + +// Returns the string representation from the reader and ultimately the +// formatter. +func (entry *Entry) String() (string, error) { + return (*logrus.Entry)(entry).String() +} + +// Add an error as single field (using the key defined in ErrorKey) to the Entry. +func (entry *Entry) WithError(err error) *Entry { + return (*Entry)((*logrus.Entry)(entry).WithError(err)) +} + +// Add a single field to the Entry. +func (entry *Entry) WithField(key string, value interface{}) *Entry { + return (*Entry)((*logrus.Entry)(entry).WithField(key, value)) +} + +// Add a map of fields to the Entry. +func (entry *Entry) WithFields(fields Fields) *Entry { + return (*Entry)((*logrus.Entry)(entry).WithFields((logrus.Fields)(fields))) +} + +// Overrides the time of the Entry. +func (entry *Entry) WithTime(t time.Time) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t} +} + +func (entry *Entry) Debug(args ...interface{}) { + (*logrus.Entry)(entry).Debug(args...) +} + +func (entry *Entry) Print(args ...interface{}) { + (*logrus.Entry)(entry).Print(args...) +} + +func (entry *Entry) Info(args ...interface{}) { + (*logrus.Entry)(entry).Info(args...) +} + +func (entry *Entry) Warn(args ...interface{}) { + (*logrus.Entry)(entry).Warn(args...) +} + +func (entry *Entry) Warning(args ...interface{}) { + (*logrus.Entry)(entry).Warning(args...) +} + +func (entry *Entry) Error(args ...interface{}) { + (*logrus.Entry)(entry).Error(args...) +} + +func (entry *Entry) Fatal(args ...interface{}) { + (*logrus.Entry)(entry).Fatal(args...) +} + +func (entry *Entry) Panic(args ...interface{}) { + (*logrus.Entry)(entry).Panic(args...) +} + +// Entry Printf family functions + +func (entry *Entry) Debugf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Debugf(format, args...) +} + +func (entry *Entry) Infof(format string, args ...interface{}) { + (*logrus.Entry)(entry).Infof(format, args...) +} + +func (entry *Entry) Printf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Printf(format, args...) +} + +func (entry *Entry) Warnf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Warnf(format, args...) +} + +func (entry *Entry) Warningf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Warningf(format, args...) +} + +func (entry *Entry) Errorf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Errorf(format, args...) +} + +func (entry *Entry) Fatalf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Fatalf(format, args...) +} + +func (entry *Entry) Panicf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Panicf(format, args...) +} + +// Entry Println family functions + +func (entry *Entry) Debugln(args ...interface{}) { + (*logrus.Entry)(entry).Debugln(args...) +} + +func (entry *Entry) Infoln(args ...interface{}) { + (*logrus.Entry)(entry).Infoln(args...) +} + +func (entry *Entry) Println(args ...interface{}) { + (*logrus.Entry)(entry).Println(args...) +} + +func (entry *Entry) Warnln(args ...interface{}) { + (*logrus.Entry)(entry).Warnln(args...) +} + +func (entry *Entry) Warningln(args ...interface{}) { + (*logrus.Entry)(entry).Warningln(args...) +} + +func (entry *Entry) Errorln(args ...interface{}) { + (*logrus.Entry)(entry).Errorln(args...) +} + +func (entry *Entry) Fatalln(args ...interface{}) { + (*logrus.Entry)(entry).Fatalln(args...) +} + +func (entry *Entry) Panicln(args ...interface{}) { + (*logrus.Entry)(entry).Panicln(args...) +} diff --git a/utils/log/logwrapper.go b/utils/log/logwrapper.go index 681a51f9c..3c32421f5 100644 --- a/utils/log/logwrapper.go +++ b/utils/log/logwrapper.go @@ -22,6 +22,7 @@ import ( "path/filepath" "runtime" "strings" + "time" "github.com/sirupsen/logrus" ) @@ -59,11 +60,28 @@ type Logger logrus.Logger type Fields logrus.Fields // CallerHook defines caller awareness hook for logrus. -type CallerHook struct{} +type CallerHook struct { + StackLevels []logrus.Level +} + +// NewCallerHook creates new CallerHook +func NewCallerHook(stackLevels []logrus.Level) *CallerHook { + return &CallerHook{ + StackLevels: stackLevels, + } +} + +// StandardCallerHook is a convenience initializer for LogrusStackHook{} with +// default args. +func StandardCallerHook() *CallerHook { + return NewCallerHook( + []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}, + ) +} // Fire defines hook event handler. func (hook *CallerHook) Fire(entry *logrus.Entry) error { - funcDesc, caller := hook.caller() + funcDesc, caller := hook.caller(entry) fields := strings.SplitN(funcDesc, ".", 2) if len(fields) > 0 { level, ok := PkgDebugLogFilter[fields[0]] @@ -90,23 +108,32 @@ func (hook *CallerHook) Levels() []logrus.Level { } } -func (hook *CallerHook) caller() (relFuncName, caller string) { - var ( - file = "unknown" - line = 0 - funcName = "unknown" - ) - pcs := make([]uintptr, 10) - if runtime.Callers(7, pcs) > 0 { - frames := runtime.CallersFrames(pcs) +func (hook *CallerHook) caller(entry *logrus.Entry) (relFuncName, caller string) { + var skipFrames int + if len(entry.Data) == 0 { + // When WithField(s) is not used, we have 8 logrus frames to skip. + skipFrames = 8 + } else { + // When WithField(s) is used, we have 6 logrus frames to skip. + skipFrames = 6 + } + + pcs := make([]uintptr, 12) + stacks := make([]runtime.Frame, 0, 12) + if runtime.Callers(skipFrames, pcs) > 0 { + var foundCaller bool + _frames := runtime.CallersFrames(pcs) for { - f, more := frames.Next() - if strings.HasSuffix(f.File, "logwrapper.go") && more { - f, _ = frames.Next() - file = f.File - line = f.Line - funcName = f.Function - break + f, more := _frames.Next() + //fmt.Printf("%s:%d %s\n", f.File, f.Line, f.Function) + if !foundCaller && strings.HasSuffix(f.File, "logwrapper.go") && more { + f, _ = _frames.Next() + relFuncName = strings.TrimPrefix(f.Function, "github.com/CovenantSQL/CovenantSQL/") + caller = fmt.Sprintf("%s:%d %s", filepath.Base(f.File), f.Line, relFuncName) + foundCaller = true + } + if foundCaller { + stacks = append(stacks, f) } if !more { break @@ -114,13 +141,28 @@ func (hook *CallerHook) caller() (relFuncName, caller string) { } } - relFuncName = strings.TrimPrefix(funcName, "github.com/CovenantSQL/CovenantSQL/") - funcLocation := fmt.Sprintf("%s:%d %s", filepath.Base(file), line, relFuncName) - return relFuncName, funcLocation + if len(stacks) > 0 { + for _, level := range hook.StackLevels { + if entry.Level == level { + stacksStr := make([]string, 0, len(stacks)) + for i, s := range stacks { + if s.Line > 0 { + fName := strings.TrimPrefix(s.Function, "github.com/CovenantSQL/CovenantSQL/") + stackStr := fmt.Sprintf("#%d %s@%s:%d ", i, fName, filepath.Base(s.File), s.Line) + stacksStr = append(stacksStr, stackStr) + } + } + entry.Data["stack"] = stacksStr + break + } + } + } + + return relFuncName, caller } func init() { - AddHook(&CallerHook{}) + AddHook(StandardCallerHook()) } //var ( @@ -159,8 +201,8 @@ func AddHook(hook logrus.Hook) { } // WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. -func WithError(err error) *logrus.Entry { - return logrus.WithField(logrus.ErrorKey, err) +func WithError(err error) *Entry { + return WithField(logrus.ErrorKey, err) } // WithField creates an entry from the standard logger and adds a field to @@ -168,8 +210,8 @@ func WithError(err error) *logrus.Entry { // // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal // or Panic on the Entry it returns. -func WithField(key string, value interface{}) *logrus.Entry { - return logrus.WithField(key, value) +func WithField(key string, value interface{}) *Entry { + return (*Entry)(logrus.WithField(key, value)) } // WithFields creates an entry from the standard logger and adds multiple @@ -178,8 +220,12 @@ func WithField(key string, value interface{}) *logrus.Entry { // // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal // or Panic on the Entry it returns. -func WithFields(fields Fields) *logrus.Entry { - return logrus.WithFields(logrus.Fields(fields)) +func WithFields(fields Fields) *Entry { + return (*Entry)(logrus.WithFields(logrus.Fields(fields))) +} + +func WithTime(t time.Time) *Entry { + return (*Entry)(logrus.WithTime(t)) } // Debug logs a message at level Debug on the standard logger. diff --git a/utils/log/logwrapper_test.go b/utils/log/logwrapper_test.go index 5edd00c1b..acc6dfc0d 100644 --- a/utils/log/logwrapper_test.go +++ b/utils/log/logwrapper_test.go @@ -19,6 +19,9 @@ package log import ( "fmt" "testing" + "time" + + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -78,3 +81,76 @@ func TestStandardLogger(t *testing.T) { Panic("Panic") } + +func call0() { + call1() +} + +func call1() { + call2() +} + +func call2() { + WithField("k", "v").Error("Error") + Error("call2 error") +} + +func TestWithField(t *testing.T) { + SetLevel(DebugLevel) + if GetLevel() != DebugLevel { + t.Fail() + } + + call0() + + f := new(Fields) + WithError(errors.New("new")).WithFields(*f).WithTime(time.Now()).Debug("Debug") + + WithFields(*f).Debug("Debug") + WithTime(time.Now()).WithError(errors.New("new")).Debug("Debug") + NewEntry(StandardLogger()).WithTime(time.Now()).String() + + WithField("k", "v").Debug("Debug") + WithField("k", "v").Debugln("Debugln") + WithField("k", "v").Debugf("Debugf %d", 1) + WithField("k", "v").Print("Print") + WithField("k", "v").Println("Println") + WithField("k", "v").Printf("Printf %d", 1) + WithField("k", "v").Info("Info") + WithField("k", "v").Infoln("Infoln") + WithField("k", "v").Infof("Infof %d", 1) + WithField("k", "v").Warning("Warning") + WithField("k", "v").Warningln("Warningln") + WithField("k", "v").Warningf("Warningf %d", 1) + WithField("k", "v").Warn("Warn") + WithField("k", "v").Warnln("Warnln") + WithField("k", "v").Warnln("Warnln") + WithField("k", "v").Warnf("Warnf %d", 1) + WithField("k", "v").Error("Error") + WithField("k", "v").Errorln("Errorln") + WithField("k", "v").Errorf("Errorf %d", 1) + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + n := NilFormatter{} + a, b := n.Format(&logrus.Entry{}) + if a != nil || b != nil { + t.Fail() + } + }() + WithField("k", "v").Panicf("Panicf %d", 1) + }() + WithField("k", "v").Panicln("Panicln") + }() + + WithField("k", "v").Panic("Panic") +} diff --git a/utils/net.go b/utils/net.go index 8648252ae..40c6d7a48 100644 --- a/utils/net.go +++ b/utils/net.go @@ -24,6 +24,8 @@ import ( "net" "sync" "time" + + "github.com/CovenantSQL/CovenantSQL/utils/log" ) var ( @@ -34,9 +36,10 @@ var ( allocateLock sync.Mutex ) -func testPortConnectable(addr string) bool { - conn, err := net.Dial("tcp", addr) +func testPortConnectable(addr string, timeout time.Duration) bool { + conn, err := net.DialTimeout("tcp", addr, timeout) if err != nil { + log.Infof("test dial to %s failed", addr) return false } else { conn.Close() @@ -72,7 +75,7 @@ func WaitToConnect(ctx context.Context, bindAddr string, ports []int, interval t case <-time.After(interval): for _, port := range ports { addr := net.JoinHostPort(bindAddr, fmt.Sprint(port)) - if !testPortConnectable(addr) { + if !testPortConnectable(addr, 100*time.Millisecond) { goto continueCheckC } }