From 7795f431a1b7c9770d1abc362f7646c94e971269 Mon Sep 17 00:00:00 2001
From: Martijn Vermaat <martijn@vermaat.name>
Date: Mon, 15 Feb 2016 16:43:36 +0100
Subject: [PATCH] Set process name for long-running processes

For long-running processes it can be convenient to have a short and
human-readable process name. For example, in our typical server
configuration we have quite a few Mutalyzer processes running with very
long process names, making ps and top output hard to parse.

It is assumed that in production environments the webservices and
website are ran in a separate WSGI server such as Gunicorn which can be
configured to set the process name.

The setproctitle dependency for this feature is a C extension and we
therefore make it a soft dependency. Construction copied from Gunicorn:

https://github.com/benoitc/gunicorn/blob/5bc13be79ecaf8f1027764c600023f674ebcf5b2/gunicorn/util.py#L55
---
 mutalyzer/entrypoints/admin.py           |  9 +++++++++
 mutalyzer/entrypoints/batch_processor.py |  5 +++++
 mutalyzer/util.py                        | 13 +++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/mutalyzer/entrypoints/admin.py b/mutalyzer/entrypoints/admin.py
index b0d26f35..77a4e948 100644
--- a/mutalyzer/entrypoints/admin.py
+++ b/mutalyzer/entrypoints/admin.py
@@ -25,6 +25,7 @@ from ..db.models import Assembly, BatchJob, BatchQueueItem, Chromosome
 from .. import mapping
 from .. import output
 from .. import sync
+from .. import util
 
 
 class UserError(Exception):
@@ -95,6 +96,10 @@ def import_mapview(assembly_name_or_alias, mapview_file, encoding,
     """
     Import transcript mappings from an NCBI mapview file.
     """
+    # For long-running processes it can be convenient to have a short and
+    # human-readable process name.
+    util.set_process_name('mutalyzer: mapview-import')
+
     mapview_file = codecs.getreader(encoding)(mapview_file)
 
     try:
@@ -144,6 +149,10 @@ def sync_cache(wsdl_url, url_template, history=7):
         25 5 * * *  mutalyzer-cache-sync 'http://dom1/?wsdl' 'http://dom1/{file}' -H 7
         55 5 * * *  mutalyzer-cache-sync 'http://dom2/?wsdl' 'http://dom2/{file}' -H 7
     """
+    # For long-running processes it can be convenient to have a short and
+    # human-readable process name.
+    util.set_process_name('mutalyzer: cache-sync')
+
     cache_sync = sync.CacheSync(output.Output(__file__))
     inserted, downloaded = cache_sync.sync_with_remote(wsdl_url, url_template,
                                                        history)
diff --git a/mutalyzer/entrypoints/batch_processor.py b/mutalyzer/entrypoints/batch_processor.py
index ae3c2945..64fe6e7e 100644
--- a/mutalyzer/entrypoints/batch_processor.py
+++ b/mutalyzer/entrypoints/batch_processor.py
@@ -15,12 +15,17 @@ import time
 
 from .. import db
 from .. import Scheduler
+from .. import util
 
 
 def process():
     """
     Run forever in a loop processing scheduled batch jobs.
     """
+    # For long-running processes it can be convenient to have a short and
+    # human-readable process name.
+    util.set_process_name('mutalyzer: batch-processor')
+
     scheduler = Scheduler.Scheduler()
 
     def handle_exit(signum, stack_frame):
diff --git a/mutalyzer/util.py b/mutalyzer/util.py
index c53d9130..c5810a9f 100644
--- a/mutalyzer/util.py
+++ b/mutalyzer/util.py
@@ -955,3 +955,16 @@ class LazyObject(object):
 
     __len__ = _new_method_proxy(len)
     __contains__ = _new_method_proxy(operator.contains)
+
+
+# We try to minimize non-trivial dependencies for non-critical features. The
+# setproctitle package is implemented as a C extension and hence requires a C
+# compiler and the Python development headers. Here we use it as an optional
+# dependency.
+try:
+    import setproctitle as _setproctitle
+    def set_process_name(name):
+        _setproctitle.setproctitle(name)
+except ImportError:
+    def set_process_name(name):
+        pass
-- 
GitLab