diff --git a/runsc/cli/main.go b/runsc/cli/main.go index 3aefb32f1..f71929c4b 100644 --- a/runsc/cli/main.go +++ b/runsc/cli/main.go @@ -147,8 +147,10 @@ func Main(version string) { // propagate it to child processes. refs.SetLeakMode(conf.ReferenceLeak) + subcommand := flag.CommandLine.Arg(0) + // Set up logging. - if conf.Debug { + if conf.Debug && specutils.IsDebugCommand(conf, subcommand) { log.SetLevel(log.Debug) } @@ -164,15 +166,13 @@ func Main(version string) { // case that does not occur. _ = time.Local.String() - subcommand := flag.CommandLine.Arg(0) - var e log.Emitter if *debugLogFD > -1 { f := os.NewFile(uintptr(*debugLogFD), "debug log file") e = newEmitter(conf.DebugLogFormat, f) - } else if conf.DebugLog != "" { + } else if len(conf.DebugLog) > 0 && specutils.IsDebugCommand(conf, subcommand) { f, err := specutils.DebugLogFile(conf.DebugLog, subcommand, "" /* name */) if err != nil { util.Fatalf("error opening debug log file in %q: %v", conf.DebugLog, err) diff --git a/runsc/config/config.go b/runsc/config/config.go index 5e11dcb91..d12168a7d 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -53,6 +53,11 @@ type Config struct { // DebugLog is the path to log debug information to, if not empty. DebugLog string `flag:"debug-log"` + // DebugCommand is a comma-separated list of commands to be debugged if + // --debug-log is also set. Empty means debug all. "!" negates the expression. + // E.g. "create,start" or "!boot,events". + DebugCommand string `flag:"debug-command"` + // PanicLog is the path to log GO's runtime messages, if not empty. PanicLog string `flag:"panic-log"` diff --git a/runsc/config/flags.go b/runsc/config/flags.go index 5fb611fe7..bbab6e51a 100644 --- a/runsc/config/flags.go +++ b/runsc/config/flags.go @@ -41,6 +41,7 @@ func RegisterFlags(flagSet *flag.FlagSet) { // Debugging flags. flagSet.String("debug-log", "", "additional location for logs. If it ends with '/', log files are created inside the directory with default names. The following variables are available: %TIMESTAMP%, %COMMAND%.") + flagSet.String("debug-command", "", `comma-separated list of commands to be debugged if --debug-log is also set. Empty means debug all. "!" negates the expression. E.g. "create,start" or "!boot,events"`) flagSet.String("panic-log", "", "file path where panic reports and other Go's runtime messages are written.") flagSet.String("coverage-report", "", "file path where Go coverage reports are written. Reports will only be generated if runsc is built with --collect_code_coverage and --instrumentation_filter Bazel flags.") flagSet.Bool("log-packets", false, "enable network packet logging.") diff --git a/runsc/container/container.go b/runsc/container/container.go index 97e6c11da..2aa598b0f 100644 --- a/runsc/container/container.go +++ b/runsc/container/container.go @@ -871,8 +871,10 @@ func (c *Container) createGoferProcess(spec *specs.Spec, conf *config.Config, bu test = t } } - if err := donations.DonateDebugLogFile("debug-log-fd", conf.DebugLog, "gofer", test); err != nil { - return nil, nil, err + if specutils.IsDebugCommand(conf, "gofer") { + if err := donations.DonateDebugLogFile("debug-log-fd", conf.DebugLog, "gofer", test); err != nil { + return nil, nil, err + } } } diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index f7156eac8..e721c2684 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -550,8 +550,10 @@ func (s *Sandbox) createSandboxProcess(conf *config.Config, args *Args, startSyn test = t } } - if err := donations.DonateDebugLogFile("debug-log-fd", conf.DebugLog, "boot", test); err != nil { - return err + if specutils.IsDebugCommand(conf, "boot") { + if err := donations.DonateDebugLogFile("debug-log-fd", conf.DebugLog, "boot", test); err != nil { + return err + } } if err := donations.DonateDebugLogFile("panic-log-fd", conf.PanicLog, "panic", test); err != nil { return err diff --git a/runsc/specutils/specutils.go b/runsc/specutils/specutils.go index 22bd192ce..2b0b9206a 100644 --- a/runsc/specutils/specutils.go +++ b/runsc/specutils/specutils.go @@ -412,6 +412,28 @@ func DebugLogFile(logPattern, command, test string) (*os.File, error) { return os.OpenFile(logPattern, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0664) } +// IsDebugCommand returns true if the command should be debugged or not, based +// on the current configuration. +func IsDebugCommand(conf *config.Config, command string) bool { + if len(conf.DebugCommand) == 0 { + // Debug everything by default. + return true + } + filter := conf.DebugCommand + rv := true + if filter[0] == '!' { + // Negate the match, e.g. !boot should log all, but "boot". + filter = filter[1:] + rv = false + } + for _, cmd := range strings.Split(filter, ",") { + if cmd == command { + return rv + } + } + return !rv +} + // SafeSetupAndMount creates the mount point and calls Mount with the given // flags. procPath is the path to procfs. If it is "", procfs is assumed to be // mounted at /proc.