Skip to content

Commit

Permalink
Added a metric for the number of per-role active offer filters.
Browse files Browse the repository at this point in the history
  • Loading branch information
bbannier authored and bmahler committed Mar 26, 2016
1 parent 2309ae9 commit 08c68dc
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 0 deletions.
7 changes: 7 additions & 0 deletions docs/monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,13 @@ and resource allocations in the allocator.
<td>Number of dispatch events in the event queue</td>
<td>Gauge</td>
</tr>
<tr>
<td>
<code>allocator/mesos/offer_filters/roles/&lt;role&gt;/active</code>
</td>
<td>Number of active offer filters for all frameworks within the role</td>
<td>Gauge</td>
</tr>
<tr>
<td>
<code>allocator/mesos/quota/roles/&lt;role&gt;/resources/&lt;resource&gt;/offered_or_allocated</code>
Expand Down
22 changes: 22 additions & 0 deletions src/master/allocator/mesos/hierarchical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ void HierarchicalAllocatorProcess::addFramework(
activeRoles[role] = 1;
roleSorter->add(role, roleWeight(role));
frameworkSorters[role] = frameworkSorterFactory();
metrics.addRole(role);
} else {
activeRoles[role]++;
}
Expand Down Expand Up @@ -315,6 +316,8 @@ void HierarchicalAllocatorProcess::removeFramework(
CHECK(frameworkSorters.contains(role));
delete frameworkSorters[role];
frameworkSorters.erase(role);

metrics.removeRole(role);
}

// Do not delete the filters contained in this
Expand Down Expand Up @@ -1758,6 +1761,25 @@ double HierarchicalAllocatorProcess::_quota_allocated(
return used.isSome() ? used->value() : 0;
}


double HierarchicalAllocatorProcess::_offer_filters_active(
const string& role)
{
double result = 0;

foreachvalue (const Framework& framework, frameworks) {
if (framework.role != role) {
continue;
}

foreachkey (const SlaveID& slaveId, framework.offerFilters) {
result += framework.offerFilters.get(slaveId)->size();
}
}

return result;
}

} // namespace internal {
} // namespace allocator {
} // namespace master {
Expand Down
3 changes: 3 additions & 0 deletions src/master/allocator/mesos/hierarchical.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ class HierarchicalAllocatorProcess : public MesosAllocatorProcess
const std::string& role,
const std::string& resource);

double _offer_filters_active(
const std::string& role);

hashmap<FrameworkID, Framework> frameworks;

struct Slave
Expand Down
32 changes: 32 additions & 0 deletions src/master/allocator/mesos/metrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ Metrics::~Metrics()
process::metrics::remove(gauge);
}
}

foreachvalue (const Gauge& gauge, offer_filters_active) {
process::metrics::remove(gauge);
}
}


Expand Down Expand Up @@ -163,6 +167,34 @@ void Metrics::removeQuota(const string& role)
quota_allocated.erase(role);
}


void Metrics::addRole(const string& role)
{
CHECK(!offer_filters_active.contains(role));

Gauge gauge(
"allocator/mesos/offer_filters/roles/" + role + "/active",
defer(allocator,
&HierarchicalAllocatorProcess::_offer_filters_active,
role));

offer_filters_active.put(role, gauge);

process::metrics::add(gauge);
}


void Metrics::removeRole(const string& role)
{
Option<Gauge> gauge = offer_filters_active.get(role);

CHECK_SOME(gauge);

offer_filters_active.erase(role);

process::metrics::remove(gauge.get());
}

} // namespace internal {
} // namespace allocator {
} // namespace master {
Expand Down
6 changes: 6 additions & 0 deletions src/master/allocator/mesos/metrics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct Metrics
void setQuota(const std::string& role, const Quota& quota);
void removeQuota(const std::string& role);

void addRole(const std::string& role);
void removeRole(const std::string& role);

const process::PID<HierarchicalAllocatorProcess> allocator;

// Number of dispatch events currently waiting in the allocator process.
Expand Down Expand Up @@ -76,6 +79,9 @@ struct Metrics
// Gauges for the per-role quota guarantee for each resource.
hashmap<std::string, hashmap<std::string, process::metrics::Gauge>>
quota_guarantee;

