From 5118dafc65e4ec39b782fa029ba74919700cb42b Mon Sep 17 00:00:00 2001
From: wanghao <sxmatch1986@gmail.com>
Date: Thu, 2 Mar 2017 09:18:44 +0800
Subject: [PATCH] Introduce Guru to Zaqar

Guru is a mechanism whereby developers
and system administrators can generate
a report about the state of a running
Zaqar executable.

This report is called a *Guru Meditation Report*

This mechanism will help developer or operator
to fix issues in (production) deployments without
stopping Zaqar service.

Implements: blueprint introduce-guru-to-zaqar
Change-Id: I72885be396be7eb0a9dd8fd564d706a8351b02c6
---
 doc/source/devref/gmr.rst                     | 87 +++++++++++++++++++
 doc/source/index.rst                          |  8 ++
 etc/oslo-config-generator/zaqar.conf          |  1 +
 ...roduce-guru-to-zaqar-ac7b51c764503829.yaml |  6 ++
 requirements.txt                              |  1 +
 zaqar/cmd/server.py                           |  6 ++
 zaqar/transport/wsgi/app.py                   |  6 ++
 zaqar/version.py                              |  1 +
 8 files changed, 116 insertions(+)
 create mode 100644 doc/source/devref/gmr.rst
 create mode 100644 releasenotes/notes/introduce-guru-to-zaqar-ac7b51c764503829.yaml

