Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save garethgreenaway/74e809ef6b4beeb74f878e2485bca8e7 to your computer and use it in GitHub Desktop.
Save garethgreenaway/74e809ef6b4beeb74f878e2485bca8e7 to your computer and use it in GitHub Desktop.
diff --git a/salt/log/setup.py b/salt/log/setup.py
index 4c6d5dd8fd..6d74ee0274 100644
--- a/salt/log/setup.py
+++ b/salt/log/setup.py
@@ -48,6 +48,7 @@ from salt.log.handlers import (TemporaryLoggingHandler,
QueueHandler)
from salt.log.mixins import LoggingMixInMeta, NewStyleClassMixIn
+from salt.utils.ctx import RequestContext
LOG_LEVELS = {
'all': logging.NOTSET,
@@ -305,6 +306,18 @@ class SaltLoggingClass(six.with_metaclass(LoggingMixInMeta, LOGGING_LOGGER_CLASS
def _log(self, level, msg, args, exc_info=None, extra=None, # pylint: disable=arguments-differ
exc_info_on_loglevel=None):
# If both exc_info and exc_info_on_loglevel are both passed, let's fail
+ if extra is None:
+ extra = {}
+
+ current_jid = RequestContext.current.get('data', {}).get('jid', None)
+ log_fmt_jid = RequestContext.current.get('opts', {}).get('log_fmt_jid', None)
+
+ if current_jid is not None:
+ extra['jid'] = current_jid
+
+ if log_fmt_jid is not None:
+ extra['log_fmt_jid'] = log_fmt_jid
+
if exc_info and exc_info_on_loglevel:
raise RuntimeError(
'Only one of \'exc_info\' and \'exc_info_on_loglevel\' is '
@@ -335,6 +348,12 @@ class SaltLoggingClass(six.with_metaclass(LoggingMixInMeta, LOGGING_LOGGER_CLASS
func=None, extra=None, sinfo=None):
# Let's remove exc_info_on_loglevel from extra
exc_info_on_loglevel = extra.pop('exc_info_on_loglevel')
+
+ jid = extra.pop('jid', '')
+ log_fmt_jid = extra.pop('log_fmt_jid', '[JID: %(jid)s]')
+ if jid:
+ jid = log_fmt_jid % {'jid': jid}
+
if not extra:
# If nothing else is in extra, make it None
extra = None
@@ -393,6 +412,7 @@ class SaltLoggingClass(six.with_metaclass(LoggingMixInMeta, LOGGING_LOGGER_CLASS
logrecord.exc_info_on_loglevel_formatted = None
logrecord.exc_info_on_loglevel = exc_info_on_loglevel
+ logrecord.jid = jid
return logrecord
# pylint: enable=C0103
diff --git a/salt/master.py b/salt/master.py
index 650dda3ead..dff9a27adf 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -8,6 +8,7 @@ involves preparing the three listeners and the workers needed by the master.
from __future__ import absolute_import, with_statement, print_function, unicode_literals
import copy
import ctypes
+import functools
import os
import re
import sys
@@ -90,6 +91,9 @@ try:
except ImportError:
HAS_HALITE = False
+from tornado.stack_context import StackContext
+from salt.utils.ctx import RequestContext
+
log = logging.getLogger(__name__)
@@ -1106,7 +1110,15 @@ class MWorker(salt.utils.process.SignalHandlingMultiprocessingProcess):
if self.opts['master_stats']:
start = time.time()
self.stats[cmd]['runs'] += 1
- ret = self.aes_funcs.run_func(data['cmd'], data)
+
+ def run_func(data):
+ return self.aes_funcs.run_func(data['cmd'], data)
+
+ with StackContext(functools.partial(RequestContext,
+ {'data': data,
+ 'opts': self.opts})):
+ ret = run_func(data)
+
if self.opts['master_stats']:
self._post_stats(start, cmd)
return ret
diff --git a/salt/minion.py b/salt/minion.py
index edecfcef5c..3c08e923dc 100644
--- a/salt/minion.py
+++ b/salt/minion.py
@@ -4,6 +4,7 @@ Routines to set up a minion
'''
# Import python libs
from __future__ import absolute_import, print_function, with_statement, unicode_literals
+import functools
import os
import re
import sys
@@ -33,6 +34,8 @@ else:
from salt.ext.six.moves import range
from salt.utils.zeromq import zmq, ZMQDefaultLoop, install_zmq, ZMQ_VERSION_INFO
+from salt.utils.ctx import RequestContext
+
# pylint: enable=no-name-in-module,redefined-builtin
import tornado
@@ -1534,11 +1537,16 @@ class Minion(MinionBase):
get_proc_dir(opts['cachedir'], uid=uid)
)
- with tornado.stack_context.StackContext(minion_instance.ctx):
+ def run_func(minion_instance, opts, data):
if isinstance(data['fun'], tuple) or isinstance(data['fun'], list):
- Minion._thread_multi_return(minion_instance, opts, data)
+ return Minion._thread_multi_return(minion_instance, opts, data)
else:
- Minion._thread_return(minion_instance, opts, data)
+ return Minion._thread_return(minion_instance, opts, data)
+
+ with tornado.stack_context.StackContext(functools.partial(RequestContext,
+ {'data': data, 'opts': opts})):
+ with tornado.stack_context.StackContext(minion_instance.ctx):
+ run_func(minion_instance, opts, data)
@classmethod
def _thread_return(cls, minion_instance, opts, data):
diff --git a/salt/utils/ctx.py b/salt/utils/ctx.py
new file mode 100644
index 0000000000..e80f8415ac
--- /dev/null
+++ b/salt/utils/ctx.py
@@ -0,0 +1,47 @@
+import threading
+
+class ClassProperty(property):
+ '''
+ Use a classmethod as a property
+ http://stackoverflow.com/a/1383402/1258307
+ '''
+ def __get__(self, cls, owner):
+ return self.fget.__get__(None, owner)() # pylint: disable=no-member
+
+
+class RequestContext(object):
+ '''
+ A context manager that saves some per-thread state globally.
+ Intended for use with Tornado's StackContext.
+ https://gist.github.com/simon-weber/7755289
+ Simply import this class into any module and access the current request handler by this
+ class's class method property 'current'. If it returns None, there's no active request.
+ .. code:: python
+ from salt.utils.ctx import RequestContext
+ current_request_handler = RequestContext.current
+ '''
+
+ _state = threading.local()
+ _state.current_request = {}
+
+ def __init__(self, current_request):
+ self._current_request = current_request
+
+ @ClassProperty
+ @classmethod
+ def current(cls):
+ if not hasattr(cls._state, 'current_request'):
+ return {}
+ return cls._state.current_request
+
+ def __enter__(self):
+ self._prev_request = self.__class__.current
+ self.__class__._state.current_request = self._current_request
+
+ def __exit__(self, *exc):
+ self.__class__._state.current_request = self._prev_request
+ del self._prev_request
+ return False
+
+ def __call__(self):
+ return self
diff --git a/salt/utils/decorators/jinja.py b/salt/utils/decorators/jinja.py
index f61efb2ac1..22d68369cf 100644
--- a/salt/utils/decorators/jinja.py
+++ b/salt/utils/decorators/jinja.py
@@ -5,7 +5,8 @@ Jinja-specific decorators
from __future__ import absolute_import, print_function, unicode_literals
# Import Python libs
-import logging
+# Ensure we're using the custom logging from Salt
+import salt.log.setup as logging
log = logging.getLogger(__name__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment