add acceptance tests

This commit is contained in:
Shreyas Goenka 2025-03-05 15:57:41 +01:00
parent b3a479ce73
commit a2825ca89a
No known key found for this signature in database
GPG Key ID: 92A07DF49CCB0622
28 changed files with 512 additions and 12 deletions

View File

@ -0,0 +1,51 @@
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}

View File

@ -0,0 +1,56 @@
>>> [CLI] selftest send-telemetry --debug
HH:MM:SS Info: start pid=PID version=[DEV_VERSION] args="[CLI], selftest, send-telemetry, --debug"
HH:MM:SS Info: completed execution pid=PID exit_code=0
HH:MM:SS Debug: POST /telemetry-ext
> {
> "items": null,
> "protoLogs": [
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (210 more bytes)",
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (210 more bytes)"
> ],
> "uploadTime": "UNIX_TIME_MILLIS"
> }
< HTTP/1.1 501 Not Implemented
< {
< "error_code": "ERROR_CODE",
< "message": "Endpoint not implemented."
< } pid=PID sdk=true
HH:MM:SS Debug: non-retriable error: Endpoint not implemented. pid=PID sdk=true
HH:MM:SS Debug: Attempt 1 failed due to a server side error. Retrying status code: 501
pid=PID
HH:MM:SS Debug: POST /telemetry-ext
> {
> "items": null,
> "protoLogs": [
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (210 more bytes)",
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (210 more bytes)"
> ],
> "uploadTime": "UNIX_TIME_MILLIS"
> }
< HTTP/1.1 501 Not Implemented
< {
< "error_code": "ERROR_CODE",
< "message": "Endpoint not implemented."
< } pid=PID sdk=true
HH:MM:SS Debug: non-retriable error: Endpoint not implemented. pid=PID sdk=true
HH:MM:SS Debug: Attempt 2 failed due to a server side error. Retrying status code: 501
pid=PID
HH:MM:SS Debug: POST /telemetry-ext
> {
> "items": null,
> "protoLogs": [
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (210 more bytes)",
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (210 more bytes)"
> ],
> "uploadTime": "UNIX_TIME_MILLIS"
> }
< HTTP/1.1 501 Not Implemented
< {
< "error_code": "ERROR_CODE",
< "message": "Endpoint not implemented."
< } pid=PID sdk=true
HH:MM:SS Debug: non-retriable error: Endpoint not implemented. pid=PID sdk=true
HH:MM:SS Debug: Attempt 3 failed due to a server side error. Retrying status code: 501
pid=PID
HH:MM:SS Debug: failed to upload telemetry: failed to upload telemetry logs after three attempts pid=PID

View File

@ -0,0 +1 @@
trace $CLI selftest send-telemetry --debug

View File

@ -0,0 +1,17 @@
[[Server]]
Pattern = "POST /telemetry-ext"
Response.Body = '''
{
"error_code": "ERROR_CODE",
"message": "Endpoint not implemented."
}
'''
Response.StatusCode = 501
[[Repls]]
Old = "(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]"
New = "HH:MM:SS"
[[Repls]]
Old = "pid=[0-9]+"
New = "pid=PID"

View File

@ -0,0 +1,51 @@
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}

View File

@ -0,0 +1,2 @@
>>> [CLI] selftest send-telemetry

View File

@ -0,0 +1 @@
trace $CLI selftest send-telemetry

View File

@ -0,0 +1,9 @@
[[Server]]
Pattern = "POST /telemetry-ext"
Response.Body = '''
{
"error_code": "ERROR_CODE",
"message": "Endpoint not implemented."
}
'''
Response.StatusCode = 501

View File

@ -0,0 +1,51 @@
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\",\"execution_time_ms\":1},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\",\"execution_time_ms\":1},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\",\"execution_time_ms\":1},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\",\"execution_time_ms\":1},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\",\"execution_time_ms\":1},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\",\"execution_time_ms\":1},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}

View File

