-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
41a21af
commit 9012c4c
Showing
19 changed files
with
620 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package telemetry_test | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"reflect" | ||
"testing" | ||
"time" | ||
|
||
"github.com/databricks/cli/integration/internal/acc" | ||
"github.com/databricks/cli/libs/telemetry" | ||
"github.com/databricks/cli/libs/telemetry/protos" | ||
"github.com/databricks/databricks-sdk-go/client" | ||
"github.com/google/uuid" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// Wrapper to capture the response from the API client since that's not directly | ||
// accessible from the logger. | ||
type apiClientWrapper struct { | ||
response *telemetry.ResponseBody | ||
apiClient *client.DatabricksClient | ||
} | ||
|
||
func (wrapper *apiClientWrapper) Do(ctx context.Context, method, path string, | ||
headers map[string]string, request, response any, | ||
visitors ...func(*http.Request) error, | ||
) error { | ||
err := wrapper.apiClient.Do(ctx, method, path, headers, request, response, visitors...) | ||
wrapper.response = response.(*telemetry.ResponseBody) | ||
return err | ||
} | ||
|
||
func TestTelemetryLogger(t *testing.T) { | ||
events := []telemetry.DatabricksCliLog{ | ||
{ | ||
CliTestEvent: &protos.CliTestEvent{ | ||
Name: protos.DummyCliEnumValue1, | ||
}, | ||
}, | ||
{ | ||
BundleInitEvent: &protos.BundleInitEvent{ | ||
Uuid: uuid.New().String(), | ||
TemplateName: "abc", | ||
TemplateEnumArgs: []protos.BundleInitTemplateEnumArg{ | ||
{ | ||
Key: "a", | ||
Value: "b", | ||
}, | ||
{ | ||
Key: "c", | ||
Value: "d", | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
assert.Equal(t, len(events), reflect.TypeOf(telemetry.DatabricksCliLog{}).NumField(), | ||
"Number of events should match the number of fields in DatabricksCliLog. Please add a new event to this test.") | ||
|
||
ctx, w := acc.WorkspaceTest(t) | ||
ctx = telemetry.WithDefaultLogger(ctx) | ||
|
||
// Extend the maximum wait time for the telemetry flush just for this test. | ||
oldV := telemetry.MaxAdditionalWaitTime | ||
telemetry.MaxAdditionalWaitTime = 1 * time.Hour | ||
t.Cleanup(func() { | ||
telemetry.MaxAdditionalWaitTime = oldV | ||
}) | ||
|
||
for _, event := range events { | ||
telemetry.Log(ctx, event) | ||
} | ||
|
||
apiClient, err := client.New(w.W.Config) | ||
require.NoError(t, err) | ||
|
||
// Flush the events. | ||
wrapper := &apiClientWrapper{ | ||
apiClient: apiClient, | ||
} | ||
telemetry.Flush(ctx, wrapper) | ||
|
||
// Assert that the events were logged. | ||
assert.Equal(t, telemetry.ResponseBody{ | ||
NumProtoSuccess: int64(len(events)), | ||
Errors: []telemetry.LogError{}, | ||
}, *wrapper.response) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package telemetry | ||
|
||
// RequestBody is the request body type bindings for the /telemetry-ext API endpoint. | ||
type RequestBody struct { | ||
UploadTime int64 `json:"uploadTime"` | ||
Items []string `json:"items"` | ||
ProtoLogs []string `json:"protoLogs"` | ||
} | ||
|
||
// ResponseBody is the response body type bindings for the /telemetry-ext API endpoint. | ||
type ResponseBody struct { | ||
Errors []LogError `json:"errors"` | ||
NumProtoSuccess int64 `json:"numProtoSuccess"` | ||
} | ||
|
||
type LogError struct { | ||
Message string `json:"message"` | ||
ErrorType string `json:"ErrorType"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package telemetry | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
) | ||
|
||
// Private type to store the telemetry logger in the context | ||
type telemetryLogger int | ||
|
||
// Key to store the telemetry logger in the context | ||
var telemetryLoggerKey telemetryLogger | ||
|
||
func WithDefaultLogger(ctx context.Context) context.Context { | ||
v := ctx.Value(telemetryLoggerKey) | ||
|
||
// If no logger is set in the context, set the default logger. | ||
if v == nil { | ||
nctx := context.WithValue(ctx, telemetryLoggerKey, &defaultLogger{}) | ||
return nctx | ||
} | ||
|
||
switch v.(type) { | ||
case *defaultLogger: | ||
panic(fmt.Errorf("default telemetry logger already set in the context: %T", v)) | ||
case *mockLogger: | ||
// Do nothing. Unit and integration tests set the mock logger in the context | ||
// to avoid making actual API calls. Thus WithDefaultLogger should silently | ||
// ignore the mock logger. | ||
default: | ||
panic(fmt.Errorf("unexpected telemetry logger type: %T", v)) | ||
} | ||
|
||
return ctx | ||
} | ||
|
||
// WithMockLogger sets a mock telemetry logger in the context. It overrides the | ||
// default logger if it is already set in the context. | ||
func WithMockLogger(ctx context.Context) context.Context { | ||
v := ctx.Value(telemetryLoggerKey) | ||
if v != nil { | ||
panic(fmt.Errorf("telemetry logger already set in the context: %T", v)) | ||
} | ||
|
||
return context.WithValue(ctx, telemetryLoggerKey, &mockLogger{}) | ||
} | ||
|
||
func fromContext(ctx context.Context) Logger { | ||
v := ctx.Value(telemetryLoggerKey) | ||
if v == nil { | ||
panic(fmt.Errorf("telemetry logger not found in the context")) | ||
} | ||
|
||
switch vv := v.(type) { | ||
case *defaultLogger: | ||
return vv | ||
case *mockLogger: | ||
return vv | ||
default: | ||
panic(fmt.Errorf("unexpected telemetry logger type: %T", v)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package telemetry | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestWithDefaultLogger(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
// No default logger set | ||
ctx1 := WithDefaultLogger(ctx) | ||
assert.Equal(t, &defaultLogger{}, ctx1.Value(telemetryLoggerKey)) | ||
|
||
// Default logger already set | ||
assert.PanicsWithError(t, "default telemetry logger already set in the context: *telemetry.defaultLogger", func() { | ||
WithDefaultLogger(ctx1) | ||
}) | ||
|
||
// Mock logger already set | ||
ctx2 := WithMockLogger(ctx) | ||
assert.NotPanics(t, func() { | ||
WithDefaultLogger(ctx2) | ||
}) | ||
|
||
// Unexpected logger type | ||
type foobar struct{} | ||
ctx3 := context.WithValue(ctx, telemetryLoggerKey, &foobar{}) | ||
assert.PanicsWithError(t, "unexpected telemetry logger type: *telemetry.foobar", func() { | ||
WithDefaultLogger(ctx3) | ||
}) | ||
} | ||
|
||
func TestWithMockLogger(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
// No logger set | ||
ctx1 := WithMockLogger(ctx) | ||
assert.Equal(t, &mockLogger{}, ctx1.Value(telemetryLoggerKey)) | ||
|
||
// Logger already set | ||
assert.PanicsWithError(t, "telemetry logger already set in the context: *telemetry.mockLogger", func() { | ||
WithMockLogger(ctx1) | ||
}) | ||
|
||
// Default logger already set | ||
ctx2 := WithDefaultLogger(ctx) | ||
assert.PanicsWithError(t, "telemetry logger already set in the context: *telemetry.defaultLogger", func() { | ||
WithMockLogger(ctx2) | ||
}) | ||
} | ||
|
||
func TestFromContext(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
// No logger set | ||
assert.PanicsWithError(t, "telemetry logger not found in the context", func() { | ||
fromContext(ctx) | ||
}) | ||
|
||
// Default logger set | ||
ctx1 := WithDefaultLogger(ctx) | ||
assert.Equal(t, &defaultLogger{}, fromContext(ctx1)) | ||
|
||
// Mock logger set | ||
ctx2 := WithMockLogger(ctx) | ||
assert.Equal(t, &mockLogger{}, fromContext(ctx2)) | ||
|
||
// Unexpected logger type | ||
type foobar struct{} | ||
ctx3 := context.WithValue(ctx, telemetryLoggerKey, &foobar{}) | ||
assert.PanicsWithError(t, "unexpected telemetry logger type: *telemetry.foobar", func() { | ||
fromContext(ctx3) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package telemetry | ||
|
||
import "github.com/databricks/cli/libs/telemetry/protos" | ||
|
||
// This corresponds to the FrontendLog lumberjack proto in universe. | ||
// FrontendLog is the top-level struct for any client-side logs at Databricks | ||
// regardless of whether they are generated from the CLI or the web UI. | ||
type FrontendLog struct { | ||
// A unique identifier for the log event generated from the CLI. | ||
FrontendLogEventID string `json:"frontend_log_event_id,omitempty"` | ||
|
||
Entry FrontendLogEntry `json:"entry,omitempty"` | ||
} | ||
|
||
type FrontendLogEntry struct { | ||
DatabricksCliLog DatabricksCliLog `json:"databricks_cli_log,omitempty"` | ||
} | ||
|
||
type DatabricksCliLog struct { | ||
CliTestEvent *protos.CliTestEvent `json:"cli_test_event,omitempty"` | ||
BundleInitEvent *protos.BundleInitEvent `json:"bundle_init_event,omitempty"` | ||
} |
Oops, something went wrong.