Commit dae1d2e2 authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[trac710] Merge branch 'master' into trac710

Conflicts:
	src/bin/cfgmgr/plugins/Makefile.am
	src/lib/python/isc/log/Makefile.am
parents ed6ec070 8cad0814
......@@ -887,12 +887,6 @@ AC_OUTPUT([doc/version.ent
src/bin/zonemgr/run_b10-zonemgr.sh
src/bin/stats/stats.py
src/bin/stats/stats_httpd.py
src/bin/stats/stats.spec
src/bin/stats/stats-schema.spec
src/bin/stats/stats-httpd.spec
src/bin/stats/stats-httpd-xml.tpl
src/bin/stats/stats-httpd-xsd.tpl
src/bin/stats/stats-httpd-xsl.tpl
src/bin/bind10/bind10.py
src/bin/bind10/run_bind10.sh
src/bin/bind10/tests/bind10_test.py
......@@ -914,8 +908,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
......@@ -957,6 +951,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
......
......@@ -4,6 +4,7 @@ EXTRA_DIST += logging.spec b10logging.py
config_plugindir = @prefix@/share/@PACKAGE@/config_plugins
config_plugin_DATA = tsig_keys.py tsig_keys.spec
config_plugin_DATA += b10logging.py logging.spec
CLEANDIRS = __pycache__
......
......@@ -118,7 +118,7 @@ of the body of the message failed due to some non-protocol related reason
(although the parsing of the header succeeded). The message parameters give
a textual description of the problem and the RCODE returned.
% PRINTMSG print message command, aeguments are: %1
% PRINTMSG print message command, arguments are: %1
This message is logged when a "print_message" command is received over the
command channel.
......@@ -169,7 +169,7 @@ resolver gives up trying to resolve a query. Retry count: the number of times
the resolver will retry a query to an upstream server if it gets a timeout.
The client and lookup timeouts require a bit more explanation. The
resolution of the clent query might require a large number of queries to
resolution of the client query might require a large number of queries to
upstream nameservers. Even if none of these queries timeout, the total time
taken to perform all the queries may exceed the client timeout. When this
happens, a SERVFAIL is returned to the client, but the resolver continues
......
......@@ -20,5 +20,5 @@ endif
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/util/io/.libs \
$(LIBRARY_PATH_PLACEHOLDER) \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
done
......@@ -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:
......
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
TESTS =
if HAVE_GTEST
......
......@@ -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
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
log_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
# Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be
# placed after -Wextra defined in AM_CXXFLAGS
log_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
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
pytest:
$(SHELL) tests/log_test
......
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