Added file logging and a new parameter (-s) for logging to stdout.
This commit is contained in:
parent
1d89481e51
commit
dbb0e23091
5 changed files with 66 additions and 18 deletions
|
|
@ -22,19 +22,20 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging
|
||||||
|
import logging.handlers
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from logging import getLogger
|
|
||||||
|
|
||||||
from linspector.core.configuration import Configuration
|
from linspector.core.configuration import Configuration
|
||||||
from linspector.core.environment import Environment
|
from linspector.core.environment import Environment
|
||||||
from linspector.core.linspector import Linspector
|
from linspector.core.linspector import Linspector
|
||||||
from linspector.core.monitors import Monitors
|
from linspector.core.monitors import Monitors
|
||||||
|
|
||||||
__version__ = '0.18'
|
__version__ = '0.18.1'
|
||||||
__author__ = 'Johannes Findeisen <you@hanez.org>'
|
__author__ = 'Johannes Findeisen <you@hanez.org>'
|
||||||
|
|
||||||
logger = getLogger('linspector')
|
logger = logging.getLogger('linspector')
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
|
|
@ -57,6 +58,9 @@ def parse_args():
|
||||||
parser.add_argument('-r', '--restart', default=False, dest='restart', action='store_true',
|
parser.add_argument('-r', '--restart', default=False, dest='restart', action='store_true',
|
||||||
help='restart the daemon if it is running(default: false)')
|
help='restart the daemon if it is running(default: false)')
|
||||||
|
|
||||||
|
parser.add_argument('-s', '--stdout', default=False, dest='stdout', action='store_true',
|
||||||
|
help='log to stdout')
|
||||||
|
|
||||||
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + str(__version__))
|
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + str(__version__))
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
@ -64,7 +68,6 @@ def parse_args():
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|
||||||
environment = Environment()
|
environment = Environment()
|
||||||
monitors = None
|
monitors = None
|
||||||
notifications = {}
|
notifications = {}
|
||||||
|
|
@ -72,13 +75,50 @@ def main():
|
||||||
services = {}
|
services = {}
|
||||||
tasks = {}
|
tasks = {}
|
||||||
|
|
||||||
|
if args.stdout:
|
||||||
|
# setting pre initialization default log level to INFO. this changes after initialization
|
||||||
|
# of the configuration. maybe there are better solutions...?
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
stdout_formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s')
|
||||||
|
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||||
|
stdout_handler.setFormatter(stdout_formatter)
|
||||||
|
logger.addHandler(stdout_handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
configuration = Configuration(args.configuration_path, environment)
|
configuration = Configuration(args.configuration_path, environment)
|
||||||
#configuration.dump_to_ini()
|
#configuration.dump_to_ini()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error('[linspector] configuration error: {0}'.format(err))
|
logger.critical('[linspector] configuration error: {0}'.format(err))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if configuration.get_option('linspector', 'log_file'):
|
||||||
|
log_file = os.path.expanduser(configuration.get_option('linspector', 'log_file'))
|
||||||
|
if not os.path.exists(os.path.dirname(log_file)):
|
||||||
|
os.makedirs(os.path.dirname(log_file))
|
||||||
|
|
||||||
|
log_file_formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s')
|
||||||
|
log_file_handler = logging.handlers.RotatingFileHandler(log_file,
|
||||||
|
maxBytes=int(
|
||||||
|
configuration.get_option(
|
||||||
|
'linspector', 'log_size')),
|
||||||
|
backupCount=int(
|
||||||
|
configuration.get_option(
|
||||||
|
'linspector', 'log_count')))
|
||||||
|
log_file_handler.setFormatter(log_file_formatter)
|
||||||
|
logger.addHandler(log_file_handler)
|
||||||
|
|
||||||
|
# critical errors will always show up even when no log_level is set. this is most silent.
|
||||||
|
logger.setLevel(logging.CRITICAL)
|
||||||
|
log_level = configuration.get_option('linspector', 'log_level')
|
||||||
|
if log_level == "error":
|
||||||
|
logger.setLevel(logging.ERROR)
|
||||||
|
elif log_level == "warning":
|
||||||
|
logger.setLevel(logging.WARNING)
|
||||||
|
elif log_level == "info":
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
elif log_level == "debug":
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
monitors = Monitors(configuration, environment, notifications, services, tasks)
|
monitors = Monitors(configuration, environment, notifications, services, tasks)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
|
@ -87,7 +127,7 @@ def main():
|
||||||
try:
|
try:
|
||||||
linspector = Linspector(configuration, environment, monitors, plugins)
|
linspector = Linspector(configuration, environment, monitors, plugins)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error('[linspector] core initialization error: {0}'.format(err))
|
logger.critical('[linspector] core initialization error: {0}'.format(err))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# daemon initialization
|
# daemon initialization
|
||||||
|
|
@ -103,7 +143,7 @@ def main():
|
||||||
else:
|
else:
|
||||||
linspectord.start()
|
linspectord.start()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error('[linspector] daemon initialization error: {0}'.format(err))
|
logger.critical('[linspector] daemon error: {0}'.format(err))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
; report core errors to the following users
|
; report core errors to the following users
|
||||||
error_receivers = admin@example.com
|
error_receivers = admin@example.com
|
||||||
log_file = ~/code/linspector/log/linspector.log
|
log_file = ~/code/linspector/log/linspector.log
|
||||||
log_level= verbose
|
; available log levels are: "error", "warning", "info" and "debug".
|
||||||
|
log_level= debug
|
||||||
log_count = 5
|
log_count = 5
|
||||||
log_size = 10485760
|
log_size = 10485760
|
||||||
pid_file = /var/run/user/1000/linspector.pid
|
pid_file = /var/run/user/1000/linspector.pid
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class Configuration:
|
||||||
self.__configuration_path = configuration_path
|
self.__configuration_path = configuration_path
|
||||||
self.__environment = environment
|
self.__environment = environment
|
||||||
|
|
||||||
|
logger.info('reading configuration file: ' + configuration_path + '/linspector.conf')
|
||||||
if os.path.isfile(configuration_path + '/linspector.conf'):
|
if os.path.isfile(configuration_path + '/linspector.conf'):
|
||||||
try:
|
try:
|
||||||
self.__configuration.read(configuration_path + '/linspector.conf', 'utf-8')
|
self.__configuration.read(configuration_path + '/linspector.conf', 'utf-8')
|
||||||
|
|
@ -39,7 +40,7 @@ class Configuration:
|
||||||
|
|
||||||
section_list = glob.glob(configuration_path + '/' + target_section + '/*.conf')
|
section_list = glob.glob(configuration_path + '/' + target_section + '/*.conf')
|
||||||
for section_file in section_list:
|
for section_file in section_list:
|
||||||
#print(__file__ + ' (60): ' + section_file)
|
#print(__file__ + ' (45): ' + section_file)
|
||||||
configuration = configparser.ConfigParser()
|
configuration = configparser.ConfigParser()
|
||||||
configuration.read(section_file, 'utf-8')
|
configuration.read(section_file, 'utf-8')
|
||||||
for source_section in configuration.sections():
|
for source_section in configuration.sections():
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,13 @@ class Linspector:
|
||||||
self.__plugins = plugins
|
self.__plugins = plugins
|
||||||
|
|
||||||
# load plugins
|
# load plugins
|
||||||
|
logger.info('loading plugins...')
|
||||||
if configuration.get_option('linspector', 'plugins'):
|
if configuration.get_option('linspector', 'plugins'):
|
||||||
plugin_list = configuration.get_option('linspector', 'plugins')
|
plugin_list = configuration.get_option('linspector', 'plugins')
|
||||||
self.__plugin_list = plugin_list.split(',')
|
self.__plugin_list = plugin_list.split(',')
|
||||||
for plugin_option in plugin_list.split(','):
|
for plugin_option in plugin_list.split(','):
|
||||||
if plugin_option not in plugins:
|
if plugin_option not in plugins:
|
||||||
|
logger.info('loading plugin: ' + plugin_option)
|
||||||
plugin_package = 'linspector.plugins.' + plugin_option.lower()
|
plugin_package = 'linspector.plugins.' + plugin_option.lower()
|
||||||
plugin_module = importlib.import_module(plugin_package)
|
plugin_module = importlib.import_module(plugin_package)
|
||||||
plugin = plugin_module.get(configuration, environment, self)
|
plugin = plugin_module.get(configuration, environment, self)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from logging import getLogger
|
||||||
logger = getLogger('linspector')
|
logger = getLogger('linspector')
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: there is a bug when stopping the daemon. the pid_file is not being deleted. NEEDS A FIX!
|
||||||
class Linspectord:
|
class Linspectord:
|
||||||
|
|
||||||
def __init__(self, configuration, environment, linspector):
|
def __init__(self, configuration, environment, linspector):
|
||||||
|
|
@ -23,7 +24,7 @@ class Linspectord:
|
||||||
try:
|
try:
|
||||||
self.__pid_file = configuration.get_option('linspector', 'pid_file')
|
self.__pid_file = configuration.get_option('linspector', 'pid_file')
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(str('daemonize error (no pid_file set): {0}'.format(err)))
|
logger.critical(str('daemonize error (no pid_file set): {0}'.format(err)))
|
||||||
|
|
||||||
def daemonize(self):
|
def daemonize(self):
|
||||||
# daemonize the class using the UNIX double fork mechanism.
|
# daemonize the class using the UNIX double fork mechanism.
|
||||||
|
|
@ -35,7 +36,7 @@ class Linspectord:
|
||||||
# exit first parent.
|
# exit first parent.
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
logger.error(str('fork #1 failed: {0}'.format(err)))
|
logger.critical(str('fork #1 failed: {0}'.format(err)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# decouple from parent environment.
|
# decouple from parent environment.
|
||||||
|
|
@ -50,7 +51,7 @@ class Linspectord:
|
||||||
# Exit from second parent.
|
# Exit from second parent.
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
logger.error(str('fork #2 failed: {0}'.format(err)))
|
logger.critical(str('fork #2 failed: {0}'.format(err)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# redirect standard file descriptors.
|
# redirect standard file descriptors.
|
||||||
|
|
@ -76,7 +77,7 @@ class Linspectord:
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
# start the daemon. check for a pidfile to see if the daemon already runs before.
|
# start the daemon. check for a pidfile to see if the daemon already runs before.
|
||||||
|
logger.info('starting daemon using pid_file: ' + self.__pid_file)
|
||||||
try:
|
try:
|
||||||
with open(self.__pid_file, 'r') as pf:
|
with open(self.__pid_file, 'r') as pf:
|
||||||
pid = int(pf.read().strip())
|
pid = int(pf.read().strip())
|
||||||
|
|
@ -85,7 +86,7 @@ class Linspectord:
|
||||||
|
|
||||||
if pid:
|
if pid:
|
||||||
message = 'pid_file {0} already exist. daemon already running?'
|
message = 'pid_file {0} already exist. daemon already running?'
|
||||||
logger.error(str(message.format(self.__pid_file)))
|
logger.critical(str(message.format(self.__pid_file)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# start the daemon.
|
# start the daemon.
|
||||||
|
|
@ -94,7 +95,7 @@ class Linspectord:
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
# stop the daemon.
|
# stop the daemon.
|
||||||
|
logger.info('stopping daemon using pid_file: ' + self.__pid_file)
|
||||||
# get the pid from the pid file.
|
# get the pid from the pid file.
|
||||||
try:
|
try:
|
||||||
with open(self.__pid_file, 'r') as pf:
|
with open(self.__pid_file, 'r') as pf:
|
||||||
|
|
@ -118,15 +119,18 @@ class Linspectord:
|
||||||
if os.path.exists(self.__pid_file):
|
if os.path.exists(self.__pid_file):
|
||||||
os.remove(self.__pid_file)
|
os.remove(self.__pid_file)
|
||||||
else:
|
else:
|
||||||
logger.error(str(err.args))
|
logger.critical(str(err.args))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
# restart the daemon.
|
# restart the daemon.
|
||||||
|
logger.info('restarting daemon using pid_file: ' + self.__pid_file)
|
||||||
self.stop()
|
self.stop()
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
|
# maybe this function can be removed in the future because Linspector should rund endless when
|
||||||
|
# starting scheduled jobs. need to cover this in the future. for now, it is useful for testing
|
||||||
|
# while development because the daemon even runs when internally is nothing to do.
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run():
|
def run():
|
||||||
while True:
|
while True:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue