package root import ( "context" "fmt" "log/slog" "os" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/flags" "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/log/handler" "github.com/spf13/cobra" ) const ( envLogFile = "DATABRICKS_LOG_FILE" envLogLevel = "DATABRICKS_LOG_LEVEL" envLogFormat = "DATABRICKS_LOG_FORMAT" ) type logFlags struct { file flags.LogFileFlag level flags.LogLevelFlag output flags.Output debug bool } func (f *logFlags) makeLogHandler(opts slog.HandlerOptions) (slog.Handler, error) { switch f.output { case flags.OutputJSON: return slog.NewJSONHandler(f.file.Writer(), &opts), nil case flags.OutputText: w := f.file.Writer() return handler.NewFriendlyHandler(w, &handler.Options{ Color: cmdio.IsTTY(w), Level: opts.Level, ReplaceAttr: opts.ReplaceAttr, }), nil default: return nil, fmt.Errorf("invalid log output mode: %s", f.output) } } func (f *logFlags) initializeContext(ctx context.Context) (context.Context, error) { if f.debug { f.level.Set("debug") } opts := slog.HandlerOptions{} opts.Level = f.level.Level() opts.AddSource = true opts.ReplaceAttr = log.ReplaceAttrFunctions{ log.ReplaceLevelAttr, log.ReplaceSourceAttr, }.ReplaceAttr // Open the underlying log file if the user configured an actual file to log to. err := f.file.Open() if err != nil { return nil, err } handler, err := f.makeLogHandler(opts) if err != nil { return nil, err } slog.SetDefault(slog.New(handler).With(slog.Int("pid", os.Getpid()))) return log.NewContext(ctx, slog.Default()), nil } func initLogFlags(cmd *cobra.Command) *logFlags { f := logFlags{ file: flags.NewLogFileFlag(), level: flags.NewLogLevelFlag(), output: flags.OutputText, } // Configure defaults from environment, if applicable. // If the provided value is invalid it is ignored. if v, ok := env.Lookup(cmd.Context(), envLogFile); ok { f.file.Set(v) } if v, ok := env.Lookup(cmd.Context(), envLogLevel); ok { f.level.Set(v) } if v, ok := env.Lookup(cmd.Context(), envLogFormat); ok { f.output.Set(v) } flags := cmd.PersistentFlags() flags.BoolVar(&f.debug, "debug", false, "enable debug logging") flags.Var(&f.file, "log-file", "file to write logs to") flags.Var(&f.level, "log-level", "log level") flags.Var(&f.output, "log-format", "log output format (text or json)") // mark fine-grained flags hidden from global --help flags.MarkHidden("log-file") flags.MarkHidden("log-level") flags.MarkHidden("log-format") cmd.RegisterFlagCompletionFunc("log-file", f.file.Complete) cmd.RegisterFlagCompletionFunc("log-level", f.level.Complete) cmd.RegisterFlagCompletionFunc("log-format", f.output.Complete) return &f }