Use heap to store top K scoring nodes.

Scoring metadata is now aggregated by scorer type to make it easier
to parse when reading it in the CLI.
This commit is contained in:
Preetha Appan
2018-08-08 09:41:56 -05:00
parent fed8ce9749
commit 4d68d935e4
7 changed files with 182 additions and 10 deletions

View File

@@ -224,6 +224,60 @@ func TestAllocStatusCommand_RescheduleInfo(t *testing.T) {
require.Regexp(regexp.MustCompile(".*Reschedule Attempts\\s*=\\s*1/2"), out)
}
func TestAllocStatusCommand_ScoreMetrics(t *testing.T) {
t.Parallel()
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
// Wait for a node to be ready
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
for _, node := range nodes {
if node.Status == structs.NodeStatusReady {
return true, nil
}
}
return false, fmt.Errorf("no ready nodes")
}, func(err error) {
t.Fatalf("err: %v", err)
})
ui := new(cli.MockUi)
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui}}
// Test reschedule attempt info
require := require.New(t)
state := srv.Agent.Server().State()
a := mock.Alloc()
mockNode1 := mock.Node()
mockNode2 := mock.Node()
a.Metrics = &structs.AllocMetric{
ScoreMetaData: map[string][]*structs.NodeScoreMeta{
"binpack": []*structs.NodeScoreMeta{
{NodeID: mockNode1.ID, Score: 0.77},
{NodeID: mockNode2.ID, Score: 0.75},
},
"node-affinity": []*structs.NodeScoreMeta{
{NodeID: mockNode1.ID, Score: 0.5},
{NodeID: mockNode2.ID, Score: 0.33},
},
},
}
require.Nil(state.UpsertAllocs(1000, []*structs.Allocation{a}))
if code := cmd.Run([]string{"-address=" + url, "-verbose", a.ID}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out := ui.OutputWriter.String()
require.Contains(out, "Placement Metrics")
require.Contains(out, fmt.Sprintf("Scorer %q, Node %q", "binpack", mockNode1.ID))
require.Contains(out, fmt.Sprintf("Scorer %q, Node %q", "binpack", mockNode2.ID))
require.Contains(out, fmt.Sprintf("Scorer %q, Node %q", "node-affinity", mockNode1.ID))
require.Contains(out, fmt.Sprintf("Scorer %q, Node %q", "binpack", mockNode2.ID))
}
func TestAllocStatusCommand_AutocompleteArgs(t *testing.T) {
assert := assert.New(t)
t.Parallel()

View File

@@ -373,8 +373,17 @@ func formatAllocMetrics(metrics *api.AllocationMetric, scores bool, prefix strin
// Print scores
if scores {
for name, score := range metrics.Scores {
out += fmt.Sprintf("%s* Score %q = %f\n", prefix, name, score)
if len(metrics.ScoreMetaData) > 0 {
for scorer, scoreMeta := range metrics.ScoreMetaData {
for _, nodeScore := range scoreMeta {
out += fmt.Sprintf("%s* Scorer %q, Node %q = %f\n", prefix, scorer, nodeScore.NodeID, nodeScore.Score)
}
}
} else {
// Backwards compatibility for old allocs
for name, score := range metrics.Scores {
out += fmt.Sprintf("%s* Score %q = %f\n", prefix, name, score)
}
}
}