@ -0,0 +1,53 @@
>>> [CLI] selftest send-telemetry --debug
HH:MM:SS Info: start pid=PID version=[DEV_VERSION] args="[CLI], selftest, send-telemetry, --debug"
HH:MM:SS Info: completed execution pid=PID exit_code=0
HH:MM:SS Debug: POST /telemetry-ext
> {
> "items": null,
> "protoLogs": [
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (232 more bytes)",
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (232 more bytes)"
> ],
> "uploadTime": "UNIX_TIME_MILLIS"
> }
< HTTP/1.1 200 OK
< {
< "errors": null,
< "numProtoSuccess": 1
< } pid=PID sdk=true
HH:MM:SS Debug: Attempt 1 was a partial success. Number of logs uploaded: 1 out of 2
pid=PID
HH:MM:SS Debug: POST /telemetry-ext
> {
> "items": null,
> "protoLogs": [
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (232 more bytes)",
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (232 more bytes)"
> ],
> "uploadTime": "UNIX_TIME_MILLIS"
> }
< HTTP/1.1 200 OK
< {
< "errors": null,
< "numProtoSuccess": 1
< } pid=PID sdk=true
HH:MM:SS Debug: Attempt 2 was a partial success. Number of logs uploaded: 1 out of 2
pid=PID
HH:MM:SS Debug: POST /telemetry-ext
> {
> "items": null,
> "protoLogs": [
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (232 more bytes)",
> "{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"... (232 more bytes)"
> ],
> "uploadTime": "UNIX_TIME_MILLIS"
> }
< HTTP/1.1 200 OK
< {
< "errors": null,
< "numProtoSuccess": 1
< } pid=PID sdk=true
HH:MM:SS Debug: Attempt 3 was a partial success. Number of logs uploaded: 1 out of 2
pid=PID
HH:MM:SS Debug: failed to upload telemetry: failed to upload telemetry logs after three attempts pid=PID

View File

@ -0,0 +1 @@
trace $CLI selftest send-telemetry --debug

View File

@ -0,0 +1,17 @@
[[Server]]
Pattern = "POST /telemetry-ext"
Response.Body = '''
{
"errors": [],
"numProtoSuccess": 1
}
'''
[[Repls]]
Old = "(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]"
New = "HH:MM:SS"
[[Repls]]
Old = "pid=[0-9]+"
New = "pid=PID"

View File

@ -0,0 +1,51 @@
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}

View File

@ -0,0 +1,2 @@
>>> [CLI] selftest send-telemetry

View File

@ -0,0 +1 @@
trace $CLI selftest send-telemetry

View File

@ -0,0 +1,8 @@
[[Server]]
Pattern = "POST /telemetry-ext"
Response.Body = '''
{
"errors": [],
"numProtoSuccess": 1
}
'''

View File

@ -0,0 +1,2 @@
>>> [CLI] selftest send-telemetry

View File

@ -0,0 +1,3 @@
export DATABRICKS_CLI_DISABLE_TELEMETRY="true"
trace $CLI selftest send-telemetry

View File

@ -0,0 +1,17 @@
{
"headers": {
"Authorization": [
"Bearer [DATABRICKS_TOKEN]"
]
},
"method": "POST",
"path": "/telemetry-ext",
"body": {
"uploadTime": "UNIX_TIME_MILLIS",
"items": [],
"protoLogs": [
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE1\"}}}}",
"{\"frontend_log_event_id\":\"[UUID]\",\"entry\":{\"databricks_cli_log\":{\"execution_context\":{\"cmd_exec_id\":\"[UUID]\",\"version\":\"[DEV_VERSION]\",\"command\":\"selftest_send-telemetry\",\"operating_system\":\"[OS]\"},\"cli_test_event\":{\"name\":\"VALUE2\"}}}}"
]
}
}

View File

@ -0,0 +1,2 @@
>>> [CLI] selftest send-telemetry

View File

@ -0,0 +1 @@
trace $CLI selftest send-telemetry

View File

