Merge ~twom/launchpad:stats-better-builder-stats-stacking into launchpad:master

Proposed by Tom Wardill
Status: Merged
Approved by: Tom Wardill
Approved revision: e8163c3a596f6d86126bac3b4820625c391a894f
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~twom/launchpad:stats-better-builder-stats-stacking
Merge into: launchpad:master
Diff against target: 233 lines (+62/-24)
10 files modified
lib/lp/buildmaster/manager.py (+6/-3)
lib/lp/buildmaster/model/buildfarmjobbehaviour.py (+5/-3)
lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py (+2/-1)
lib/lp/services/config/schema-lazr.conf (+1/-0)
lib/lp/services/statsd/model/statsd_client.py (+6/-0)
lib/lp/services/statsd/numbercruncher.py (+5/-5)
lib/lp/services/statsd/tests/__init__.py (+1/-0)
lib/lp/services/statsd/tests/test_numbercruncher.py (+14/-6)
lib/lp/services/statsd/tests/test_statsd_client.py (+14/-2)
lib/lp/services/webapp/publication.py (+8/-4)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Ioana Lasc (community) Approve
Review via email: mp+392892@code.launchpad.net

Commit message

Move to use statsd environment config variable

Description of the change

The prefix setting in statsd doesn't let us do the final queries in quite the way we wanted, so add another setting for it and apply it as a label in all the metrics.

Also increase number cruncher logging level to DEBUG to see if we can work out why it appears to stop from the logs.

To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) wrote :

LGTM

review: Approve
Revision history for this message
Colin Watson (cjwatson) wrote :

