Teil 27: logging.config
This commit is contained in:
6
teil27/.gitignore
vendored
Normal file
6
teil27/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
example.py
|
||||
ex2.py
|
||||
*.log
|
||||
__pycache__
|
||||
db.ini
|
||||
|
10
teil27/JSONFormatter.py
Normal file
10
teil27/JSONFormatter.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import logging
|
||||
import logging.config
|
||||
import json
|
||||
ATTR_TO_JSON = ['created', 'filename', 'funcName', 'levelname', 'lineno', 'module', 'msecs', 'msg', 'name', 'pathname', 'process', 'processName', 'relativeCreated', 'thread', 'threadName']
|
||||
class JsonFormatter:
|
||||
def format(self, record):
|
||||
obj = {attr: getattr(record, attr)
|
||||
for attr in ATTR_TO_JSON}
|
||||
return json.dumps(obj, indent=4)
|
||||
|
8
teil27/db.ini.sample
Normal file
8
teil27/db.ini.sample
Normal file
@@ -0,0 +1,8 @@
|
||||
[pidb]
|
||||
host=database
|
||||
user=piuser
|
||||
password=<passwort>
|
||||
database=pidb
|
||||
|
||||
|
||||
|
75
teil27/dbhandler.py
Normal file
75
teil27/dbhandler.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# Datei dbhandler.py
|
||||
import mysql.connector
|
||||
import datetime
|
||||
import configparser
|
||||
import logging
|
||||
from logging import config
|
||||
import json
|
||||
|
||||
|
||||
|
||||
|
||||
class DBHandler(logging.Handler):
|
||||
def __init__(self):
|
||||
logging.Handler.__init__(self)
|
||||
# Datenbank Konfiguration lesen
|
||||
confparser = configparser.ConfigParser()
|
||||
confparser.read('db.ini')
|
||||
# Verbindung zur DB herstellen
|
||||
self.connection= mysql.connector.connect(host=confparser['pidb']['host'],user = confparser['pidb']['user'],password = confparser['pidb']['password'],database = confparser['pidb']['database'])
|
||||
# Tabelle anlegen, falls noch keine existiert.
|
||||
self.connection.cursor().execute('''CREATE TABLE IF NOT EXISTS logs (
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
||||
zeit VARCHAR(50),
|
||||
level VARCHAR(8),
|
||||
message VARCHAR(40),
|
||||
logger_name VARCHAR(25),
|
||||
filename VARCHAR(60),
|
||||
line INTEGER)''')
|
||||
self.connection.commit()
|
||||
|
||||
# Bei Löschung der Klasseninstanz, Connection schliessen
|
||||
def __del__(self):
|
||||
if self.connection != None:
|
||||
self.connection.close()
|
||||
self.connection = None
|
||||
|
||||
# LogRecord in die DB schreiben
|
||||
def emit(self, record):
|
||||
try:
|
||||
# Log-Daten in ein Tupel extrahieren
|
||||
log_entry = (datetime.datetime.utcnow().isoformat(),
|
||||
record.levelname,
|
||||
record.getMessage(),
|
||||
record.name,
|
||||
record.pathname,
|
||||
record.lineno)
|
||||
|
||||
# Log in die Datenbank einfügen
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute('''INSERT INTO logs (zeit, level, message, logger_name, filename, line)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)''', log_entry)
|
||||
self.connection.commit()
|
||||
cursor.close()
|
||||
|
||||
except Exception as e:
|
||||
# im Fehlerfall den LogRecord nach "oben" weiterreichen.
|
||||
self.handleError(record)
|
||||
|
||||
# Config aus JSON Datei laden und setzen
|
||||
with open('handler_config.json') as file_config:
|
||||
config.dictConfig(json.load(file_config))
|
||||
# Logging testen
|
||||
def testlogging():
|
||||
print('testlogging() aufgerufen.')
|
||||
logging.debug('Diese Zeile wird ausgefiltert.')
|
||||
logging.debug('DEBUG/Druckdaten werden gesendet.')
|
||||
logging.info('INFO/Es werden 2 Seiten gedruckt')
|
||||
logging.debug('Diese Zeile wird auch ausgefiltert.')
|
||||
logging.warning('WARN/nicht genügend Papier im Drucker')
|
||||
logging.error('ERROR/Drucker nicht gefunden.')
|
||||
logging.critical('CRITICAL/Drucker brennt')
|
||||
|
||||
if __name__ == '__main__':
|
||||
testlogging()
|
||||
|
37
teil27/filterlogging.py
Normal file
37
teil27/filterlogging.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import logging
|
||||
from logging import config
|
||||
import json
|
||||
|
||||
# Filter definieren
|
||||
class DruckFilter(logging.Filter):
|
||||
|
||||
def __init__(self, params=None):
|
||||
self.param = params
|
||||
print('Druckfilter initialisiert')
|
||||
|
||||
def filter(self, record:logging.LogRecord)-> bool| logging.LogRecord:
|
||||
|
||||
# nur Text, der das Wort Druck enthält soll geloggt werden.
|
||||
return record.getMessage().lower().find('druck') > -1
|
||||
|
||||
|
||||
# Config aus JSON Datei laden und setzen
|
||||
|
||||
with open('log_config.json') as file_config:
|
||||
config.dictConfig(json.load(file_config))
|
||||
|
||||
|
||||
# Logging testen
|
||||
def testlogging():
|
||||
print('testlogging() aufgerufen.')
|
||||
logging.debug('Diese Zeile wird ausgefiltert.')
|
||||
logging.debug('DEBUG/Druckdaten werden gesendet.')
|
||||
logging.info('INFO/Es werden 2 Seiten gedruckt')
|
||||
logging.debug('Diese Zeile wird auch ausgefiltert.')
|
||||
logging.warning('WARN/nicht genügend Papier im Drucker')
|
||||
logging.error('ERROR/Drucker nicht gefunden.')
|
||||
logging.critical('CRITICAL/Drucker brennt')
|
||||
|
||||
if __name__ == '__main__':
|
||||
testlogging()
|
||||
|
41
teil27/halloween.py
Normal file
41
teil27/halloween.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#encoding: utf-8
|
||||
import logging
|
||||
from logging import config
|
||||
import json
|
||||
import random
|
||||
import JSONFormatter
|
||||
|
||||
#JSON Formatter
|
||||
ATTR_TO_JSON = ['created', 'filename', 'funcName', 'levelname', 'lineno', 'module', 'msecs', 'msg', 'name', 'pathname', 'process', 'processName', 'relativeCreated', 'thread', 'threadName']
|
||||
class JsonFormatter:
|
||||
def format(self, record):
|
||||
obj = {attr: getattr(record, attr)
|
||||
for attr in ATTR_TO_JSON}
|
||||
return json.dumps(obj, indent=4)
|
||||
|
||||
#CustomFilter
|
||||
|
||||
class HalloweenFilter(logging.Filter):
|
||||
|
||||
def __init__(self, params=None):
|
||||
self.param = params
|
||||
print('Halloweenfilter initialisiert')
|
||||
|
||||
def filter(self, record:logging.LogRecord)-> bool| logging.LogRecord:
|
||||
|
||||
# Der Unsichtbare soll keine Spuren im Logfile hinterlassen.
|
||||
return record.getMessage().lower().find('unsichtbar') == -1
|
||||
|
||||
visitors = ['Werwolf','Gespenst','Hexe','Unsichtbarer','Vampir','Dämon','Gorilla','Monster','Mumie']
|
||||
|
||||
treats = ['Bonbons','Twinkies','Lollis','Schokoladen','Kuchen', 'Äpfel']
|
||||
|
||||
secrets = random.SystemRandom()
|
||||
|
||||
with open('halloween_log_conf.json') as file_config:
|
||||
config.dictConfig(json.load(file_config))
|
||||
for v in visitors:
|
||||
logging.info(f'An der Tür klopft eine gruselige Gestalt: {v}')
|
||||
number = secrets._randbelow(20)
|
||||
treat = secrets.choice(treats)
|
||||
logging.info(f'Du gibst ihr {number} {treat} und sie zieht weiter')
|
37
teil27/halloween_log_conf.json
Normal file
37
teil27/halloween_log_conf.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"version":1,
|
||||
"filters": {
|
||||
"halloween":{
|
||||
"()": "__main__.HalloweenFilter"
|
||||
}
|
||||
},
|
||||
"formatters":{
|
||||
"std_out":{
|
||||
"format": "%(asctime)s : %(levelname)s : %(lineno)d : %(message)s",
|
||||
"datefmt":"%I:%M:%S %d.%m.%Y"
|
||||
},
|
||||
"json": {
|
||||
"()": "__main__.JsonFormatter"
|
||||
}
|
||||
},
|
||||
"handlers":{
|
||||
"console":{
|
||||
"formatter": "std_out",
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "DEBUG"
|
||||
},
|
||||
"file":{
|
||||
"formatter":"json",
|
||||
"class":"logging.FileHandler",
|
||||
"level":"DEBUG",
|
||||
"filename" : "halloween.log",
|
||||
"filters": ["halloween"]
|
||||
}
|
||||
},
|
||||
"root":{
|
||||
"handlers":["console","file"],
|
||||
"level": "DEBUG"
|
||||
}
|
||||
|
||||
}
|
||||
|
33
teil27/handler_config.json
Normal file
33
teil27/handler_config.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"version":1,
|
||||
"formatters":{
|
||||
"std_out":{
|
||||
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||
}
|
||||
},
|
||||
"handlers":{
|
||||
"console":{
|
||||
"formatter": "std_out",
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "DEBUG"
|
||||
},
|
||||
"db":{
|
||||
"formatter": "std_out",
|
||||
"()": "__main__.DBHandler",
|
||||
"level": "DEBUG"
|
||||
},
|
||||
"file":{
|
||||
"formatter":"std_out",
|
||||
"class":"logging.FileHandler",
|
||||
"level":"DEBUG",
|
||||
"filename" : "raspithek.log"
|
||||
}
|
||||
},
|
||||
"root":{
|
||||
"handlers":["console","file","db"],
|
||||
"level": "DEBUG"
|
||||
}
|
||||
|
||||
}
|
||||
|
35
teil27/log_config.json
Normal file
35
teil27/log_config.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"version":1,
|
||||
"filters": {
|
||||
"drucker":{
|
||||
"()": "__main__.DruckFilter",
|
||||
"params": "noshow"
|
||||
}
|
||||
},
|
||||
"formatters":{
|
||||
"std_out":{
|
||||
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||
}
|
||||
},
|
||||
"handlers":{
|
||||
"console":{
|
||||
"formatter": "std_out",
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "DEBUG",
|
||||
"filters": ["drucker"]
|
||||
},
|
||||
"file":{
|
||||
"formatter":"std_out",
|
||||
"class":"logging.FileHandler",
|
||||
"level":"DEBUG",
|
||||
"filename" : "raspithek.log"
|
||||
}
|
||||
},
|
||||
"root":{
|
||||
"handlers":["console","file"],
|
||||
"level": "DEBUG"
|
||||
}
|
||||
|
||||
}
|
||||
|
52
teil27/testloggingconf.py
Normal file
52
teil27/testloggingconf.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import logging
|
||||
from logging import config
|
||||
|
||||
# Logging Konfiguration definieren.
|
||||
|
||||
log_config = {
|
||||
"version":1,
|
||||
# root-Logger
|
||||
"root":{
|
||||
"handlers" : ["console",'file'],
|
||||
"level": "DEBUG"
|
||||
},
|
||||
"handlers":{
|
||||
#Handler für Console
|
||||
"console":{
|
||||
"formatter": "std_out",
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "DEBUG"
|
||||
},
|
||||
# Handler für Logdatei
|
||||
"file":{
|
||||
"formatter":"std_out",
|
||||
"class":"logging.FileHandler",
|
||||
"level":"DEBUG",
|
||||
"filename":"raspithek.log"
|
||||
},
|
||||
},
|
||||
|
||||
# Format einer Logzeile
|
||||
"formatters":{
|
||||
"std_out": {
|
||||
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
# Config setzen
|
||||
config.dictConfig(log_config)
|
||||
|
||||
# Logging testen
|
||||
def testlogging():
|
||||
print('testlogging() aufgerufen.')
|
||||
logging.debug('DEBUG/Druckdaten werden gesendet.')
|
||||
logging.info('INFO/Es werden 2 Seiten gedruckt')
|
||||
logging.warning('WARN/nicht genügend Papier im Drucker')
|
||||
logging.error('ERROR/Drucker nicht gefunden.')
|
||||
logging.critical('CRITICAL/Drucker brennt')
|
||||
|
||||
if __name__ == '__main__':
|
||||
testlogging()
|
||||
|
Reference in New Issue
Block a user