Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ Stack Trace:
Command: commandStr,
OperatingSystem: runtime.GOOS,
DbrVersion: dbr.RuntimeVersion(ctx),
InteractiveMode: cmdio.GetInteractiveMode(ctx),
ExecutionTimeMs: time.Since(startTime).Milliseconds(),
ExitCode: int64(exitCode),
})
Expand Down
20 changes: 20 additions & 0 deletions libs/cmdio/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,23 @@ func detectGitBash(ctx context.Context) bool {

return false
}

// Interactive mode constants for telemetry.
const (
InteractiveModeFull = "full" // Both interactive output and prompts supported
InteractiveModeOutputOnly = "output_only" // Interactive output only, no prompts (stdin not TTY or Git Bash)
InteractiveModeNone = "none" // Non-interactive (CI, cron, stderr redirected)
)

// InteractiveMode returns the interactive mode based on terminal capabilities.
// Returns one of: "full", "output_only", or "none".
func (c Capabilities) InteractiveMode() string {
// SupportsPrompt() implies SupportsInteractive() (it's a stricter check).
if c.SupportsPrompt() {
return InteractiveModeFull
}
Comment on lines +81 to +83
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SupportsPrompt requires SupportsInteractive as well, so thats why we can do the logic this way

if c.SupportsInteractive() {
return InteractiveModeOutputOnly
}
return InteractiveModeNone
}
75 changes: 75 additions & 0 deletions libs/cmdio/capabilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,81 @@ func TestDetectGitBash(t *testing.T) {
assert.True(t, detectGitBash(ctx))
}

func TestCapabilities_InteractiveMode(t *testing.T) {
tests := []struct {
name string
caps Capabilities
expected string
}{
{
name: "full interactive - all TTYs, color, no Git Bash",
caps: Capabilities{
stdinIsTTY: true,
stderrIsTTY: true,
color: true,
isGitBash: false,
},
expected: InteractiveModeFull,
},
{
name: "output only - stdin not TTY",
caps: Capabilities{
stdinIsTTY: false,
stderrIsTTY: true,
color: true,
isGitBash: false,
},
expected: InteractiveModeOutputOnly,
},
{
name: "output only - Git Bash",
caps: Capabilities{
stdinIsTTY: true,
stderrIsTTY: true,
color: true,
isGitBash: true,
},
expected: InteractiveModeOutputOnly,
},
{
name: "none - stderr not TTY",
caps: Capabilities{
stdinIsTTY: true,
stderrIsTTY: false,
color: true,
isGitBash: false,
},
expected: InteractiveModeNone,
},
{
name: "none - NO_COLOR set",
caps: Capabilities{
stdinIsTTY: true,
stderrIsTTY: true,
color: false,
isGitBash: false,
},
expected: InteractiveModeNone,
},
{
name: "none - no TTY support at all",
caps: Capabilities{
stdinIsTTY: false,
stderrIsTTY: false,
color: false,
isGitBash: false,
},
expected: InteractiveModeNone,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, tt.caps.InteractiveMode())
})
}
}

func TestCapabilities_SupportsColor(t *testing.T) {
tests := []struct {
name string
Expand Down
11 changes: 11 additions & 0 deletions libs/cmdio/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ func SupportsColor(ctx context.Context, w io.Writer) bool {
return c.capabilities.SupportsColor(w)
}

// GetInteractiveMode returns the interactive mode based on terminal capabilities.
// Returns one of: "full", "output_only", or "none".
// Returns empty string if cmdio is not initialized in the context.
func GetInteractiveMode(ctx context.Context) string {
c, ok := ctx.Value(cmdIOKey).(*cmdIO)
if !ok {
return ""
}
return c.capabilities.InteractiveMode()
}

type Tuple struct{ Name, Id string }

func (c *cmdIO) Select(items []Tuple, label string) (id string, err error) {
Expand Down
6 changes: 6 additions & 0 deletions libs/telemetry/protos/databricks_cli_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ type ExecutionContext struct {
// If true, the CLI is being run from a Databricks notebook / cluster web terminal.
FromWebTerminal bool `json:"from_web_terminal,omitempty"`

// Interactive mode of the terminal. Possible values:
// - "full": Both interactive output (spinners, colors) and prompts are supported
// - "output_only": Interactive output is supported, but prompts are not (stdin not TTY or Git Bash)
// - "none": Non-interactive environment (CI, cron, stderr redirected)
InteractiveMode string `json:"interactive_mode,omitempty"`

// Time taken for the CLI command to execute.
// We want to serialize the zero value as well so the omitempty tag is not set.
ExecutionTimeMs int64 `json:"execution_time_ms"`
Expand Down
Loading