# -*- coding: utf-8 -*-
#
# Univention Management Console
# logging module for UMC
#
# Copyright 2011-2022 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.
"""
Logging
=======
This module provides a wrapper for univention.debug
"""
import univention.debug as ud
import logging
import grp
import os
from univention.config_registry import ConfigRegistry
# no exceptions from logging
# otherwise shutdown the server will raise an exception that the logging stream could not be closed
logging.raiseExceptions = 0
#: list of available debugging components
COMPONENTS = (ud.MAIN, ud.LDAP, ud.NETWORK, ud.SSL, ud.ADMIN, ud.MODULE, ud.AUTH, ud.PARSER, ud.LOCALE, ud.ACL, ud.RESOURCES, ud.PROTOCOL)
_ucr = ConfigRegistry()
_debug_ready = False
_debug_loglevel = 2
_log_pid = None
def _reset_debug_loglevel():
global _debug_loglevel
_ucr.load()
_debug_loglevel = max(int(_ucr.get('umc/server/debug/level', 2)), int(_ucr.get('umc/module/debug/level', 2)))
_reset_debug_loglevel()
[docs]def log_init(filename, log_level=2, log_pid=None):
"""Initializes Univention debug.
:param str filename: The filename just needs to be a relative name. The directory /var/log/univention/ is prepended and the suffix '.log' is appended.
:param int log_level: log level to use (1-4)
:param bool log_pid: Prefix log message with process ID
"""
if filename[0] != '/':
filename = '/var/log/univention/%s.log' % filename
fd = ud.init(filename, ud.FLUSH, ud.NO_FUNCTION)
adm = grp.getgrnam('adm')
os.chown(filename, 0, adm.gr_gid)
os.chmod(filename, 0o640)
log_set_level(log_level)
global _debug_ready, _log_pid
_debug_ready = True
if log_pid is not None:
_log_pid = log_pid
return fd
[docs]def log_set_level(level=0):
"""Sets the log level for all components.
:param int level: log level to set
"""
for component in COMPONENTS:
ud.set_level(component, level)
[docs]def log_reopen():
"""Reopenes the logfile and reset the current loglevel"""
if not _debug_ready:
return
ud.reopen()
_reset_debug_loglevel()
log_set_level(_debug_loglevel)
[docs]class ILogger(object):
"""This class provides a simple interface to access the univention
debug function for the given component.
:param int id: id of the component to use
"""
def __init__(self, id):
self._id = getattr(ud, id)
fallbackLoggingFormatter = logging.Formatter('%%(asctime)s.%%(msecs)03d %(component)-11s ( %%(level)-7s ) : %%(message)s' % {'component': id}, '%d.%m.%y %H:%M:%S')
fallbackLoggingHandler = logging.StreamHandler()
fallbackLoggingHandler.setFormatter(fallbackLoggingFormatter)
self._fallbackLogger = logging.getLogger('UMC.%s' % id)
self._fallbackLogger.setLevel(logging.DEBUG)
self._fallbackLogger.addHandler(fallbackLoggingHandler)
self._extras = [
{'level': 'ERROR'},
{'level': 'WARN'},
{'level': 'PROCESS'},
{'level': 'INFO'},
]
[docs] def error(self, message):
"""Write a debug message with level ERROR"""
self.__log(ud.ERROR, message, self._fallbackLogger.error)
[docs] def warn(self, message):
"""Write a debug message with level WARN"""
self.__log(ud.WARN, message, self._fallbackLogger.warning)
[docs] def process(self, message):
"""Write a debug message with level PROCESS"""
self.__log(ud.PROCESS, message, self._fallbackLogger.info)
[docs] def info(self, message):
"""Write a debug message with level INFO"""
self.__log(ud.INFO, message, self._fallbackLogger.debug)
def __log(self, level, message, logger):
if _log_pid:
message = '%s: %s' % (os.getpid(), message)
if _debug_ready:
try:
ud.debug(self._id, level, message)
except TypeError:
ud.debug(self._id, ud.ERROR, 'Could not log message %r' % (message,))
elif _debug_loglevel >= level:
logger(message, extra=self._extras[level])
CORE = ILogger('MAIN')
NETWORK = ILogger('NETWORK')
CRYPT = ILogger('SSL')
UDM = ILogger('ADMIN')
MODULE = ILogger('MODULE')
AUTH = ILogger('AUTH')
PARSER = ILogger('PARSER')
LOCALE = ILogger('LOCALE')
ACL = ILogger('ACL')
RESOURCES = ILogger('RESOURCES')
PROTOCOL = ILogger('PROTOCOL')