@ -0,0 +1,26 @@
IncludeRequestHeaders = ["Authorization"]
RecordRequests = true
Local = true
Cloud = false
[[Repls]]
Old = '17\d{11}'
New = '"UNIX_TIME_MILLIS"'
[[Repls]]
Old = 'darwin|linux|windows'
New = '[OS]'
[[Repls]]
Old = 'execution_time_ms\\\":\d{1,5},'
New = 'execution_time_ms\":\"SMALL_INT\",'
[[Server]]
Pattern = "POST /telemetry-ext"
Response.Body = '''
{
"errors": [],
"numProtoSuccess": 2
}
'''

View File

@ -6,13 +6,18 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"os" "os"
"runtime"
"runtime/debug" "runtime/debug"
"strings" "strings"
"time"
"github.com/databricks/cli/internal/build" "github.com/databricks/cli/internal/build"
"github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/dbr" "github.com/databricks/cli/libs/dbr"
"github.com/databricks/cli/libs/env"
"github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/log"
"github.com/databricks/cli/libs/telemetry"
"github.com/databricks/cli/libs/telemetry/protos"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -74,9 +79,6 @@ func New(ctx context.Context) *cobra.Command {
// get the context back // get the context back
ctx = cmd.Context() ctx = cmd.Context()
// Detect if the CLI is running on DBR and store this on the context.
ctx = dbr.DetectRuntime(ctx)
// Configure our user agent with the command that's about to be executed. // Configure our user agent with the command that's about to be executed.
ctx = withCommandInUserAgent(ctx, cmd) ctx = withCommandInUserAgent(ctx, cmd)
ctx = withCommandExecIdInUserAgent(ctx) ctx = withCommandExecIdInUserAgent(ctx)
@ -124,6 +126,14 @@ Stack Trace:
%s`, version, r, string(trace)) %s`, version, r, string(trace))
}() }()
// Configure a telemetry logger and store it in the context.
ctx = telemetry.WithNewLogger(ctx)
// Detect if the CLI is running on DBR and store this on the context.
ctx = dbr.DetectRuntime(ctx)
startTime := time.Now()
// Run the command // Run the command
cmd, err = cmd.ExecuteContextC(ctx) cmd, err = cmd.ExecuteContextC(ctx)
if err != nil && !errors.Is(err, ErrAlreadyPrinted) { if err != nil && !errors.Is(err, ErrAlreadyPrinted) {
@ -151,5 +161,38 @@ Stack Trace:
} }
} }
exitCode := 0
if err != nil {
exitCode = 1
}
uploadTelemetry(cmd.Context(), commandString(cmd), startTime, exitCode)
return err return err
} }
func uploadTelemetry(ctx context.Context, cmdStr string, startTime time.Time, exitCode int) {
// Return early if there are no logs to upload.
if !telemetry.HasLogs(ctx) {
return
}
// Telemetry is disabled. We don't upload logs.
if os.Getenv(telemetry.DisableEnvVar) != "" {
return
}
telemetry.SetExecutionContext(ctx, protos.ExecutionContext{
CmdExecID: cmdExecId,
Version: build.GetInfo().Version,
Command: cmdStr,
OperatingSystem: runtime.GOOS,
DbrVersion: env.Get(ctx, dbr.EnvVarName),
ExecutionTimeMs: time.Since(startTime).Milliseconds(),
ExitCode: int64(exitCode),
})
err := telemetry.Upload(ctx, ConfigUsed(ctx))
if err != nil {
log.Debugf(ctx, "failed to upload telemetry: %v", err)
}
}

View File

@ -7,8 +7,10 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
var cmdExecId = uuid.New().String()
func withCommandExecIdInUserAgent(ctx context.Context) context.Context { func withCommandExecIdInUserAgent(ctx context.Context) context.Context {
// A UUID that will allow us to correlate multiple API requests made by // A UUID that will allow us to correlate multiple API requests made by
// the same CLI invocation. // the same CLI invocation.
return useragent.InContext(ctx, "cmd-exec-id", uuid.New().String()) return useragent.InContext(ctx, "cmd-exec-id", cmdExecId)
} }

