← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:numbercruncher-empty-build-queues into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:numbercruncher-empty-build-queues into launchpad:master.

Commit message:
Send buildqueue gauges for active builders with empty queues

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/411047

If builders for a (processor name, virtualized) combination exist but have no queued builds, we should still send a zero value for the corresponding `buildqueue` gauge, as otherwise we end up with unsightly gaps in graphs.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:numbercruncher-empty-build-queues into launchpad:master.
diff --git a/lib/lp/services/statsd/numbercruncher.py b/lib/lp/services/statsd/numbercruncher.py
index 8d538fe..02aa08a 100644
--- a/lib/lp/services/statsd/numbercruncher.py
+++ b/lib/lp/services/statsd/numbercruncher.py
@@ -89,13 +89,23 @@ class NumberCruncher(service.Service):
         """
         self.logger.debug("Updating build queue stats.")
         try:
+            # Send gauges for any (processor name, virtualized) combination
+            # that has either an active builder or a pending build.
+            queues = set()
+            for builder in self.builder_factory.iterVitals():
+                for processor_name in builder.processor_names:
+                    queues.add((processor_name, builder.virtualized))
             queue_details = getUtility(IBuilderSet).getBuildQueueSizes()
             for queue_type, contents in queue_details.items():
-                virt = queue_type == 'virt'
-                for arch, value in contents.items():
-                    self._sendGauge(
-                        "buildqueue", value[0],
-                        labels={"virtualized": virt, "arch": arch})
+                for processor_name in contents:
+                    queues.add((processor_name, queue_type == "virt"))
+            for processor_name, virt in sorted(queues):
+                virt_str = "virt" if virt else "nonvirt"
+                queue_size, _ = queue_details[virt_str].get(
+                    processor_name, (0, None))
+                self._sendGauge(
+                    "buildqueue", queue_size,
+                    labels={"virtualized": virt, "arch": processor_name})
             self.logger.debug("Build queue stats update complete.")
         except Exception:
             self.logger.exception("Failure while updating build queue stats:")
diff --git a/lib/lp/services/statsd/tests/test_numbercruncher.py b/lib/lp/services/statsd/tests/test_numbercruncher.py
index e2ed4be..cb9f61a 100644
--- a/lib/lp/services/statsd/tests/test_numbercruncher.py
+++ b/lib/lp/services/statsd/tests/test_numbercruncher.py
@@ -205,17 +205,21 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
         transaction.commit()
         clock = task.Clock()
         manager = NumberCruncher(clock=clock)
+        manager.builder_factory.update()
         manager._updateBuilderCounts = FakeMethod()
         manager.updateBuilderQueues()
 
         self.assertFalse(is_transaction_in_progress())
-        self.assertEqual(2, self.stats_client.gauge.call_count)
         self.assertThat(
             [x[0] for x in self.stats_client.gauge.call_args_list],
             MatchesSetwise(
                 Equals(('buildqueue,arch={},env=test,virtualized=True'.format(
                     build.processor.name), 1)),
-                Equals(('buildqueue,arch=386,env=test,virtualized=False', 1))
+                Equals(('buildqueue,arch=386,env=test,virtualized=False', 1)),
+                # These builders exist even though their queues are empty,
+                # so we send gauges for them to avoid gaps in graphs.
+                Equals(('buildqueue,arch=amd64,env=test,virtualized=True', 0)),
+                Equals(('buildqueue,arch=386,env=test,virtualized=True', 0)),
                 ))
 
     def test_updateBuilderQueues_error(self):