From e9777a88cec651446a6845c13bb02dfb5620064f Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Thu, 27 May 2021 09:11:50 -0400 Subject: [PATCH] plan applier: add trace-level log of plan The plans generated by the scheduler produce high-level output of counts on each evaluation, but when debugging scheduler issues it'd be nice to have a more detailed view of the resulting plan. Emitting this log at trace minimizes the overhead, and producing it in the plan applyer makes it easier to find as it will always be on the leader. --- nomad/plan_apply.go | 2 ++ nomad/structs/structs.go | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/nomad/plan_apply.go b/nomad/plan_apply.go index b566736a4..19c8f1b56 100644 --- a/nomad/plan_apply.go +++ b/nomad/plan_apply.go @@ -400,6 +400,8 @@ func (p *planner) asyncPlanWait(indexCh chan<- uint64, future raft.ApplyFuture, func evaluatePlan(pool *EvaluatePool, snap *state.StateSnapshot, plan *structs.Plan, logger log.Logger) (*structs.PlanResult, error) { defer metrics.MeasureSince([]string{"nomad", "plan", "evaluate"}, time.Now()) + logger.Trace("evaluating plan", "plan", log.Fmt("%#v", plan)) + // Denormalize without the job err := snap.DenormalizeAllocationsMap(plan.NodeUpdate) if err != nil { diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 418d48e5d..f44d5136b 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -10541,6 +10541,67 @@ type Plan struct { SnapshotIndex uint64 } +func (p *Plan) GoString() string { + out := fmt.Sprintf("(eval %s", p.EvalID[:8]) + out += fmt.Sprintf(", job %s", p.Job.ID) + if p.Deployment != nil { + out += fmt.Sprintf(", deploy %s", p.Deployment.ID[:8]) + } + if len(p.NodeUpdate) > 0 { + out += ", NodeUpdates: " + for node, allocs := range p.NodeUpdate { + out += fmt.Sprintf("(node[%s]", node[:8]) + for _, alloc := range allocs { + out += fmt.Sprintf(" (%s stop/evict)", alloc.ID[:8]) + } + out += ")" + } + } + if len(p.NodeAllocation) > 0 { + out += ", NodeAllocations: " + for node, allocs := range p.NodeAllocation { + out += fmt.Sprintf("(node[%s]", node[:8]) + for _, alloc := range allocs { + out += fmt.Sprintf(" (%s %s %s)", + alloc.ID[:8], alloc.Name, alloc.DesiredStatus, + ) + } + out += ")" + } + } + if len(p.NodePreemptions) > 0 { + out += ", NodePreemptions: " + for node, allocs := range p.NodePreemptions { + out += fmt.Sprintf("(node[%s]", node[:8]) + for _, alloc := range allocs { + out += fmt.Sprintf(" (%s %s %s)", + alloc.ID[:8], alloc.Name, alloc.DesiredStatus, + ) + } + out += ")" + } + } + if len(p.DeploymentUpdates) > 0 { + out += ", DeploymentUpdates: " + for _, dupdate := range p.DeploymentUpdates { + out += fmt.Sprintf("(%s %s)", + dupdate.DeploymentID[:8], dupdate.Status) + } + } + if p.Annotations != nil { + out += ", Annotations: " + for tg, updates := range p.Annotations.DesiredTGUpdates { + out += fmt.Sprintf("(update[%s] %v)", tg, updates) + } + for _, preempted := range p.Annotations.PreemptedAllocs { + out += fmt.Sprintf("(preempt %s)", preempted.ID[:8]) + } + } + + out += ")" + return out +} + // AppendStoppedAlloc marks an allocation to be stopped. The clientStatus of the // allocation may be optionally set by passing in a non-empty value. func (p *Plan) AppendStoppedAlloc(alloc *Allocation, desiredDesc, clientStatus, followupEvalID string) {