View File

@ -11,6 +11,7 @@ func New() *cobra.Command {
Hidden: true, Hidden: true,
} }
cmd.AddCommand(newSendTelemetry())
cmd.AddCommand(newPanic()) cmd.AddCommand(newPanic())
return cmd return cmd
} }

View File

@ -0,0 +1,29 @@
package selftest
import (
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/libs/telemetry"
"github.com/databricks/cli/libs/telemetry/protos"
"github.com/spf13/cobra"
)
func newSendTelemetry() *cobra.Command {
cmd := &cobra.Command{
Use: "send-telemetry",
Short: "log some test telemetry events",
PreRunE: root.MustWorkspaceClient,
}
cmd.RunE = func(cmd *cobra.Command, args []string) error {
for _, v := range []string{"VALUE1", "VALUE2"} {
telemetry.Log(cmd.Context(), protos.DatabricksCliLog{
CliTestEvent: &protos.CliTestEvent{
Name: protos.DummyCliEnum(v),
},
})
}
return nil
}
return cmd
}

View File

@ -11,6 +11,8 @@ import (
// Dereference [os.Stat] to allow mocking in tests. // Dereference [os.Stat] to allow mocking in tests.
var statFunc = os.Stat var statFunc = os.Stat
const EnvVarName = "DATABRICKS_RUNTIME_VERSION"
// detect returns true if the current process is running on a Databricks Runtime. // detect returns true if the current process is running on a Databricks Runtime.
// Its return value is meant to be cached in the context. // Its return value is meant to be cached in the context.
func detect(ctx context.Context) bool { func detect(ctx context.Context) bool {
@ -21,7 +23,7 @@ func detect(ctx context.Context) bool {
} }
// Databricks Runtime always has the DATABRICKS_RUNTIME_VERSION environment variable set. // Databricks Runtime always has the DATABRICKS_RUNTIME_VERSION environment variable set.
if value, ok := env.Lookup(ctx, "DATABRICKS_RUNTIME_VERSION"); !ok || value == "" { if value, ok := env.Lookup(ctx, EnvVarName); !ok || value == "" {
return false return false
} }

View File

@ -16,22 +16,22 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
// Environment variable to disable telemetry. If this is set to any value, telemetry
// will be disabled.
const DisableEnvVar = "DATABRICKS_CLI_DISABLE_TELEMETRY"
func Log(ctx context.Context, event protos.DatabricksCliLog) { func Log(ctx context.Context, event protos.DatabricksCliLog) {
fromContext(ctx).log(event) fromContext(ctx).log(event)
} }
func GetLogs(ctx context.Context) []protos.FrontendLog { func SetExecutionContext(ctx context.Context, ec protos.ExecutionContext) {
return fromContext(ctx).getLogs() fromContext(ctx).setExecutionContext(ec)
} }
func HasLogs(ctx context.Context) bool { func HasLogs(ctx context.Context) bool {
return len(fromContext(ctx).getLogs()) > 0 return len(fromContext(ctx).getLogs()) > 0
} }
func SetExecutionContext(ctx context.Context, ec protos.ExecutionContext) {
fromContext(ctx).setExecutionContext(ec)
}
type logger struct { type logger struct {
logs []protos.FrontendLog logs []protos.FrontendLog
} }
@ -63,7 +63,7 @@ func (l *logger) setExecutionContext(ec protos.ExecutionContext) {
func Upload(ctx context.Context, cfg *config.Config) error { func Upload(ctx context.Context, cfg *config.Config) error {
l := fromContext(ctx) l := fromContext(ctx)
if len(l.logs) == 0 { if len(l.logs) == 0 {
return nil return fmt.Errorf("no logs to upload")
} }
protoLogs := make([]string, len(l.logs)) protoLogs := make([]string, len(l.logs))