Commit 62318bb5 authored by Michal 'vorner' Vaner's avatar Michal 'vorner' Vaner
Browse files

Merge branch 'work/pylog'

parents f3813c74 9723ecc5
......@@ -885,8 +885,8 @@ AC_OUTPUT([doc/version.ent
src/lib/config/tests/data_def_unittests_config.h
src/lib/python/isc/config/tests/config_test
src/lib/python/isc/cc/tests/cc_test
src/lib/python/isc/log/tests/log_test
src/lib/python/isc/notify/tests/notify_out_test
src/lib/python/isc/log/tests/log_console.py
src/lib/dns/gen-rdatacode.py
src/lib/python/bind10_config.py
src/lib/dns/tests/testdata/gen-wiredata.py
......@@ -928,6 +928,7 @@ AC_OUTPUT([doc/version.ent
chmod +x src/lib/log/tests/destination_test.sh
chmod +x src/lib/log/tests/severity_test.sh
chmod +x src/lib/util/python/mkpywrapper.py
chmod +x src/lib/python/isc/log/tests/log_console.py
chmod +x tests/system/conf.sh
])
AC_OUTPUT
......
......@@ -116,8 +116,8 @@ class TestXfroutSession(unittest.TestCase):
def setUp(self):
self.sock = MySocket(socket.AF_INET,socket.SOCK_STREAM)
self.log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(), self.log, TSIGKeyRing())
#self.log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(), TSIGKeyRing())
self.mdata = bytes(b'\xd6=\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\xfc\x00\x01')
self.soa_record = (4, 3, 'example.com.', 'com.example.', 3600, 'SOA', None, 'master.example.com. admin.example.com. 1234 3600 1800 2419200 7200')
......@@ -520,7 +520,7 @@ class MyUnixSockServer(UnixSockServer):
self._shutdown_event = threading.Event()
self._max_transfers_out = 10
self._cc = MyCCSession()
self._log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
#self._log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
class TestUnixSockServer(unittest.TestCase):
def setUp(self):
......
......@@ -26,7 +26,7 @@ from isc.datasrc import sqlite3_ds
from socketserver import *
import os
from isc.config.ccsession import *
from isc.log.log import *
#from isc.log.log import *
from isc.cc import SessionError, SessionTimeout
from isc.notify import notify_out
import isc.util.process
......@@ -88,13 +88,13 @@ def get_rrset_len(rrset):
class XfroutSession():
def __init__(self, sock_fd, request_data, server, log, tsig_key_ring):
def __init__(self, sock_fd, request_data, server, tsig_key_ring):
# The initializer for the superclass may call functions
# that need _log to be set, so we set it first
self._sock_fd = sock_fd
self._request_data = request_data
self._server = server
self._log = log
#self._log = log
self._tsig_key_ring = tsig_key_ring
self._tsig_ctx = None
self._tsig_len = 0
......@@ -110,7 +110,8 @@ class XfroutSession():
self.dns_xfrout_start(self._sock_fd, self._request_data)
#TODO, avoid catching all exceptions
except Exception as e:
self._log.log_message("error", str(e))
#self._log.log_message("error", str(e))
pass
os.close(self._sock_fd)
......@@ -137,7 +138,7 @@ class XfroutSession():
rcode = self._check_request_tsig(msg, mdata)
except Exception as err:
self._log.log_message("error", str(err))
#self._log.log_message("error", str(err))
return Rcode.FORMERR(), None
return rcode, msg
......@@ -244,16 +245,17 @@ class XfroutSession():
zone_name = self._get_query_zone_name(msg)
rcode_ = self._check_xfrout_available(zone_name)
if rcode_ != Rcode.NOERROR():
self._log.log_message("info", "transfer of '%s/IN' failed: %s",
zone_name, rcode_.to_text())
#self._log.log_message("info", "transfer of '%s/IN' failed: %s",
# zone_name, rcode_.to_text())
return self. _reply_query_with_error_rcode(msg, sock_fd, rcode_)
try:
self._log.log_message("info", "transfer of '%s/IN': AXFR started" % zone_name)
#self._log.log_message("info", "transfer of '%s/IN': AXFR started" % zone_name)
self._reply_xfrout_query(msg, sock_fd, zone_name)
self._log.log_message("info", "transfer of '%s/IN': AXFR end" % zone_name)
#self._log.log_message("info", "transfer of '%s/IN': AXFR end" % zone_name)
except Exception as err:
self._log.log_message("error", str(err))
#self._log.log_message("error", str(err))
pass
self._server.decrease_transfers_counter()
return
......@@ -317,7 +319,7 @@ class XfroutSession():
for rr_data in sqlite3_ds.get_zone_datas(zone_name, self._server.get_db_file()):
if self._server._shutdown_event.is_set(): # Check if xfrout is shutdown
self._log.log_message("info", "xfrout process is being shutdown")
#self._log.log_message("info", "xfrout process is being shutdown")
return
# TODO: RRType.SOA() ?
if RRType(rr_data[5]) == RRType("SOA"): #ignore soa record
......@@ -357,7 +359,7 @@ class XfroutSession():
class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
'''The unix domain socket server which accept xfr query sent from auth server.'''
def __init__(self, sock_file, handle_class, shutdown_event, config_data, cc, log):
def __init__(self, sock_file, handle_class, shutdown_event, config_data, cc):
self._remove_unused_sock_file(sock_file)
self._sock_file = sock_file
socketserver_mixin.NoPollMixIn.__init__(self)
......@@ -366,7 +368,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
self._transfers_counter = 0
self._shutdown_event = shutdown_event
self._write_sock, self._read_sock = socket.socketpair()
self._log = log
#self._log = log
self.update_config_data(config_data)
self._cc = cc
......@@ -394,7 +396,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
try:
request, client_address = self.get_request()
except socket.error:
self._log.log_message("error", "Failed to fetch request")
#self._log.log_message("error", "Failed to fetch request")
return
# Check self._shutdown_event to ensure the real shutdown comes.
......@@ -408,7 +410,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
(rlist, wlist, xlist) = ([], [], [])
continue
else:
self._log.log_message("error", "Error with select(): %s" %e)
#self._log.log_message("error", "Error with select(): %s" %e)
break
# self.server._shutdown_event will be set by now, if it is not a false
......@@ -419,8 +421,8 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
try:
self.process_request(request)
except:
self._log.log_message("error", "Exception happened during processing of %s"
% str(client_address))
#self._log.log_message("error", "Exception happened during processing of %s"
# % str(client_address))
break
def _handle_request_noblock(self):
......@@ -438,8 +440,8 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
# This may happen when one xfrout process try to connect to
# xfrout unix socket server, to check whether there is another
# xfrout running.
if sock_fd == FD_COMM_ERROR:
self._log.log_message("error", "Failed to receive the file descriptor for XFR connection")
#if sock_fd == FD_COMM_ERROR:
#self._log.log_message("error", "Failed to receive the file descriptor for XFR connection")
return
# receive request msg
......@@ -456,7 +458,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
def finish_request(self, sock_fd, request_data):
'''Finish one request by instantiating RequestHandlerClass.'''
self.RequestHandlerClass(sock_fd, request_data, self, self._log, self.tsig_key_ring)
self.RequestHandlerClass(sock_fd, request_data, self, self.tsig_key_ring)
def _remove_unused_sock_file(self, sock_file):
'''Try to remove the socket file. If the file is being used
......@@ -464,8 +466,8 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
If it's not a socket file or nobody is listening
, it will be removed. If it can't be removed, exit from python. '''
if self._sock_file_in_use(sock_file):
self._log.log_message("error", "Fail to start xfrout process, unix socket file '%s'"
" is being used by another xfrout process\n" % sock_file)
#self._log.log_message("error", "Fail to start xfrout process, unix socket file '%s'"
# " is being used by another xfrout process\n" % sock_file)
sys.exit(0)
else:
if not os.path.exists(sock_file):
......@@ -474,7 +476,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
try:
os.unlink(sock_file)
except OSError as err:
self._log.log_message("error", "[b10-xfrout] Fail to remove file %s: %s\n" % (sock_file, err))
#self._log.log_message("error", "[b10-xfrout] Fail to remove file %s: %s\n" % (sock_file, err))
sys.exit(0)
def _sock_file_in_use(self, sock_file):
......@@ -495,17 +497,18 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
try:
os.unlink(self._sock_file)
except Exception as e:
self._log.log_message('error', str(e))
#self._log.log_message('error', str(e))
pass
def update_config_data(self, new_config):
'''Apply the new config setting of xfrout module. '''
self._log.log_message('info', 'update config data start.')
#self._log.log_message('info', 'update config data start.')
self._lock.acquire()
self._max_transfers_out = new_config.get('transfers_out')
self.set_tsig_key_ring(new_config.get('tsig_key_ring'))
self._log.log_message('info', 'max transfer out : %d', self._max_transfers_out)
#self._log.log_message('info', 'max transfer out : %d', self._max_transfers_out)
self._lock.release()
self._log.log_message('info', 'update config data complete.')
#self._log.log_message('info', 'update config data complete.')
def set_tsig_key_ring(self, key_list):
"""Set the tsig_key_ring , given a TSIG key string list representation. """
......@@ -521,7 +524,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
self.tsig_key_ring.add(TSIGKey(key_item))
except InvalidParameter as ipe:
errmsg = "bad TSIG key string: " + str(key_item)
self._log.log_message('error', '%s' % errmsg)
#self._log.log_message('error', '%s' % errmsg)
def get_db_file(self):
file, is_default = self._cc.get_remote_config_value("Auth", "database_file")
......@@ -553,16 +556,16 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
class XfroutServer:
def __init__(self):
self._unix_socket_server = None
self._log = None
#self._log = None
self._listen_sock_file = UNIX_SOCKET_FILE
self._shutdown_event = threading.Event()
self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler)
self._config_data = self._cc.get_full_config()
self._cc.start()
self._cc.add_remote_config(AUTH_SPECFILE_LOCATION);
self._log = isc.log.NSLogger(self._config_data.get('log_name'), self._config_data.get('log_file'),
self._config_data.get('log_severity'), self._config_data.get('log_versions'),
self._config_data.get('log_max_bytes'), True)
#self._log = isc.log.NSLogger(self._config_data.get('log_name'), self._config_data.get('log_file'),
# self._config_data.get('log_severity'), self._config_data.get('log_versions'),
# self._config_data.get('log_max_bytes'), True)
self._start_xfr_query_listener()
self._start_notifier()
......@@ -570,13 +573,13 @@ class XfroutServer:
'''Start a new thread to accept xfr query. '''
self._unix_socket_server = UnixSockServer(self._listen_sock_file, XfroutSession,
self._shutdown_event, self._config_data,
self._cc, self._log);
self._cc)
listener = threading.Thread(target=self._unix_socket_server.serve_forever)
listener.start()
def _start_notifier(self):
datasrc = self._unix_socket_server.get_db_file()
self._notifier = notify_out.NotifyOut(datasrc, self._log)
self._notifier = notify_out.NotifyOut(datasrc)
self._notifier.dispatcher()
def send_notify(self, zone_name, zone_class):
......@@ -591,8 +594,8 @@ class XfroutServer:
continue
self._config_data[key] = new_config[key]
if self._log:
self._log.update_config(new_config)
#if self._log:
# self._log.update_config(new_config)
if self._unix_socket_server:
self._unix_socket_server.update_config_data(self._config_data)
......@@ -621,7 +624,7 @@ class XfroutServer:
def command_handler(self, cmd, args):
if cmd == "shutdown":
self._log.log_message("info", "Received shutdown command.")
#self._log.log_message("info", "Received shutdown command.")
self.shutdown()
answer = create_answer(0)
......@@ -629,8 +632,8 @@ class XfroutServer:
zone_name = args.get('zone_name')
zone_class = args.get('zone_class')
if zone_name and zone_class:
self._log.log_message("info", "zone '%s/%s': receive notify others command" \
% (zone_name, zone_class))
#self._log.log_message("info", "zone '%s/%s': receive notify others command" \
# % (zone_name, zone_class))
self.send_notify(zone_name, zone_class)
answer = create_answer(0)
else:
......
......@@ -266,12 +266,12 @@ writePythonFile(const string& file, MessageDictionary& dictionary) {
"# File created from " << message_file.fullName() << " on " <<
currentTime() << "\n" <<
"\n" <<
"import isc.log.message\n" <<
"import isc.log\n" <<
"\n";
vector<string> idents(sortedIdentifiers(dictionary));
BOOST_FOREACH(const string& ident, idents) {
pyfile << ident << " = isc.log.message.create(\"" <<
pyfile << ident << " = isc.log.create_message(\"" <<
ident << "\", \"" << quoteString(dictionary.getText(ident)) <<
"\")\n";
}
......
......@@ -2,4 +2,3 @@ import isc.datasrc
import isc.cc
import isc.config
#import isc.dns
import isc.log
SUBDIRS = . tests
SUBDIRS = tests
python_PYTHON = __init__.py log.py
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
pythondir = $(pyexecdir)/isc/log
pythondir = $(pyexecdir)/isc
python_LTLIBRARIES = log.la
log_la_SOURCES = log.cc
pytest:
$(SHELL) tests/log_test
log_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
log_la_LDFLAGS = $(PYTHON_LDFLAGS)
log_la_LDFLAGS += -module
log_la_LIBADD = $(top_builddir)/src/lib/log/liblog.la
log_la_LIBADD += $(PYTHON_LIB)
# This is not installed, it helps locate the module during tests
EXTRA_DIST = __init__.py
from isc.log.log import *
# Copyright (C) 2011 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# This file is not installed. The log.so is installed into the right place.
# It is only to find it in the .libs directory when we run as a test or
# from the build directory.
# But as nobody gives us the builddir explicitly (and we can't use generation
# from .in file, as it would put us into the builddir and we wouldn't be found)
# we guess from current directory. Any idea for something better? This should
# be enough for the tests, but would it work for B10_FROM_SOURCE as well?
# Should we look there? Or define something in bind10_config?
import os
cwd = os.getcwd()
pos = cwd.rfind('/src/')
import sys; sys.path.insert(0, cwd[:pos] + '/src/lib/python/isc/log/.libs')
from log import *
This diff is collapsed.
# Copyright (C) 2010 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""This module is to convert python logging module over
to log4python.
Copyright (C) 2010 Internet Systems Consortium.
To use, simply 'import isc.log.log' and log away!
"""
import os
import sys
import syslog
import logging
import logging.handlers
"""LEVELS: logging levels mapping
"""
LEVELS = {'debug' : logging.DEBUG,
'info' : logging.INFO,
'warning' : logging.WARNING,
'error' : logging.ERROR,
'critical' : logging.CRITICAL}
FORMATTER = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
TIME_FORMATTER = logging.Formatter("%(asctime)s.%(msecs)03d %(name)s: %(levelname)s: %(message)s",
"%d-%b-%Y %H:%M:%S")
def log_err(err_type, err_msg):
sys.stderr.write(err_type + ": " + "%s.\n" % str(err_msg)[str(err_msg).find(']')+1:])
class NSFileLogHandler(logging.handlers.RotatingFileHandler):
"""RotatingFileHandler: replace RotatingFileHandler with a custom handler"""
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0):
abs_file_name = self._get_abs_file_path(filename)
"""Create log directory beforehand, because the underlying logging framework won't
create non-exsiting log directory on writing logs.
"""
if not (os.path.exists(os.path.dirname(abs_file_name))):
os.makedirs(os.path.dirname(abs_file_name))
super(NSFileLogHandler, self).__init__(abs_file_name, mode, maxBytes,
backupCount, encoding, delay)
def handleError(self, record):
"""Overwrite handleError to provide more user-friendly error messages"""
if logging.raiseExceptions:
ei = sys.exc_info()
if (ei[1]):
sys.stderr.write("[b10-logging] : " + str(ei[1]))
def _get_abs_file_path(self, file_name):
""" Get absolute file path"""
# For a bare filename, log_dir will be set the current directory.
if not os.path.dirname(file_name):
abs_file_dir = os.getcwd()
else:
abs_file_dir = os.path.abspath(os.path.dirname(file_name))
abs_file_name = os.path.join(abs_file_dir, os.path.basename(file_name))
return abs_file_name
def shouldRollover(self, record):
"""Rewrite RotatingFileHandler.shouldRollover.
If the log file is deleted at runtime, a new file will be created.
"""
dfn = self.baseFilename
if (self.stream) and (not os.path.exists(dfn)): #Does log file exist?
self.stream = None
""" Log directory may be deleted while bind10 running or updated with a
non-existing directory. Need to create log directory beforehand, because
the underlying logging framework won't create non-exsiting log directory
on writing logs.
"""
if not (os.path.exists(os.path.dirname(dfn))): #Does log subdirectory exist?
os.makedirs(os.path.dirname(dfn))
self.stream = self._open()
return super(NSFileLogHandler, self).shouldRollover(record)
def update_config(self, file_name, backup_count, max_bytes):
"""Update RotatingFileHandler configuration.
Changes will be picked up in the next call to shouldRollover().
input:
log file name
max backup count
predetermined log file size
"""
abs_file_name = self._get_abs_file_path(file_name)
self.baseFilename = abs_file_name
self.maxBytes = max_bytes
self.backupCount = backup_count
class NSSysLogHandler(logging.Handler):
"""Replace SysLogHandler with a custom handler
A handler class which sends formatted logging records to a syslog
server.
"""
def __init__(self, ident, logopt=0, facility=syslog.LOG_USER):
"""Initialize a handler.
If facility is not specified, LOG_USER is used.
"""
super(NSSysLogHandler, self).__init__()
self._ident = ident
self._logopt = logopt
self._facility = facility
self._mappings = {
logging.DEBUG: syslog.LOG_DEBUG,
logging.INFO: syslog.LOG_INFO,
logging.WARNING: syslog.LOG_WARNING,
logging.ERROR: syslog.LOG_ERR,
logging.CRITICAL: syslog.LOG_CRIT,
}
def _encodeLevel(self, level):
"""Encoding the priority."""
return self._mappings.get(level, syslog.LOG_INFO)
def emit(self, record):
"""Emit a record.
The record is formatted, and then sent to the syslog server. If
exception information is present, it is NOT sent to the server.
"""
syslog.openlog(self._ident, self._logopt, self._facility)
msg = self.format(record)
prio = self._encodeLevel(record.levelno)
syslog.syslog(prio, msg)
syslog.closelog()
class NSLogger(logging.getLoggerClass()):
"""Override logging.logger behaviour."""
def __init__(self, log_name, log_file, severity='debug', versions=0,
max_bytes=0, log_to_console=True):
"""Initializes the logger with some specific parameters
If log_to_console is True, stream handler will be used;
else syslog handler will be used.
To disable file handler, set log_file = ''.
"""
self._log_name = log_name
self._log_file = log_file
self._severity = severity
self._versions = versions
self._max_bytes = max_bytes
super(NSLogger, self).__init__(self._log_name)
# Set up a specific logger with our desired output level
logLevel = LEVELS.get(self._severity, logging.NOTSET)
self.setLevel(logLevel)
self._file_handler = None
self._stream_handler = None
self._syslog_handler = None
self._add_rotate_handler(self._log_file, self._versions, self._max_bytes)
if log_to_console:
self._add_stream_handler()
else:
self._add_syslog_handler()
def _add_rotate_handler(self, log_file, backup_count, max_bytes):
"""Add a rotate file handler.
input:
log_file : the location of log file. Handler will not be created
if log_file=''
max_bytes : limit log growth
backup_count : max backup count
"""
if (log_file != 0 and log_file != ''):
try:
self._file_handler = NSFileLogHandler(filename = log_file,
maxBytes = max_bytes, backupCount = backup_count)
except (IOError, OSError) as e:
self._file_handler = None
log_err("[b10-logging] Add file handler fail", str(e))
return
self._file_handler.setFormatter(TIME_FORMATTER)
self.addHandler(self._file_handler)
def _add_stream_handler(self):
"""Add a stream handler.
sys.stderr will be used for logging output.
"""
self._stream_handler = logging.StreamHandler()
self._stream_handler.setFormatter(TIME_FORMATTER)
self.addHandler(self._stream_handler)
def _add_syslog_handler(self, nsfacility=syslog.LOG_USER):
"""Add a syslog handler.
If facility is not specified, LOG_USER is used.
The default severity level is INFO.
"""
self._syslog_handler = NSSysLogHandler('BIND10', facility = nsfacility)
self._syslog_handler.setFormatter(FORMATTER)
#set syslog handler severity level INFO
self._syslog_handler.setLevel(logging.INFO)
self.addHandler(self._syslog_handler)
def _update_rotate_handler(self, log_file, backup_count, max_bytes):
"""If the rotate file handler has been added to the logger, update its
configuration, or add it to the logger.
"""
if (self._file_handler in self.handlers):
if (log_file != 0 and log_file != ''):
self._file_handler.update_config(log_file, backup_count, max_bytes)
else:
"""If log file is empty, the handler will be removed."""
self._file_handler.flush()
self._file_handler.close()
self.removeHandler(self._file_handler)
else:
self._add_rotate_handler(log_file, backup_count, max_bytes)
def _get_config(self, config_data):
"""Get config data from module configuration"""
log_file_str = config_data.get('log_file')
if (log_file_str):
self._log_file = log_file_str
severity_str = config_data.get('log_severity')
if (severity_str):
self._severity = severity_str
versions_str = config_data.get('log_versions')
if (versions_str):
self._versions = int(versions_str)
max_bytes_str = config_data.get('log_max_bytes')
if (max_bytes_str):
self._max_bytes = int(max_bytes_str)
def update_config(self, config_data):
"""Update logger's configuration.
We can update logger's log level and its rotate file handler's configuration.
"""
self._get_config(config_data)