Skip to content

Commit 39565c8

Browse files
Track variable usage in telemetry (#2593)
## Why This gives us insight into usage patterns of variables by customers. Like how popular are lookup variables or complex variables overall compared to just default variables. Potential followup: track lookup variable usage per resource type. ## Tests Acceptance tests.
1 parent e590727 commit 39565c8

File tree

8 files changed

+177
-9
lines changed

8 files changed

+177
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
bundle:
2+
name: chicken
3+
4+
variables:
5+
v1:
6+
description: var 1
7+
default: 1
8+
9+
v2:
10+
description: var 2
11+
default: 2
12+
13+
v3:
14+
description: var 3
15+
default: 3
16+
17+
lv1:
18+
description: lookup var 1
19+
lookup:
20+
cluster: cluster_one
21+
22+
lv2:
23+
description: lookup var 2
24+
lookup:
25+
cluster: cluster_two
26+
27+
c1:
28+
description: complex 1
29+
type: complex
30+
default:
31+
a: 1
32+
b: 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
>>> [CLI] bundle deploy
3+
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/chicken/default/files...
4+
Deploying resources...
5+
Deployment complete!
6+
7+
>>> cat out.requests.txt
8+
{
9+
"bundle_uuid": "[UUID]",
10+
"deployment_id": "[UUID]",
11+
"resource_count": 0,
12+
"resource_job_count": 0,
13+
"resource_pipeline_count": 0,
14+
"resource_model_count": 0,
15+
"resource_experiment_count": 0,
16+
"resource_model_serving_endpoint_count": 0,
17+
"resource_registered_model_count": 0,
18+
"resource_quality_monitor_count": 0,
19+
"resource_schema_count": 0,
20+
"resource_volume_count": 0,
21+
"resource_cluster_count": 0,
22+
"resource_dashboard_count": 0,
23+
"resource_app_count": 0,
24+
"experimental": {
25+
"configuration_file_count": 1,
26+
"variable_count": 6,
27+
"complex_variable_count": 1,
28+
"lookup_variable_count": 2,
29+
"target_count": 1,
30+
"bool_values": [
31+
{
32+
"key": "python_wheel_wrapper_is_set",
33+
"value": false
34+
}
35+
],
36+
"bundle_mode": "TYPE_UNSPECIFIED",
37+
"workspace_artifact_path_type": "WORKSPACE_FILE_SYSTEM"
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trace $CLI bundle deploy
2+
3+
trace cat out.requests.txt | jq 'select(has("path") and .path == "/telemetry-ext") | .body.protoLogs.[] | fromjson | .entry.databricks_cli_log.bundle_deploy_event'
4+
5+
rm out.requests.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[[Server]]
2+
Pattern = "GET /api/2.1/clusters/list"
3+
Response.Body = '''
4+
{
5+
"clusters": [
6+
{
7+
"cluster_id": "cls-1",
8+
"cluster_name": "cluster_one"
9+
},
10+
{
11+
"cluster_id": "cls-2",
12+
"cluster_name": "cluster_two"
13+
}
14+
]
15+
}
16+
'''

acceptance/bundle/telemetry/deploy-whl-artifacts/output.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Deployment complete!
3232
"resource_app_count": 0,
3333
"experimental": {
3434
"configuration_file_count": 1,
35-
"variable_count": 0,
35+
"variable_count": 1,
3636
"complex_variable_count": 0,
3737
"lookup_variable_count": 0,
3838
"target_count": 2,
@@ -72,7 +72,7 @@ Deployment complete!
7272
"resource_app_count": 0,
7373
"experimental": {
7474
"configuration_file_count": 1,
75-
"variable_count": 0,
75+
"variable_count": 1,
7676
"complex_variable_count": 0,
7777
"lookup_variable_count": 0,
7878
"target_count": 2,

bundle/config/variable/variable.go

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package variable
22

33
import (
4-
"errors"
54
"fmt"
65
"reflect"
76
)
@@ -66,19 +65,25 @@ func (v *Variable) Set(val VariableValue) error {
6665
return fmt.Errorf("variable has already been assigned value: %s", v.Value)
6766
}
6867

69-
rv := reflect.ValueOf(val)
70-
switch rv.Kind() {
71-
case reflect.Struct, reflect.Array, reflect.Slice, reflect.Map:
72-
if v.Type != VariableTypeComplex {
73-
return errors.New("variable type is not complex")
74-
}
68+
if v.IsComplexValued() && v.Type != VariableTypeComplex {
69+
return fmt.Errorf("variable type is not complex: %s", v.Type)
7570
}
7671

7772
v.Value = val
7873

7974
return nil
8075
}
8176

77+
func (v *Variable) IsComplexValued() bool {
78+
rv := reflect.ValueOf(v.Value)
79+
switch rv.Kind() {
80+
case reflect.Struct, reflect.Array, reflect.Slice, reflect.Map:
81+
return true
82+
default:
83+
return false
84+
}
85+
}
86+
8287
func (v *Variable) IsComplex() bool {
8388
return v.Type == VariableTypeComplex
8489
}
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package variable
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestVariable_IsComplexValued(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
v *Variable
13+
want bool
14+
}{
15+
{
16+
name: "map",
17+
v: &Variable{
18+
Value: map[string]any{
19+
"foo": "bar",
20+
},
21+
},
22+
want: true,
23+
},
24+
{
25+
name: "slice",
26+
v: &Variable{
27+
Value: []any{1, 2, 3},
28+
},
29+
want: true,
30+
},
31+
{
32+
name: "struct",
33+
v: &Variable{
34+
Value: struct{ Foo string }{Foo: "bar"},
35+
},
36+
want: true,
37+
},
38+
{
39+
name: "non-complex valued",
40+
v: &Variable{
41+
Value: "foo",
42+
},
43+
want: false,
44+
},
45+
}
46+
47+
for _, test := range tests {
48+
t.Run(test.name, func(t *testing.T) {
49+
assert.Equal(t, test.want, test.v.IsComplexValued())
50+
})
51+
}
52+
}

bundle/phases/deploy.go

+19
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,22 @@ func logTelemetry(ctx context.Context, b *bundle.Bundle) {
319319
bundleUuid = b.Config.Bundle.Uuid
320320
}
321321

322+
variableCount := len(b.Config.Variables)
323+
complexVariableCount := int64(0)
324+
lookupVariableCount := int64(0)
325+
for _, v := range b.Config.Variables {
326+
// If the resolved value of the variable is a complex type, we count it as a complex variable.
327+
// We can't rely on the "type: complex" annotation because the annotation is optional in some contexts
328+
// like bundle YAML files.
329+
if v.IsComplexValued() {
330+
complexVariableCount++
331+
}
332+
333+
if v.Lookup != nil {
334+
lookupVariableCount++
335+
}
336+
}
337+
322338
artifactPathType := protos.BundleDeployArtifactPathTypeUnspecified
323339
if libraries.IsVolumesPath(b.Config.Workspace.ArtifactPath) {
324340
artifactPathType = protos.BundleDeployArtifactPathTypeVolume
@@ -372,6 +388,9 @@ func logTelemetry(ctx context.Context, b *bundle.Bundle) {
372388
PythonUpdatedResourcesCount: b.Metrics.PythonUpdatedResourcesCount,
373389
PythonResourceLoadersCount: int64(len(experimentalConfig.Python.Resources)),
374390
PythonResourceMutatorsCount: int64(len(experimentalConfig.Python.Mutators)),
391+
VariableCount: int64(variableCount),
392+
ComplexVariableCount: complexVariableCount,
393+
LookupVariableCount: lookupVariableCount,
375394
},
376395
},
377396
})

0 commit comments

Comments
 (0)