// Gauges for the per-role count of active offer filters.
hashmap<std::string, process::metrics::Gauge> offer_filters_active;
};

} // namespace internal {
Expand Down
102 changes: 102 additions & 0 deletions src/tests/hierarchical_allocator_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,12 @@ TEST_F(HierarchicalAllocatorTest, OfferFilter)
// Ensure the offer filter timeout is set before advancing the clock.
Clock::settle();

JSON::Object metrics = Metrics();

string activeOfferFilters =
"allocator/mesos/offer_filters/roles/" + ROLE + "/active";
EXPECT_EQ(1, metrics.values[activeOfferFilters]);

// Trigger a batch allocation.
Clock::advance(flags.allocation_interval);
Clock::settle();
Expand All @@ -557,6 +563,10 @@ TEST_F(HierarchicalAllocatorTest, OfferFilter)
AWAIT_READY(allocation);
EXPECT_EQ(framework1.id(), allocation.get().frameworkId);
EXPECT_EQ(agent1.resources(), Resources::sum(allocation.get().resources));

metrics = Metrics();

EXPECT_EQ(0, metrics.values[activeOfferFilters]);
}


Expand Down Expand Up @@ -2643,6 +2653,98 @@ TEST_F(HierarchicalAllocatorTest, AllocationRunTimerMetrics)
}


// This test checks that per-role active offer filter metrics
// are correctly reported in the metrics endpoint.
TEST_F(HierarchicalAllocatorTest, ActiveOfferFiltersMetrics)
{
// Pausing the clock is not necessary, but ensures that the test
// doesn't rely on the batch allocation in the allocator, which
// would slow down the test.
Clock::pause();

initialize();

SlaveInfo agent = createSlaveInfo("cpus:2;mem:1024;disk:0");
allocator->addSlave(agent.id(), agent, None(), agent.resources(), {});

// Register three frameworks, two of which are in the same role.
// For every offer the frameworks install practically indefinite
// offer filters.
Duration filterTimeout = flags.allocation_interval * 100;
Filters offerFilter;
offerFilter.set_refuse_seconds(filterTimeout.secs());

FrameworkInfo framework1 = createFrameworkInfo("roleA");
allocator->addFramework(framework1.id(), framework1, {});

Future<Allocation> allocation = allocations.get();

AWAIT_READY(allocation);
ASSERT_EQ(framework1.id(), allocation->frameworkId);

allocator->recoverResources(
allocation->frameworkId,
agent.id(),
allocation->resources.get(agent.id()).get(),
offerFilter);

JSON::Object expected;
expected.values = {
{"allocator/mesos/offer_filters/roles/roleA/active", 1},
};

JSON::Value metrics = Metrics();

EXPECT_TRUE(metrics.contains(expected));

FrameworkInfo framework2 = createFrameworkInfo("roleB");
allocator->addFramework(framework2.id(), framework2, {});

allocation = allocations.get();

AWAIT_READY(allocation);
ASSERT_EQ(framework2.id(), allocation->frameworkId);

allocator->recoverResources(
allocation->frameworkId,
agent.id(),
allocation->resources.get(agent.id()).get(),
offerFilter);

expected.values = {
{"allocator/mesos/offer_filters/roles/roleA/active", 1},
{"allocator/mesos/offer_filters/roles/roleB/active", 1},
};

metrics = Metrics();

EXPECT_TRUE(metrics.contains(expected));

FrameworkInfo framework3 = createFrameworkInfo("roleA");
allocator->addFramework(framework3.id(), framework3, {});

allocation = allocations.get();

AWAIT_READY(allocation);
ASSERT_EQ(framework3.id(), allocation->frameworkId);

allocator->recoverResources(
allocation->frameworkId,
agent.id(),
allocation->resources.get(agent.id()).get(),
offerFilter);

expected.values = {
{"allocator/mesos/offer_filters/roles/roleA/active", 2},
{"allocator/mesos/offer_filters/roles/roleB/active", 1},
};

metrics = Metrics();

EXPECT_TRUE(metrics.contains(expected));
}


// This test ensures that resource allocation is done according to each role's
// weight. This is done by having six agents and three frameworks and making
// sure each framework gets the appropriate number of resources.
Expand Down

0 comments on commit 08c68dc

Please sign in to comment.