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.
This commit is contained in:
Tim Gross 2021-05-27 09:11:50 -04:00 committed by Tim Gross
parent 7a55a6af16
commit e9777a88ce
2 changed files with 63 additions and 0 deletions

View file

@ -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 {

View file

@ -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) {