Ideally I'd like the LP client to fill in the extra label automatically rather than having to repeat it everywhere, but this will do fine for now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/buildmaster/manager.py b/lib/lp/buildmaster/manager.py
index 7bbe4aa..e9732ea 100644
--- a/lib/lp/buildmaster/manager.py
+++ b/lib/lp/buildmaster/manager.py
@@ -532,10 +532,13 @@ class SlaveScanner:
532 if builder.current_build is not None:532 if builder.current_build is not None:
533 builder.current_build.gotFailure()533 builder.current_build.gotFailure()
534 self.statsd_client.incr(534 self.statsd_client.incr(
535 'builders.judged_failed,build=True,arch={}'.format(535 'builders.judged_failed,build=True,arch={},env={}'.format(
536 builder.current_build.processor.name))536 builder.current_build.processor.name,
537 self.statsd_client.lp_environment))
537 else:538 else:
538 self.statsd_client.incr('builders.judged_failed,build=False')539 self.statsd_client.incr(
540 'builders.judged_failed,build=False,env={}'.format(
541 self.statsd_client.lp_environment))
539 recover_failure(self.logger, vitals, builder, retry, failure.value)542 recover_failure(self.logger, vitals, builder, retry, failure.value)
540 transaction.commit()543 transaction.commit()
541 except Exception:544 except Exception:
diff --git a/lib/lp/buildmaster/model/buildfarmjobbehaviour.py b/lib/lp/buildmaster/model/buildfarmjobbehaviour.py
index edff53b..88ede6a 100644
--- a/lib/lp/buildmaster/model/buildfarmjobbehaviour.py
+++ b/lib/lp/buildmaster/model/buildfarmjobbehaviour.py
@@ -156,10 +156,12 @@ class BuildFarmJobBehaviourBase:
156 # Update stats156 # Update stats
157 job_type = getattr(self.build, 'job_type', None)157 job_type = getattr(self.build, 'job_type', None)
158 job_type_name = job_type.name if job_type else 'UNKNOWN'158 job_type_name = job_type.name if job_type else 'UNKNOWN'
159 getUtility(IStatsdClient).incr(159 statsd_client = getUtility(IStatsdClient)
160 'build.count,job_type={},builder_name={}'.format(160 statsd_client.incr(
161 'build.count,job_type={},builder_name={},env={}'.format(
161 job_type_name,162 job_type_name,
162 self._builder.name))163 self._builder.name,
164 statsd_client.lp_environment))
163165
164 logger.info(166 logger.info(
165 "Job %s (%s) started on %s: %s %s"167 "Job %s (%s) started on %s: %s %s"
diff --git a/lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py b/lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py
index 3bdf53d..06b0e3f 100644
--- a/lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py
+++ b/lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py
@@ -275,7 +275,8 @@ class TestDispatchBuildToSlave(StatsMixin, TestCase):
275 self.assertEqual(1, self.stats_client.incr.call_count)275 self.assertEqual(1, self.stats_client.incr.call_count)
276 self.assertEqual(276 self.assertEqual(
277 self.stats_client.incr.call_args_list[0][0],277 self.stats_client.incr.call_args_list[0][0],
278 ('build.count,job_type=UNKNOWN,builder_name=mock-builder',))278 ('build.count,job_type=UNKNOWN,'
279 'builder_name=mock-builder,env=test',))
279280
280281
281class TestGetUploadMethodsMixin:282class TestGetUploadMethodsMixin:
diff --git a/lib/lp/services/config/schema-lazr.conf b/lib/lp/services/config/schema-lazr.conf
index c16270a..aaa9d30 100644
--- a/lib/lp/services/config/schema-lazr.conf
+++ b/lib/lp/services/config/schema-lazr.conf
@@ -2028,3 +2028,4 @@ concurrency: 1
2028host: none2028host: none
2029port: none2029port: none
2030prefix: none2030prefix: none
2031environment: none
diff --git a/lib/lp/services/statsd/model/statsd_client.py b/lib/lp/services/statsd/model/statsd_client.py
index 868af30..6ccf027 100644
--- a/lib/lp/services/statsd/model/statsd_client.py
+++ b/lib/lp/services/statsd/model/statsd_client.py
@@ -43,6 +43,12 @@ class StatsdClient:
43 self._make_client()43 self._make_client()
4444
45 def __getattr__(self, name):45 def __getattr__(self, name):
46 # This is a convenience to keep all statsd client related
47 # items on the client. Having this separate from prefix
48 # allows us to use it as a label, rather than as part of the
49 # gauge name
50 if name == 'lp_environment':
51 return config.statsd.environment
46 if self._client is not None:52 if self._client is not None:
47 return getattr(self._client, name)53 return getattr(self._client, name)
48 else:54 else:
diff --git a/lib/lp/services/statsd/numbercruncher.py b/lib/lp/services/statsd/numbercruncher.py
index d2301d0..0a0552c 100644
--- a/lib/lp/services/statsd/numbercruncher.py
+++ b/lib/lp/services/statsd/numbercruncher.py
@@ -47,7 +47,7 @@ class NumberCruncher(service.Service):
47 def _setupLogger(self):47 def _setupLogger(self):
48 """Set up a 'number-cruncher' logger that redirects to twisted.48 """Set up a 'number-cruncher' logger that redirects to twisted.
49 """49 """
50 level = logging.INFO50 level = logging.DEBUG
51 logger = logging.getLogger(NUMBER_CRUNCHER_LOG_NAME)51 logger = logging.getLogger(NUMBER_CRUNCHER_LOG_NAME)
52 logger.propagate = False52 logger.propagate = False
5353
@@ -74,8 +74,8 @@ class NumberCruncher(service.Service):
74 for queue_type, contents in queue_details.items():74 for queue_type, contents in queue_details.items():
75 virt = queue_type == 'virt'75 virt = queue_type == 'virt'
76 for arch, value in contents.items():76 for arch, value in contents.items():
77 gauge_name = "buildqueue,virtualized={},arch={}".format(77 gauge_name = "buildqueue,virtualized={},arch={},env={}".format(
78 virt, arch)78 virt, arch, self.statsd_client.lp_environment)
79 self.logger.debug("{}: {}".format(gauge_name, value[0]))79 self.logger.debug("{}: {}".format(gauge_name, value[0]))
80 self.statsd_client.gauge(gauge_name, value[0])80 self.statsd_client.gauge(gauge_name, value[0])
81 self.logger.debug("Build queue stats update complete.")81 self.logger.debug("Build queue stats update complete.")
@@ -107,8 +107,8 @@ class NumberCruncher(service.Service):
107 counts['idle'] += 1107 counts['idle'] += 1
108 for processor, counts in counts_by_processor.items():108 for processor, counts in counts_by_processor.items():
109 for count_name, count_value in counts.items():109 for count_name, count_value in counts.items():
110 gauge_name = "builders.{},arch={}".format(110 gauge_name = "builders,status={},arch={},env={}".format(
111 count_name, processor)111 count_name, processor, self.statsd_client.lp_environment)
112 self.logger.debug("{}: {}".format(gauge_name, count_value))112 self.logger.debug("{}: {}".format(gauge_name, count_value))
113 self.statsd_client.gauge(gauge_name, count_value)113 self.statsd_client.gauge(gauge_name, count_value)
114 self.logger.debug("Builder stats update complete.")114 self.logger.debug("Builder stats update complete.")
diff --git a/lib/lp/services/statsd/tests/__init__.py b/lib/lp/services/statsd/tests/__init__.py
index 20885a4..23fb067 100644
--- a/lib/lp/services/statsd/tests/__init__.py
+++ b/lib/lp/services/statsd/tests/__init__.py
@@ -19,5 +19,6 @@ class StatsMixin:
19 # Install a mock statsd client so we can assert against the call19 # Install a mock statsd client so we can assert against the call
20 # counts and args.20 # counts and args.
21 self.stats_client = mock.Mock()21 self.stats_client = mock.Mock()
22 self.stats_client.lp_environment = "test"
22 self.useFixture(23 self.useFixture(
23 ZopeUtilityFixture(self.stats_client, IStatsdClient))24 ZopeUtilityFixture(self.stats_client, IStatsdClient))
diff --git a/lib/lp/services/statsd/tests/test_numbercruncher.py b/lib/lp/services/statsd/tests/test_numbercruncher.py
index 47c633f..c5a4ff6 100644
--- a/lib/lp/services/statsd/tests/test_numbercruncher.py
+++ b/lib/lp/services/statsd/tests/test_numbercruncher.py
@@ -85,10 +85,18 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
85 if 'amd64' in c[0][0]]85 if 'amd64' in c[0][0]]
86 self.assertThat(86 self.assertThat(
87 calls, MatchesListwise(87 calls, MatchesListwise(
88 [Equals(('builders.disabled,arch=amd64,virtualized=True', 0)),88 [Equals((
89 Equals(('builders.building,arch=amd64,virtualized=True', 0)),89 'builders,status=disabled,arch=amd64,'
90 Equals(('builders.idle,arch=amd64,virtualized=True', 0)),90 'virtualized=True,env=test', 0)),
91 Equals(('builders.cleaning,arch=amd64,virtualized=True', 1))91 Equals((
92 'builders,status=building,arch=amd64,'
93 'virtualized=True,env=test', 0)),
94 Equals((
95 'builders,status=idle,arch=amd64,'
96 'virtualized=True,env=test', 0)),
97 Equals((
98 'builders,status=cleaning,arch=amd64,'
99 'virtualized=True,env=test', 1))
92 ]))100 ]))
93101
94 def test_updateBuilderQueues(self):102 def test_updateBuilderQueues(self):
@@ -109,9 +117,9 @@ class TestNumberCruncher(StatsMixin, TestCaseWithFactory):
109 self.assertThat(117 self.assertThat(
110 [x[0] for x in self.stats_client.gauge.call_args_list],118 [x[0] for x in self.stats_client.gauge.call_args_list],
111 MatchesListwise(119 MatchesListwise(
112 [Equals(('buildqueue,virtualized=True,arch={}'.format(120 [Equals(('buildqueue,virtualized=True,arch={},env=test'.format(
113 build.processor.name), 1)),121 build.processor.name), 1)),
114 Equals(('buildqueue,virtualized=False,arch=386', 1))122 Equals(('buildqueue,virtualized=False,arch=386,env=test', 1))
115 ]))123 ]))
116124
117 def test_startService_starts_update_queues_loop(self):125 def test_startService_starts_update_queues_loop(self):
diff --git a/lib/lp/services/statsd/tests/test_statsd_client.py b/lib/lp/services/statsd/tests/test_statsd_client.py
index 6852af7..2e1a8e1 100644
--- a/lib/lp/services/statsd/tests/test_statsd_client.py
+++ b/lib/lp/services/statsd/tests/test_statsd_client.py
@@ -26,7 +26,8 @@ class TestClientConfiguration(TestCase):
26 self.addCleanup(client.reload)26 self.addCleanup(client.reload)
27 config.push(27 config.push(
28 'statsd_test',28 'statsd_test',
29 "[statsd]\nhost: 127.0.01\nport: 9999\nprefix: test\n")29 "[statsd]\nhost: 127.0.01\n"
30 "port: 9999\nprefix: test\nenvironment: test\n")
30 client.reload()31 client.reload()
31 self.assertIsInstance(client._client, StatsClient)32 self.assertIsInstance(client._client, StatsClient)
3233
@@ -45,6 +46,17 @@ class TestClientConfiguration(TestCase):
45 self.addCleanup(client.reload)46 self.addCleanup(client.reload)
46 config.push(47 config.push(
47 'statsd_test',48 'statsd_test',
48 "[statsd]\nhost: 127.0.01\nport: 9999\nprefix: test\n")49 "[statsd]\nhost: 127.0.01\n"
50 "port: 9999\nprefix: test\nenvironment: test\n")
49 client.reload()51 client.reload()
50 self.assertIsInstance(client._client, StatsClient)52 self.assertIsInstance(client._client, StatsClient)
53
54 def test_lp_environment_is_available(self):
55 client = getUtility(IStatsdClient)
56 self.addCleanup(client.reload)
57 config.push(
58 'statsd_test',
59 "[statsd]\nhost: 127.0.01\n"
60 "port: 9999\nprefix: test\nenvironment: test\n")
61 client.reload()
62 self.assertEqual(client.lp_environment, "test")
diff --git a/lib/lp/services/webapp/publication.py b/lib/lp/services/webapp/publication.py
index 7325d9f..9a9a0e3 100644
--- a/lib/lp/services/webapp/publication.py
+++ b/lib/lp/services/webapp/publication.py
@@ -795,13 +795,16 @@ class LaunchpadBrowserPublication(
795 status = request.response.getStatus()795 status = request.response.getStatus()
796 if status == 404: # Not Found796 if status == 404: # Not Found
797 OpStats.stats['404s'] += 1797 OpStats.stats['404s'] += 1
798 statsd_client.incr('errors.404')798 statsd_client.incr('errors.404,env={}'.format(
799 statsd_client.lp_environment))
799 elif status == 500: # Unhandled exceptions800 elif status == 500: # Unhandled exceptions
800 OpStats.stats['500s'] += 1801 OpStats.stats['500s'] += 1
801 statsd_client.incr('errors.500')802 statsd_client.incr('errors.500,env={}'.format(
803 statsd_client.lp_environment))
802 elif status == 503: # Timeouts804 elif status == 503: # Timeouts
803 OpStats.stats['503s'] += 1805 OpStats.stats['503s'] += 1
804 statsd_client.incr('errors.503')806 statsd_client.incr('errors.503,env={}'.format(
807 statsd_client.lp_environment))
805808
806 # Increment counters for status code groups.809 # Increment counters for status code groups.
807 status_group = str(status)[0] + 'XXs'810 status_group = str(status)[0] + 'XXs'
@@ -810,7 +813,8 @@ class LaunchpadBrowserPublication(
810 # Increment counter for 5XXs_b.813 # Increment counter for 5XXs_b.
811 if is_browser(request) and status_group == '5XXs':814 if is_browser(request) and status_group == '5XXs':
812 OpStats.stats['5XXs_b'] += 1815 OpStats.stats['5XXs_b'] += 1
813 statsd_client.incr('errors.5XX')816 statsd_client.incr('errors.5XX,env={}'.format(
817 statsd_client.lp_environment))
814818
815 # Make sure our databases are in a sane state for the next request.819 # Make sure our databases are in a sane state for the next request.
816 thread_name = threading.current_thread().name820 thread_name = threading.current_thread().name

Subscribers

People subscribed via source and target branches

to status/vote changes: