How to log from handlers in tornado in console?
I started app from console and put above handlers logging.getLogger().setLevel(logging.DEBUG)
and inside handlers
logging.info('RECEIVED HTTP GET REQUEST')
but nothing writes in console from handlers. I have tried with print but it doesn't work inside handlers.
You can try by importing tornado.options
https://github.com/facebook/tornado/blob/branch2.4/tornado/options.py
Line 465 - 468:
define("logging", default="info",
help=("Set the Python log level. If 'none', tornado won't touch the "
"logging configuration."),
metavar="debug|info|warning|error|none")
This block of code register 'logging' as a command line argument within tornado command line argument parser and set default value to info.
In the development version they moved it to function 'define_logging_options' * in 'tornado.log' module.
Related
I have this python code:
import logging
LOGGER = logging.getLogger(__name__)
LOGGER.info('test')
It does not get written to the console, so where does this get logged?
This does not get logged anywhere, because you did not configure any logging handlers. Without a handler configured, the log event goes nowhere. When there are no handlers configured, the root logger gets a handler automatically added if an event at WARNING or above is seen, but your event was just at INFO level.
If you put a line like this before, then you will see it logged to terminal:
logging.basicConfig(level=logging.INFO)
Basic config will add a StreamHandler writing to sys.stderr if you don't specify otherwise.
I have a tornado application and a custom logger method. My code to build and use the custom logger is the following:
def create_logger():
"""
This function creates the logger functionality to be used throughout the Python application
:return: bool - true if successful
"""
# Configuring the logger
filename = "PythonLogger.log"
# Change the current working directory to the logs folder, so that the logs files is written in it.
os.chdir(os.path.normpath(os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + os.sep + os.pardir + os.sep + os.pardir + os.sep + 'logs')))
# Create the logs file
logging.basicConfig(filename=filename, format='%(asctime)s %(message)s', filemode='w')
# Creating the logger
logger = logging.getLogger()
# Setting the threshold of logger to DEBUG
logger.setLevel(logging.NOTSET)
logger.log(0, 'El logger está inicializado')
return True
def log_info_message(msg):
"""
Utility for message logging with code 20
:param msg:
:return:
"""
return logging.getLogger().log(20, msg)
In the code, I initialize the logger and already write a message to it before the Tornado application initialization:
if __name__ == '__main__':
# Logger initialization
create_logger()
# First log message
log_info_message('Initiating Python application')
# Starting Tornado
tornado.options.parse_command_line()
# Specifying what app exactly is being started
server = tornado.httpserver.HTTPServer(test.app)
server.listen(options.port)
try:
if 'Windows_NT' not in os.environ.values():
server.start(0)
tornado.ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
tornado.ioloop.IOLoop.instance().stop()
Then let's say my method get of HTTP request is as follows (only interesting lines):
class API(tornado.web.RequestHandler):
def get(self):
self.write('Get request ')
logging.getLogger("tornado.access").log(20, 'Hola')
logging.getLogger("tornado.application").log(20, '1')
logging.getLogger("tornado.general").log(20, '2')
log_info_message('Received a GET request at: ' + datetime.datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"))
What I see is a difference between local testing and testing on server.
A) On local, I can see log message at first script running, and log messages of requests (after initializing Tornado app) in my log file and the Tornado logs.
B) On server, I only see the first message, not my log messages when Get requests are accepted and also see Tornado's loggers when there's an error, but even don't see the messages produced by Tornado's loggers. I guess that means that somehow Tornado is re-initializing the logger and making mine and his 3 ones write in some other file (somehow that does not affect when errors happens??).
I am aware that Tornado uses its own 3 logging functions, but somehow I would like to use mine as well, at the same time as keeping the Tornado's ones and writing them all into the same file. Basically reproduce that local behaviour on server but also keeping it when some error happens, of course.
How could I achieve this?
Thanks in advance!
P.S.: if I add a name to the logger, let's say logging.getLogger('Example') and changed log_info_message function to return logging.getLogger('Example').log(20, msg), Tornado's logger would fail and raise error. So that option destroys its own loggers...
It seems the only problem was that, on the server side, tornado was setting the the mininum level for a log message to be written on log file higher (minimum of 40 was required). So that logging.getLogger().log(20, msg) would not write on the logging file but logging.getLogger().log(40, msg) would.
I would like to understand why, so if anybody knows, your knowledge would be more than welcome. For the time being that solution is working though.
tornado.log defines options that can be used to customise logging via command line (check tornado.options) - one of them is logging that defines the log level used. You are likely using this on the server and setting it to error.
When debugging logging I suggest you create a RequestHandler that will log or return the structure of the existing loggers by inspecting the root logger. When you see the structure it is much easier to understand why it works the way it works.
I can only see warning and error, how can I get info and debug printed out? To clarify, I am starting the tornado app with python app.py. I want the info and debug logs to print out to the console after I run the app.
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write('hello fun fun test world from tornado super')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.debug('debug')
application = tornado.web.Application([(r"/", MainHandler)], debug=True)
You probably need to change the level of the logging module to allow for debug and info messages to be displayed in the console.
logger.setLevel(logging.DEBUG) # this should allow all messages to be displayed
if you don't want to display debug messages then do this:
logger.setLevel(logging.INFO)
And just a quick fyi. Here are the levels in order, so if you set one of them it will display any messages of the types below the set level and it will NOT any messages above the set level.
logging.DEBUG
logging.INFO
logging.WARNING
logging.ERROR
logging.CRITICAL
By calling tornado.options.parse_command_line you register tornado command line flags.
You can use logging command line flag to change logging level from command line.
For more information: https://stackoverflow.com/a/14269208/63097
python helloworld.py --logging=debug
helloworld.py is tornado offical demo
more details about tornado/options.py
Here's the trick: you can directly modify tornados internal access logger:
import logging
import tornado
import tornado.log
tornado.log.access_log.setLevel(logging.DEBUG)
I am trying to set up logging with Cherrypy on my Openshift python 3.3 app. The 'appserver.log' file only updates until the actual server starts then nothing gets added to the log file. I have read and followed (as far as I know) the documentation at the below links. Still no logging.
CherryPy server errors log
http://docs.cherrypy.org/dev/refman/_cplogging.html
My python code snippet:
def run_cherrypy_server(app, ip, port=8080):
from cherrypy import wsgiserver
from cherrypy import config
# log.screen: Set this to True to have both “error” and “access” messages printed to stdout.
# log.access_file: Set this to an absolute filename where you want “access” messages written.
# log.error_file: Set this to an absolute filename where you want “error” messages written.
appserver_error_log = os.path.join(os.environ['OPENSHIFT_HOMEDIR'], 'python', 'logs','appserver_error.log')
appserver_access_log = os.path.join(os.environ['OPENSHIFT_HOMEDIR'], 'python', 'logs','appserver_access.log')
config.update({
'log.screen': True,
'log.error_file': appserver_error_log,
'log.access_file': appserver_access_log
})
server = wsgiserver.CherryPyWSGIServer(
(ip, port), app, server_name='www.cherrypy.example')
server.start()
The 'appserver_error.log' and 'appserver_access.log' files actually get created in the proper Openshift python directory. However, no logging information in both of the files appserver_error.log and appserver_access.log.
Everything runs fine but no logging.
Any ideas what I am doing wrong?
The WSGI server itself does not do any logging. The CherryPy engine (which controls process startup and shutdown) writes to the "error" log, and only CherryPy applications (that use CherryPy's Request and Response objects) write to the access log. If you're passing your own WSGI application, you'll have to do your own logging.
I have a plain python (non-Django) project where I'm trying to tie Raven into the logging setup.
Under our current setup, we use a simple logging config:
import logging
logging.basicConfig(format='long detailed format',
level=logging.DEBUG)
The output is then redirected to a log file; this produces a nice, verbose log that we can look through when we need to.
We now want to add Raven's error logging, tying it into our current logging setup so that logging.error calls also result in a message being sent to the Sentry server. Using the following code:
from raven import Client
from raven.conf import setup_logging
from raven.handlers.logging import SentryHandler
raven = Client(environ.get('SENTRYURL', ''), site='SITE')
setup_logging(SentryHandler(raven, level=logging.ERROR))
Errors are being successfully sent to Sentry, but I'm now getting only a single line of file output:
DEBUG: Configuring Raven for host: <DSN url>
All other file output -- from logging.debug to logging.error -- is being suppressed.
If I comment the setup_logging line, I get file output but no Sentry errors. What am I doing wrong?
This turned out to be a case of sloppy code. We had some hack elsewhere in the startup execution path that re-initialized the logging:
logging.root.removeHandler(logging.root.handlers[0]) # Undo previous basicConfig
logging.basicConfig(format='same long format',
level=logging.DEBUG)
However, since logging.basicConfig doesn't do anything if logging.root has existing handlers, this simply removed the stream handler, leaving the sentry handler, and caused basicConfig to then act as no-op, meaning we lost our StreamHandler altogether.
Removing these lines and having only one basicConfig and a setup_logging call worked.