diff --git a/doc/source/devref/gmr.rst b/doc/source/devref/gmr.rst
new file mode 100644
index 000000000..405a3c7fd
--- /dev/null
+++ b/doc/source/devref/gmr.rst
@@ -0,0 +1,87 @@
+..
+      Copyright (c) 2017 OpenStack Foundation
+      All Rights Reserved.
+
+      Licensed under the Apache License, Version 2.0 (the "License"); you may
+      not use this file except in compliance with the License. You may obtain
+      a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+      License for the specific language governing permissions and limitations
+      under the License.
+
+=======================
+Guru Meditation Reports
+=======================
+
+Zaqar contains a mechanism whereby developers and system administrators can
+generate a report about the state of a running Zaqar executable.
+This report is called a *Guru Meditation Report* (*GMR* for short).
+
+Generating a GMR
+----------------
+
+For wsgi and websocket mode, a *GMR* can be generated by sending the *USR2*
+signal to any Zaqar process with support (see below).
+The *GMR* will then be outputted standard error for that particular process.
+
+For example, suppose that ``zaqar-server`` has process id ``8675``, and was
+run with ``2>/var/log/zaqar/zaqar-server-err.log``.
+Then, ``kill -USR2 8675`` will trigger the Guru Meditation report to be
+printed to ``/var/log/zaqar/zaqar-server-err.log``.
+
+For uwsgi mode, user should add a configuration in Zaqar's conf file::
+
+    [oslo_reports]
+    file_event_handler=['The path to a file to watch for changes to trigger '
+                        'the reports, instead of signals. Setting this option '
+                        'disables the signal trigger for the reports.']
+    file_event_handler_interval=['How many seconds to wait between polls when '
+                                 'file_event_handler is set, default value '
+                                 'is 1']
+
+For example, you can specify "file_event_handler=/tmp/guru_report" and
+"file_event_handler_interval=1" in Zaqar's conf file.
+
+A *GMR* can be generated by "touch"ing the file which was specified in
+file_event_handler. The *GMR* will then output to standard error for
+that particular process.
+
+For example, suppose that ``zaqar-server`` was run with
+``2>/var/log/zaqar/zaqar-server-err.log``, and the file path is
+``/tmp/guru_report``.
+Then, ``touch /tmp/guru_report`` will trigger the Guru Meditation report to be
+printed to ``/var/log/zaqar/zaqar-server-err.log``.
+
+Structure of a GMR
+------------------
+
+The *GMR* is designed to be extensible; any particular executable may add
+its own sections.  However, the base *GMR* consists of several sections:
+
+Package
+  Shows information about the package to which this process belongs,
+  including version information
+
+Threads
+  Shows stack traces and thread ids for each of the threads within this process
+
+Green Threads
+  Shows stack traces for each of the green threads within this process
+  (green threads don't have thread ids)
+
+Configuration
+  Lists all the configuration options currently accessible via the CONF object
+  for the current process
+
+Extending the GMR
+-----------------
+
+As mentioned above, additional sections can be added to the GMR for a
+particular executable.  For more information, see the inline documentation
+about oslo.reports:
+`oslo.reports <http://docs.openstack.org/developer/oslo.reports/>`_
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 00fcafb5d..5bed22b7f 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -208,6 +208,14 @@ Internal API reference
 
    api/autoindex
 
+Guru Meditation Reports
+=======================
+
+.. toctree::
+   :maxdepth: 1
+
+   devref/gmr
+
 Indices and tables
 ------------------
 
diff --git a/etc/oslo-config-generator/zaqar.conf b/etc/oslo-config-generator/zaqar.conf
index 64561e1c8..665fec25b 100644
--- a/etc/oslo-config-generator/zaqar.conf
+++ b/etc/oslo-config-generator/zaqar.conf
@@ -16,3 +16,4 @@ namespace = keystonemiddleware.auth_token
 namespace = oslo.cache
 namespace = oslo.messaging
 namespace = osprofiler
+namespace = oslo.reports
diff --git a/releasenotes/notes/introduce-guru-to-zaqar-ac7b51c764503829.yaml b/releasenotes/notes/introduce-guru-to-zaqar-ac7b51c764503829.yaml
new file mode 100644
index 000000000..3ffd681e1
--- /dev/null
+++ b/releasenotes/notes/introduce-guru-to-zaqar-ac7b51c764503829.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - Introduce Guru to Zaqar. Guru is a mechanism whereby developers and system
+    administrators can generate a report about the state of a running Zaqar
+    executable. This report is called a *Guru Meditation Report*. Now Guru can
+    support wsgi, websocket and uwsgi modes all.
diff --git a/requirements.txt b/requirements.txt
index 8cfd5fed4..53298849c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -20,6 +20,7 @@ oslo.context>=2.12.0 # Apache-2.0
 oslo.i18n>=2.1.0 # Apache-2.0
 oslo.log>=3.11.0 # Apache-2.0
 oslo.messaging>=5.14.0 # Apache-2.0
+oslo.reports>=0.6.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
 oslo.utils>=3.18.0 # Apache-2.0
 oslo.policy>=1.17.0 # Apache-2.0
diff --git a/zaqar/cmd/server.py b/zaqar/cmd/server.py
index 24de42b4d..ae1673f34 100644
--- a/zaqar/cmd/server.py
+++ b/zaqar/cmd/server.py
@@ -16,10 +16,13 @@ import os
 
 from oslo_config import cfg
 from oslo_log import log
+from oslo_reports import guru_meditation_report as gmr
+from oslo_reports import opts as gmr_opts
 
 from zaqar import bootstrap
 from zaqar.common import cli
 from zaqar.common import configs
+from zaqar import version
 
 # NOTE(eggmaster): define command line options for zaqar-server
 _CLI_OPTIONS = (
@@ -33,6 +36,7 @@ _CLI_OPTIONS = (
 def run():
     # Use the global CONF instance
     conf = cfg.CONF
+    gmr_opts.set_defaults(conf)
     # NOTE(eggmaster): register command line options for zaqar-server
     conf.register_cli_opts(_CLI_OPTIONS)
     log.register_options(conf)
@@ -46,6 +50,8 @@ def run():
     conf(project='zaqar', prog='zaqar-server')
     log.setup(conf, 'zaqar')
 
+    gmr.TextGuruMeditation.setup_autorun(version, conf=conf)
+
     server = bootstrap.Bootstrap(conf)
 
     # The following code is to daemonize zaqar-server to avoid
diff --git a/zaqar/transport/wsgi/app.py b/zaqar/transport/wsgi/app.py
index 6c3098a53..ff4909114 100644
--- a/zaqar/transport/wsgi/app.py
+++ b/zaqar/transport/wsgi/app.py
@@ -28,15 +28,21 @@ to the WSGI app when it is called from other apps.
 
 from oslo_config import cfg
 from oslo_log import log
+from oslo_reports import guru_meditation_report as gmr
+from oslo_reports import opts as gmr_opts
 
 from zaqar import bootstrap
+from zaqar import version
 
 # Use the global CONF instance
 conf = cfg.CONF
+gmr_opts.set_defaults(conf)
 log.register_options(conf)
 conf(project='zaqar', prog='zaqar-queues', args=[])
 log.setup(conf, 'zaqar')
 
+gmr.TextGuruMeditation.setup_autorun(version, conf=conf)
+
 boot = bootstrap.Bootstrap(conf)
 conf.drivers.transport = 'wsgi'
 application = boot.transport.app
diff --git a/zaqar/version.py b/zaqar/version.py
index cfd53a648..352b2f228 100644
--- a/zaqar/version.py
+++ b/zaqar/version.py
@@ -17,6 +17,7 @@ import pbr.version
 
 
 version_info = pbr.version.VersionInfo('zaqar')
+version_string = version_info.version_string
 
 
 def verify_sha(expected):