Skip to content
Draft
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
3 changes: 3 additions & 0 deletions acceptance/bundle/telemetry/deploy/databricks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ resources:
jobs:
job_one:
name: job one
permissions:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To check that the telemetry correctly tracks permissions changes.

- level: CAN_VIEW
user_name: viewer@example.com
job_two:
name: job two
job_three:
Expand Down
23 changes: 22 additions & 1 deletion acceptance/bundle/telemetry/deploy/out.telemetry.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,28 @@
],
"bundle_mode": "TYPE_UNSPECIFIED",
"workspace_artifact_path_type": "WORKSPACE_FILE_SYSTEM",
"local_cache_measurements_ms": [...redacted...]
"local_cache_measurements_ms": [...redacted...],
"resource_state_size_bytes": [
250,
250,
282,
284,
409
],
"resource_action_counts": [
{
"key": "jobs.create",
"value": 3
},
{
"key": "jobs.permissions.create",
"value": 1
},
{
"key": "pipelines.create",
"value": 2
}
]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion bundle/phases/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func Deploy(ctx context.Context, b *bundle.Bundle, outputHandler sync.OutputHand
return
}

logDeployTelemetry(ctx, b)
logDeployTelemetry(ctx, b, plan)
bundle.ApplyContext(ctx, b, scripts.Execute(config.ScriptPostDeploy))
}

Expand Down
71 changes: 70 additions & 1 deletion bundle/phases/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (

"github.com/databricks/cli/bundle"
"github.com/databricks/cli/bundle/config"
"github.com/databricks/cli/bundle/deployplan"
"github.com/databricks/cli/bundle/libraries"
"github.com/databricks/cli/libs/dyn"
"github.com/databricks/cli/libs/dyn/jsonsaver"
"github.com/databricks/cli/libs/log"
"github.com/databricks/cli/libs/telemetry"
"github.com/databricks/cli/libs/telemetry/protos"
Expand All @@ -33,7 +35,7 @@ func getExecutionTimes(b *bundle.Bundle) []protos.IntMapEntry {
return executionTimes
}

func logDeployTelemetry(ctx context.Context, b *bundle.Bundle) {
func logDeployTelemetry(ctx context.Context, b *bundle.Bundle, plan *deployplan.Plan) {
resourcesCount := int64(0)
_, err := dyn.MapByPattern(b.Config.Value(), dyn.NewPattern(dyn.Key("resources"), dyn.AnyKey(), dyn.AnyKey()), func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
resourcesCount++
Expand Down Expand Up @@ -184,7 +186,74 @@ func logDeployTelemetry(ctx context.Context, b *bundle.Bundle) {
ComplexVariableCount: complexVariableCount,
LookupVariableCount: lookupVariableCount,
BundleMutatorExecutionTimeMs: getExecutionTimes(b),
ResourceStateSizeBytes: computeResourceStateSizes(ctx, b),
ResourceActionCounts: computeActionCounts(plan),
},
},
})
}

// computeActionCounts computes per-resource-type action counts from the deploy plan.
func computeActionCounts(plan *deployplan.Plan) []protos.IntMapEntry {
if plan == nil {
return nil
}

counts := map[string]int64{}
for key, entry := range plan.Plan {
if entry.Action == deployplan.Skip {
continue
}

resourceType := config.GetResourceTypeFromKey(key)
if resourceType == "" {
continue
}

mapKey := resourceType + "." + string(entry.Action)
counts[mapKey]++
}

return sortedIntMapEntries(counts)
}

// computeResourceStateSizes computes per-resource config sizes in bytes from
// the bundle's YAML configuration. Returns one entry per resource instance,
// sorted in ascending order. This is engine-independent since it uses the
// YAML config directly.
func computeResourceStateSizes(ctx context.Context, b *bundle.Bundle) []int64 {
var sizes []int64

_, err := dyn.MapByPattern(
b.Config.Value(),
dyn.NewPattern(dyn.Key("resources"), dyn.AnyKey(), dyn.AnyKey()),
func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
jsonBytes, err := jsonsaver.Marshal(v)
if err != nil {
log.Debugf(ctx, "failed to marshal resource %s: %s", p, err)
return v, nil
}
sizes = append(sizes, int64(len(jsonBytes)))
return v, nil
},
)
if err != nil {
log.Debugf(ctx, "failed to compute resource state sizes: %s", err)
return nil
}

slices.Sort(sizes)
return sizes
}

// sortedIntMapEntries converts a map to a sorted slice of IntMapEntry.
func sortedIntMapEntries(m map[string]int64) []protos.IntMapEntry {
entries := make([]protos.IntMapEntry, 0, len(m))
for k, v := range m {
entries = append(entries, protos.IntMapEntry{Key: k, Value: v})
}
sort.Slice(entries, func(i, j int) bool {
return entries[i].Key < entries[j].Key
})
return entries
}
9 changes: 9 additions & 0 deletions libs/telemetry/protos/bundle_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ type BundleDeployExperimental struct {

// Local cache measurements in milliseconds (compute duration, potential savings, etc.)
LocalCacheMeasurementsMs []IntMapEntry `json:"local_cache_measurements_ms,omitempty"`

// Per-resource config sizes in bytes, one entry per resource instance.
// Sorted in ascending order.
ResourceStateSizeBytes []int64 `json:"resource_state_size_bytes,omitempty"`

// Per-resource-type deployment action counts.
// Keys are "{resource_type}.{action}" (e.g., "jobs.create", "pipelines.update").
// Values are the number of resources with that action.
ResourceActionCounts []IntMapEntry `json:"resource_action_counts,omitempty"`
}

type BoolMapEntry struct {
Expand Down