github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/cmd/br/cmd.go (about) 1 // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. 2 3 package main 4 5 import ( 6 "context" 7 "fmt" 8 "os" 9 "path/filepath" 10 "sync" 11 "sync/atomic" 12 "time" 13 14 "github.com/pingcap/errors" 15 "github.com/pingcap/log" 16 tidbutils "github.com/pingcap/tidb-tools/pkg/utils" 17 "github.com/pingcap/tidb/util/logutil" 18 "github.com/spf13/cobra" 19 20 "github.com/pingcap/br/pkg/gluetidb" 21 "github.com/pingcap/br/pkg/redact" 22 "github.com/pingcap/br/pkg/summary" 23 "github.com/pingcap/br/pkg/task" 24 "github.com/pingcap/br/pkg/utils" 25 "github.com/pingcap/br/pkg/version/build" 26 ) 27 28 var ( 29 initOnce = sync.Once{} 30 defaultContext context.Context 31 hasLogFile uint64 32 tidbGlue = gluetidb.New() 33 envLogToTermKey = "BR_LOG_TO_TERM" 34 35 filterOutSysAndMemTables = []string{ 36 "*.*", 37 fmt.Sprintf("!%s.*", utils.TemporaryDBName("*")), 38 "!mysql.*", 39 "!sys.*", 40 "!INFORMATION_SCHEMA.*", 41 "!PERFORMANCE_SCHEMA.*", 42 "!METRICS_SCHEMA.*", 43 "!INSPECTION_SCHEMA.*", 44 } 45 acceptAllTables = []string{ 46 "*.*", 47 } 48 ) 49 50 const ( 51 // FlagLogLevel is the name of log-level flag. 52 FlagLogLevel = "log-level" 53 // FlagLogFile is the name of log-file flag. 54 FlagLogFile = "log-file" 55 // FlagLogFormat is the name of log-format flag. 56 FlagLogFormat = "log-format" 57 // FlagStatusAddr is the name of status-addr flag. 58 FlagStatusAddr = "status-addr" 59 // FlagSlowLogFile is the name of slow-log-file flag. 60 FlagSlowLogFile = "slow-log-file" 61 // FlagRedactLog is whether to redact sensitive information in log, already deprecated by FlagRedactInfoLog 62 FlagRedactLog = "redact-log" 63 // FlagRedactInfoLog is whether to redact sensitive information in log. 64 FlagRedactInfoLog = "redact-info-log" 65 66 flagVersion = "version" 67 flagVersionShort = "V" 68 ) 69 70 func timestampLogFileName() string { 71 return filepath.Join(os.TempDir(), time.Now().Format("br.log.2006-01-02T15.04.05Z0700")) 72 } 73 74 // AddFlags adds flags to the given cmd. 75 func AddFlags(cmd *cobra.Command) { 76 cmd.Version = build.Info() 77 cmd.Flags().BoolP(flagVersion, flagVersionShort, false, "Display version information about BR") 78 cmd.SetVersionTemplate("{{printf \"%s\" .Version}}\n") 79 80 cmd.PersistentFlags().StringP(FlagLogLevel, "L", "info", 81 "Set the log level") 82 cmd.PersistentFlags().String(FlagLogFile, timestampLogFileName(), 83 "Set the log file path. If not set, logs will output to temp file") 84 cmd.PersistentFlags().String(FlagLogFormat, "text", 85 "Set the log format") 86 cmd.PersistentFlags().Bool(FlagRedactLog, false, 87 "Set whether to redact sensitive info in log, already deprecated by --redact-info-log") 88 cmd.PersistentFlags().Bool(FlagRedactInfoLog, false, 89 "Set whether to redact sensitive info in log") 90 cmd.PersistentFlags().String(FlagStatusAddr, "", 91 "Set the HTTP listening address for the status report service. Set to empty string to disable") 92 task.DefineCommonFlags(cmd.PersistentFlags()) 93 94 cmd.PersistentFlags().StringP(FlagSlowLogFile, "", "", 95 "Set the slow log file path. If not set, discard slow logs") 96 _ = cmd.PersistentFlags().MarkHidden(FlagSlowLogFile) 97 _ = cmd.PersistentFlags().MarkHidden(FlagRedactLog) 98 } 99 100 // Init initializes BR cli. 101 func Init(cmd *cobra.Command) (err error) { 102 initOnce.Do(func() { 103 slowLogFilename, e := cmd.Flags().GetString(FlagSlowLogFile) 104 if e != nil { 105 err = e 106 return 107 } 108 tidbLogCfg := logutil.LogConfig{} 109 if len(slowLogFilename) != 0 { 110 tidbLogCfg.SlowQueryFile = slowLogFilename 111 // Just for special grpc log file, 112 // otherwise the info will be print in stdout... 113 tidbLogCfg.File.Filename = timestampLogFileName() 114 } else { 115 // Disable annoying TiDB Log. 116 // TODO: some error logs outputs randomly, we need to fix them in TiDB. 117 tidbLogCfg.Level = "fatal" 118 } 119 e = logutil.InitLogger(&tidbLogCfg) 120 if e != nil { 121 err = e 122 return 123 } 124 // Initialize the logger. 125 conf := new(log.Config) 126 conf.Level, err = cmd.Flags().GetString(FlagLogLevel) 127 if err != nil { 128 return 129 } 130 conf.File.Filename, err = cmd.Flags().GetString(FlagLogFile) 131 if err != nil { 132 return 133 } 134 conf.Format, err = cmd.Flags().GetString(FlagLogFormat) 135 if err != nil { 136 return 137 } 138 _, outputLogToTerm := os.LookupEnv(envLogToTermKey) 139 if outputLogToTerm { 140 // Log to term if env `BR_LOG_TO_TERM` is set. 141 conf.File.Filename = "" 142 } 143 if len(conf.File.Filename) != 0 { 144 atomic.StoreUint64(&hasLogFile, 1) 145 summary.InitCollector(true) 146 // cmd.PrintErr prints to stderr, but PrintErrf prints to stdout. 147 cmd.PrintErr(fmt.Sprintf("Detail BR log in %s \n", conf.File.Filename)) 148 } 149 lg, p, e := log.InitLogger(conf) 150 if e != nil { 151 err = e 152 return 153 } 154 log.ReplaceGlobals(lg, p) 155 156 redactLog, e := cmd.Flags().GetBool(FlagRedactLog) 157 if e != nil { 158 err = e 159 return 160 } 161 redactInfoLog, e := cmd.Flags().GetBool(FlagRedactInfoLog) 162 if e != nil { 163 err = e 164 return 165 } 166 redact.InitRedact(redactLog || redactInfoLog) 167 err = startPProf(cmd) 168 }) 169 return errors.Trace(err) 170 } 171 172 func startPProf(cmd *cobra.Command) error { 173 // Initialize the pprof server. 174 statusAddr, err := cmd.Flags().GetString(FlagStatusAddr) 175 if err != nil { 176 return errors.Trace(err) 177 } 178 ca, cert, key, err := task.ParseTLSTripleFromFlags(cmd.Flags()) 179 if err != nil { 180 return errors.Trace(err) 181 } 182 // Host isn't used here. 183 tls, err := tidbutils.NewTLS(ca, cert, key, "localhost", nil) 184 if err != nil { 185 return errors.Trace(err) 186 } 187 188 if statusAddr != "" { 189 return utils.StartPProfListener(statusAddr, tls) 190 } 191 utils.StartDynamicPProfListener(tls) 192 return nil 193 } 194 195 // HasLogFile returns whether we set a log file. 196 func HasLogFile() bool { 197 return atomic.LoadUint64(&hasLogFile) != uint64(0) 198 } 199 200 // SetDefaultContext sets the default context for command line usage. 201 func SetDefaultContext(ctx context.Context) { 202 defaultContext = ctx 203 } 204 205 // GetDefaultContext returns the default context for command line usage. 206 func GetDefaultContext() context.Context { 207 return defaultContext 208 }