Reputation: 1077
I have the following script that I want only the "DEBUG" log messages to be logged to the file, and nothing to the screen.
from flask import Flask, request, jsonify
from gevent.pywsgi import WSGIServer
import usaddress
app = Flask(__name__)
from logging.handlers import RotatingFileHandler
import logging
#logging.basicConfig(filename='error.log',level=logging.DEBUG)
# create a file to store weblogs
log = open('error.log', 'w'); log.seek(0); log.truncate();
log.write("Web Application Log\n"); log.close();
log_handler = RotatingFileHandler('error.log', maxBytes =1000000, backupCount=1)
formatter = logging.Formatter(
"[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s"
)
log_handler.setFormatter(formatter)
app.logger.setLevel(logging.DEBUG)
app.logger.addHandler(log_handler)
@app.route('/')
def hello():
return "Hello World!"
@app.route("/parseAddress", methods=["POST"])
def parseAddress():
address = request.form['address']
return jsonify(usaddress.tag(address)), 200
if __name__ == '__main__':
# app.run(host='0.0.0.0')
http_server = WSGIServer(('', 5000), app, log=app.logger)
http_server.serve_forever()
But right now even "INFO" messages are being logged to the file and to the screen. How can I have only the "DEBUG" messages logged to the file and nothing to the screen?
Upvotes: 2
Views: 2690
Reputation: 363
def setup_logger(modes, logger_name, log_file, level=logging.INFO):
l = logging.getLogger(logger_name)
l.setLevel(level)
print(modes)
if(modes == 2):
formatterTwo = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
fileHandler = logging.FileHandler(log_file, mode='a')
fileHandler.setFormatter(formatterTwo)
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatterTwo)
l.addHandler(fileHandler)
l.addHandler(streamHandler)
else:
formatterOne = logging.Formatter('%(message)s')
fileHandler = logging.FileHandler(log_file, mode='a')
fileHandler.setFormatter(formatterOne)
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatterOne)
l.setLevel(logging.DEBUG)
l.addHandler(fileHandler)
setup_logger(2,'log1', "logFile_With_output_to_file_and_screen.log")
setup_logger(1,'log2', "logFile_Only_no_output_to_screen.log")
loggerOne = logging.getLogger('log1')
loggerTwo = logging.getLogger('log2')
loggerOne.info("This will output to Screen and File")
loggerTwo.debug("This will output to File ONLY")
**Notes : modes 1: Only File, 2 File and Screen
Upvotes: 0
Reputation: 6344
I did some interactive testing and it looks like app.logger
is a logger named with python file
print(app.logger.name) # filename
and it has one handler
print(app.logger.handlers) # [<StreamHandler <stderr> (NOTSET)>]
A handler with level logging.NOTSET
processes all messages (from all logging levels). So when you set app.logger.setLevel(logging.DEBUG)
then all debug and higher logs will be passed to handlers and all of them will appear on stderr.
To log absolutely nothing on the screen you have to manually remove StreamHandler:
app.logger.handlers.pop(0)
and to log DEBUG and higher to the file set logging level also on the handler
log_handler.setLevel(logging.DEBUG)
Python logging is quite complicated. See this logging flow chart for better understanding what is going on :)
EDIT: to log only one specific level you need custom Filter object:
class LevelFilter:
def __init__(self, level):
self._level = level
def filter(self, log_record):
return log_record.levelno == self._level
log_handler.setLevel(logging.DEBUG)
log_handler.addFilter(LevelFilter(logging.DEBUG))
Upvotes: 3