Skip to content

Commit

Permalink
Encoders fo logging.
Browse files Browse the repository at this point in the history
  • Loading branch information
idlesign committed Jul 9, 2017
1 parent 9461d83 commit 10e2ecd
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 26 deletions.
33 changes: 32 additions & 1 deletion tests/options/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@

def test_logging_basics(assert_lines):

logging = Section().logging

assert_lines([
'disable-logging = true',
], Section().logging.set_basic_params(no_requests=True))
'log-format = %(method) --> %(uri)',

], logging.set_basic_params(
no_requests=True,
template='%s --> %s' % (logging.Vars.REQ_METHOD, logging.Vars.REQ_URL)
))

assert_lines([
'log-reopen = true',
Expand Down Expand Up @@ -77,3 +84,27 @@ def test_logging_add_logger(assert_lines):
assert_lines([
'logger = my zeromq:tcp://192.168.173.18:9191',
], logging.add_logger(logging.cls_logger_zeromq('my', 'tcp://192.168.173.18:9191')))


def test_logging_add_logger_encoder(assert_lines):

logging = Section().logging

assert_lines([
'worker-log-encoder = prefix -->',
'worker-log-encoder = suffix <--',

], logging.add_logger_encoder([
logging.cls_encoder_prefix('-->'),
logging.cls_encoder_suffix('<--'),
], for_single_worker=True))

logging = Section().logging
enc_format = logging.cls_encoder_format

assert_lines([
'log-encoder = format > ${msg} <:myfile',

], logging.add_logger_encoder([
enc_format('> %s <' % enc_format.Vars.MESSAGE),
], logger=logging.cls_logger_file('myfile', '/home/here.log')))
145 changes: 123 additions & 22 deletions uwsgiconf/options/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
from ..utils import listify


class LoggerBase(object):
class Logger(object):
"""Base for loggers."""

plugin = None

def __init__(self, alias, *args):
self.name = alias or ''
self.alias = alias or ''
self.args = args

def __str__(self):
Expand All @@ -19,10 +19,10 @@ def __str__(self):
if args:
chunks.append(':%s' % ','.join(args))

return '%s %s' % (self.name, ''.join(chunks))
return '%s %s' % (self.alias, ''.join(chunks))


class FileLogger(LoggerBase):
class FileLogger(Logger):
"""Allows logging into files."""

plugin = 'file'
Expand All @@ -37,7 +37,7 @@ def __init__(self, alias, filepath):
super(FileLogger, self).__init__(alias, filepath)


class SocketLogger(LoggerBase):
class SocketLogger(Logger):
"""Allows logging into UNIX and UDP sockets."""

plugin = 'socket'
Expand All @@ -56,7 +56,7 @@ def __init__(self, alias, addr_or_path):
super(SocketLogger, self).__init__(alias, addr_or_path)


class SyslogLogger(LoggerBase):
class SyslogLogger(Logger):
"""Allows logging into Unix standard syslog or a remote syslog."""

plugin = 'syslog'
Expand All @@ -83,7 +83,7 @@ def __init__(self, alias, app_name=None, facility=None, host=None):
super(SyslogLogger, self).__init__(alias, *args)


class RedisLogger(LoggerBase):
class RedisLogger(Logger):
"""Allows logging into Redis.
.. note:: Consider using ``dedicate_thread`` param.
Expand All @@ -110,7 +110,7 @@ def __init__(self, alias, host=None, command=None, prefix=None):
super(RedisLogger, self).__init__(alias, host, command, prefix)


class MongoLogger(LoggerBase):
class MongoLogger(Logger):
"""Allows logging into Mongo DB.
.. note:: Consider using ``dedicate_thread`` param.
Expand All @@ -134,7 +134,7 @@ def __init__(self, alias, host=None, collection=None, node=None):
super(MongoLogger, self).__init__(alias, host, collection, node)


class ZeroMqLogger(LoggerBase):
class ZeroMqLogger(Logger):
"""Allows logging into ZeroMQ sockets."""

plugin = 'zeromq'
Expand All @@ -152,6 +152,94 @@ def __init__(self, alias, connection_str):
super(ZeroMqLogger, self).__init__(alias, connection_str)


class Encoder(object):
"""Base for logger encoders."""

name = None

def __init__(self, *args):
self.args = args

def __str__(self):
return '%s %s' % (self.name, self.args[0])


class PrefixEncoder(Encoder):
"""Add a raw prefix to each log msg."""

name = 'prefix'

def __init__(self, value):
"""
:param str|unicode value: Value to be used as affix
"""
super(PrefixEncoder, self).__init__(value)


class SuffixEncoder(PrefixEncoder):
"""Add a raw suffix to each log msg"""

name = 'suffix'


class NewlineEncoder(Encoder):
"""Add a newline char to each log msg."""

name = 'nl'


class GzipEncoder(Encoder):
"""Compress each msg with gzip (requires zlib)."""

name = 'gzip'


class CompressEncoder(Encoder):
"""Compress each msg with zlib compress (requires zlib)."""

name = 'compress'


class FormatEncoder(Encoder):
"""Apply the specified format to each log msg."""

name = 'format'

def __init__(self, template):
"""
:param str|unicode template: Template string.
Available variables are listed in ``FormatEncoder.Vars``.
"""
super(FormatEncoder, self).__init__(template)

class Vars(object):
"""Variables available to use."""

MESSAGE = '${msg}'
'''Raw log message (newline stripped).'''

MESSAGE_NEWLINE = '${msgnl}'
'''Raw log message (with newline).'''

TIME = '${unix}'
'''Current unix time.'''

TIME_MS = '${micros}'
'''Current unix time in microseconds.'''

# todo consider adding ${strftime:xxx} - strftime using the xxx format


class JsonEncoder(FormatEncoder):
"""Apply the specified format to each log msg with each variable json escaped."""

name = 'json'


class Logging(OptionsGroup):
"""Logging.
Expand All @@ -166,18 +254,27 @@ class Logging(OptionsGroup):
cls_logger_redis = RedisLogger
cls_logger_mongo = MongoLogger
cls_logger_zeromq = ZeroMqLogger

# todo consider adding other loggers: crypto, graylog2, systemd

cls_encoder_prefix = PrefixEncoder
cls_encoder_suffix = SuffixEncoder
cls_encoder_newline = NewlineEncoder
cls_encoder_gzip = GzipEncoder
cls_encoder_compress = CompressEncoder
cls_encoder_format = FormatEncoder
cls_encoder_json = JsonEncoder
# todo consider adding msgpack encoder

def set_basic_params(
self, no_requests=None, fmt=None, memory_report=None, prefix=None, prefix_date=None,
self, no_requests=None, template=None, memory_report=None, prefix=None, prefix_date=None,
apply_strftime=None, response_ms=None, ip_x_forwarded=None):
"""
:param bool no_requests: Disable requests logging - only uWSGI internal messages
and errors will be logged.
:param str|unicode fmt: Set advanced format for request logging.
:param str|unicode template: Set advanced format for request logging.
This template string can use variables from ``Logging.Vars``.
:param str|unicode prefix: Prefix log items with a string.
Expand All @@ -196,7 +293,7 @@ def set_basic_params(
"""
self._set('disable-logging', no_requests, cast=bool)
self._set('log-format', fmt)
self._set('log-format', template)
self._set('memory-report', memory_report)
self._set('log-prefix', prefix)
self._set('log-date', prefix_date, cast=bool)
Expand Down Expand Up @@ -373,27 +470,31 @@ def add_logger_encoder(self, encoder, logger=None, requests_only=False, for_sing
.. note:: For best performance consider allocating a thread
for log sending with ``threaded-logger``.
:param str|unicode|list encoder: Encoder to add into processing.
:param str|unicode|list|Encoder encoder: Encoder (or a list) to add into processing.
:param str|unicode|list|Logger logger:
:param str|unicode|Logger logger: Logger apply associate encoders to.
:param bool requests_only: Encoder to be used only for requests information messages.
:param bool for_single_worker: Encoder to be used in single-worker setup.
"""
# todo implement
value = ''

if logger:
value += ':%s' % logger.alias

if for_single_worker:
command = 'worker-log-req-encoder' if requests_only else 'worker-log-encoder'
else:
command = 'log-req-encoder' if requests_only else 'log-encoder'

self._set(command, value, multi=True)
for encoder in listify(encoder):

value = '%s' % encoder

if logger:
if isinstance(logger, Logger):
logger = logger.alias

value += ':%s' % logger

self._set(command, value, multi=True)

return self._section

Expand Down
6 changes: 3 additions & 3 deletions uwsgiconf/options/main_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,22 +181,22 @@ def set_pid_file(self, fpath, before_priv_drop=True, safe=False):

return self._section

def set_naming_params(self, autonaming=None, prefix=None, postfix=None, name=None):
def set_naming_params(self, autonaming=None, prefix=None, suffix=None, name=None):
"""Setups processes naming parameters.
:param bool autonaming: Automatically set process name to something meaningful.
Generated process names may be 'uWSGI Master', 'uWSGI Worker #', etc.
:param str prefix: Add prefix to process names.
:param str postfix: Append string to process names.
:param str suffix: Append string to process names.
:param str name: Set process names to given static value.
"""
self._set('auto-procname', autonaming, cast=bool)
self._set('procname-prefix%s' % ('-spaced' if prefix and prefix.endswith(' ') else ''), prefix)
self._set('procname-append', postfix)
self._set('procname-append', suffix)
self._set('procname', name)

return self._section

0 comments on commit 10e2ecd

Please sign in to comment.