← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:script-activity-statsd into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:script-activity-statsd into launchpad:master.

Commit message:
Send script activity timings to statsd as well

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

This will make it easier to add graphs, use modern alerting systems, and so on.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:script-activity-statsd into launchpad:master.
diff --git a/lib/lp/services/scripts/doc/script-monitoring.txt b/lib/lp/services/scripts/doc/script-monitoring.txt
index 9e22745..eeb3604 100644
--- a/lib/lp/services/scripts/doc/script-monitoring.txt
+++ b/lib/lp/services/scripts/doc/script-monitoring.txt
@@ -22,21 +22,38 @@ IScriptActivitySet.recordSuccess():
     >>> import socket
     >>> import subprocess
     >>> import tempfile
+    >>> from textwrap import dedent
+
+    >>> from fixtures import MockPatchObject
     >>> import pytz
     >>> import transaction
     >>> from zope.component import getUtility
+
+    >>> from lp.services.compat import mock
+    >>> from lp.services.config import config
     >>> from lp.services.scripts.interfaces.scriptactivity import (
     ...     IScriptActivitySet)
+    >>> from lp.services.statsd.interfaces.statsd_client import IStatsdClient
     >>> from lp.testing.dbuser import switch_dbuser
 
     >>> UTC = pytz.timezone('UTC')
     >>> switch_dbuser('garbo_daily') # A script db user
 
-    >>> activity = getUtility(IScriptActivitySet).recordSuccess(
-    ...     name='script-name',
-    ...     date_started=datetime.datetime(2007,2,1,10,0,tzinfo=UTC),
-    ...     date_completed=datetime.datetime(2007,2,1,10,1,tzinfo=UTC),
-    ...     hostname='script-host')
+    >>> config.push('statsd_test', dedent('''
+    ...     [statsd]
+    ...     environment: test
+    ...     '''))
+    >>> statsd_client = getUtility(IStatsdClient)
+    >>> stats_client = mock.Mock()
+
+    >>> with MockPatchObject(statsd_client, '_client', stats_client):
+    ...     activity = getUtility(IScriptActivitySet).recordSuccess(
+    ...         name='script-name',
+    ...         date_started=datetime.datetime(2007,2,1,10,0,tzinfo=UTC),
+    ...         date_completed=datetime.datetime(2007,2,1,10,1,tzinfo=UTC),
+    ...         hostname='script-host')
+
+    >>> _ = config.pop('statsd_test')
 
 The activity object records the script name, the host name it ran on
 and the start and end timestamps:
@@ -50,6 +67,15 @@ and the start and end timestamps:
     >>> print(activity.date_completed)
     2007-02-01 10:01:00+00:00
 
+It sends a corresponding timing stat to statsd.
+
+    >>> stats_client.timing.call_count
+    1
+    >>> print(stats_client.timing.call_args[0][0])
+    script_activity,name=script-name,env=test
+    >>> stats_client.timing.call_args[0][1]
+    60000.0
+
 We can also query for the last activity for a particular script, which
 will match the activity we just created:
 
diff --git a/lib/lp/services/scripts/model/scriptactivity.py b/lib/lp/services/scripts/model/scriptactivity.py
index 7984696..0df3849 100644
--- a/lib/lp/services/scripts/model/scriptactivity.py
+++ b/lib/lp/services/scripts/model/scriptactivity.py
@@ -17,6 +17,7 @@ from storm.locals import (
     Int,
     Unicode,
     )
+from zope.component import getUtility
 from zope.interface import implementer
 
 from lp.services.database.interfaces import IStore
@@ -25,6 +26,7 @@ from lp.services.scripts.interfaces.scriptactivity import (
     IScriptActivity,
     IScriptActivitySet,
     )
+from lp.services.statsd.interfaces.statsd_client import IStatsdClient
 
 
 @implementer(IScriptActivity)
@@ -58,6 +60,11 @@ class ScriptActivitySet:
             name=six.ensure_text(name), hostname=six.ensure_text(hostname),
             date_started=date_started, date_completed=date_completed)
         IStore(ScriptActivity).add(activity)
+        # Pass equivalent information through to statsd as well.  (Don't
+        # bother with the hostname, since telegraf adds that.)
+        getUtility(IStatsdClient).timing(
+            'script_activity,name={}'.format(name),
+            (date_completed - date_started).total_seconds() * 1000)
         return activity
 
     def getLastActivity(self, name):