Logging in Python WSGI application with Passenger not working - python

I'm trying to get the Python logging facility working without success, despite googling and reading the docs. This is a WSGI Python app inside Passenger on a Dreamhost shared server. The Paste middleware is working to provide info on 500 errors. There are no python errors when this code is run.
My sanitized code (passenger_wsgi.py):
#!/usr/bin/python
import os
import sys
import logging
cwd = os.getcwd()
sys.path.insert(0,cwd)
sys.path.append(cwd)
from paste.exceptions.errormiddleware import ErrorMiddleware
# configure the logging
logfilename = os.path.join('<path>/passenger_wsgi.log')
logging.basicConfig(filename=logfilename, level=logging.DEBUG, filemode='a+', format='%(asctime)s %(levelname)s %(message)s')
logging.info("Running %s", sys.executable)
log = file('<path>/passenger_wsgi_2.log', 'a')
print >>log, "Running %s" % (sys.executable)
log.flush()
application = ''
def application(environ, start_response):
results = ''
logging.info("Application called:")
logging.info("environ: %s", str(environ))
print >>log, "Application called:"
log.flush()
status = '200 OK'
results = 'Hello World! Running Python version ' + sys.version + '\n\n'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(results)))]
# to test paste's error catching prowess, uncomment the following line
#raise("error")
start_response(status, response_headers)
return results
# load the application within Paste's error middleware
application = ErrorMiddleware(application, debug=True)
The print >>log statements work as expected, both when run from the command line and when run in response to an http request. The first logging.info statement works when run from the command line (of course the other logging.info statements never get hit from the command line). However, when run in response to an HTTP request, none of the logging.info statements work.
When I say 'work' here, I mean 'writes the statements to the log file'. I'd much rather use the logging facility than the print statements, if it can be made to work.
Thanks in advance for helping me understand and solve this issue.

Answering for posterity because I recently hit the same issue.
It looks like the default logger doesn't work inside the dreamhost passenger environment. I got it to work with this (snipped from https://gist.github.com/jhamrick/044c3607979eea2123ae):
import logging
from logging.handlers import RotatingFileHandler
logfilename = os.path.join(os.environ['HOME'], 'logs', 'passenger_wsgi.log')
logformat = "[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s"
loglevel = logging.INFO
handler = RotatingFileHandler(logfilename, maxBytes=1048576, backupCount=5)
handler.setLevel(loglevel)
handler.setFormatter(logging.Formatter(logformat))
logging.basicConfig(filename=logfilename, format=logformat, level=loglevel)
logger = logging.getLogger("passenger_wsgi")
logger.addHandler(handler)
logger.setLevel(loglevel)
logger.debug("Starting application")
Using logger from inside routes works as well. Hope this helps others who come across this!

Related

How to do logging in python in an explicit file

I tried below code only to find that my logs are getting printed in console.
What mistake I am doing here?
import logging
logging.basicConfig(filename="logger.log",
format='%(asctime)s %(message)s',
filemode='w')
logger=logging.getLogger()
logger.setLevel(logging.INFO)
logger.info("An information")
I am running this code as a fastapi project via uvicorn server.
Pass the log level to run method
uvicorn.run("example:app", host='localhost', port=8000, reload=True, log_level='info')
Use logger
from uvicorn.config import logger
logger.info('Your Comment')

Python Tornado - disable logging to stderr

I have minimalistic Tornado application:
import tornado.ioloop
import tornado.web
class PingHandler(tornado.web.RequestHandler):
def get(self):
self.write("pong\n")
if __name__ == "__main__":
application = tornado.web.Application([ ("/ping", PingHandler), ])
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Tornado keeps reporting error requests to stderr:
WARNING:tornado.access:404 GET / (127.0.0.1) 0.79ms
Question: It want to prevent it from logging error messages. How?
Tornado version 3.1; Python 2.6
Its clear that "someone" is initializing logging subsystem when we start Tornado. Here is the code from ioloop.py that reveals the mystery:
def start(self):
if not logging.getLogger().handlers:
# The IOLoop catches and logs exceptions, so it's
# important that log output be visible. However, python's
# default behavior for non-root loggers (prior to python
# 3.2) is to print an unhelpful "no handlers could be
# found" message rather than the actual log entry, so we
# must explicitly configure logging if we've made it this
# far without anything.
logging.basicConfig()
basicConfig is called and configures default stderr handler.
So to setup proper logging for tonado access, you need to:
Add a handler to tornado.access logger: logging.getLogger("tornado.access").addHandler(...)
Disable propagation for the above logger: logging.getLogger("tornado.access").propagate = False. Otherwise messages will arrive BOTH to your handler AND to stderr
The previous answer was correct, but a little incomplete. This will send everything to the NullHandler:
hn = logging.NullHandler()
hn.setLevel(logging.DEBUG)
logging.getLogger("tornado.access").addHandler(hn)
logging.getLogger("tornado.access").propagate = False
You could also quite simply (in one line) do:
logging.getLogger('tornado.access').disabled = True

How to set up logging for a Python Pyramid Waitress server?

I am trying to setup logging for a Python Pyramid Waitress Server. I have followed the docs here:
Pyramid logging and here: Pyramid PasteDeploy logging. I have tired both methods which have yield no logging results from waitress. My own logging works perfectly.
I have set Waitress logging level to DEBUG and I get nothing even I remove server files. Waitress fails server silently.
How do you set up logging for a Pyramid Waitress Server so I can see files be requested, missing file errors, etc?
Method 1:
Setup from code:
import logging
logging.basicConfig()
logger = logging.getLogger('waitress')
logger.setLevel(logging.DEBUG)
Method 2:
Starting the server with pserve development.ini where the development.ini file sets up the logging as below
[app:main]
use = egg:MyProject
pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
pyramid_debugtoolbar
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
[loggers]
keys = root, myproject, waitress
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_myproject]
level = DEBUG
handlers =
qualname = myproject
[logger_waitress]
level = DEBUG
handlers =
qualname = waitress
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
The logging configuration actually works. Here I demonstrate a simple view to emit logging message for waitress logger
#view_config(route_name='hello_baby',
request_method='GET',
renderer='string')
def hello_baby(request):
import logging
logger = logging.getLogger('waitress')
logger.info('Hello baby!')
return 'Hi there'
You should be able to see the logging message when you hit the page. The reason you didn't see messages from waitress is - there is no logging messages are emitted for common routines in waitress. It only emits messages when something goes wrong, you can read the source code
For some other knowledge about Python logging, you can read my article : Good logging practice in Python
I got console logging (for all requests) to show up by using paste's translogger; A good example is at http://flask.pocoo.org/snippets/27/.
Here's the relevant section of my .ini:
[app:main]
use = egg:${:app}
filter-with = translogger
[filter:translogger]
use = egg:Paste#translogger
# these are the option default values (see http://pythonpaste.org/modules/translogger.html)
# logger_name='wsgi'
# format=None
# logging_level=20
# setup_console_handler=True
# set_logger_level=10

Why is my log level not being used when using loadapp from paste.deploy?

I want to temporailiy turn on debug messages in a production pyramid web project so I adjusted the production.ini file, pushed it to Heroku and saw only error and warn level messages.
So I thought, that seems odd since if I start the pyramid application like the following on my local PC I get all the log level messages.
env/bin/pserve production.ini
OK, so that's not exactly how it runs on Heroku, it is actually run from a little bit of python that looks like this (in a file called runapp.py):
import os
from paste.deploy import loadapp
from waitress import serve
if __name__ == "__main__":
port = int(os.environ.get("PORT", 5000))
app = loadapp('config:production.ini', relative_to='.')
serve(app, host='0.0.0.0', port=port)
Now, sure enough if I do this on my local PC I get the same behavior as when it is deployed to Heroku (hardly surprising).
python runapp.py
My question is, what am I missing here? Why does running it the second way result in no log messages other than ERROR and WARN being output to standard out? Surely, since it is using the same production.ini file it should work the same as if I use the pserve process?
Here is my logging section from production.ini:
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
###
[loggers]
keys = root, test
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = DEBUG
handlers = console
[logger_test]
level = DEBUG
handlers = console
qualname = test
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = DEBUG
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
PasteDeploy does not actually assume responsibility for configuring logging. This is a little quirk where the INI file is dual-purposed. There are sections that PasteDeploy cares about, and there are sections that logging.config.fileConfig cares about, and both must be run to fully load an INI file.
If you follow the pyramid wrappers for doing this, you'd do:
pyramid.paster.setup_logging(inipath)
pyramid.paster.get_app(inipath)
The main reason you would use these instead of doing it yourself is that they support doing "the right thing" when inipath contains a section specifier like development.ini#myapp, which fileConfig would crash on.

Try to write into syslog

I am working in linux and the process rsyslogd is listening to port 514.
The following code can't write into /var/log/syslog.
Is anybody know what is the problem?
import logging
import logging.handlers
root_logger = logging.getLogger()
root_logger.setLevel(config.get_value("log_level"))
syslog_hdlr = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_DAEMON)
syslog_hdlr.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s')
syslog_hdlr.setFormatter(formatter)
root_logger.addHandler(syslog_hdlr)
logger = logging.getLogger("imapcd.daemon")
logger.debug('test')
This code works fine in my system if I make some changes:
import logging.handlers as sh
syslog_hdlr = sh.SysLogHandler(address='/dev/log', facility=sh.SysLogHandler.LOG_DAEMON)
and
root_logger.setLevel(logging.DEBUG)
So check the logging level you are getting from config is not more restrictive than DEBUG (ex: if it is set to INFO no debug messages are printed).
If you still don't see anything on syslog try to use the syslog module and see if you get anything from there:
import syslog
syslog.syslog(syslog.LOG_ERR, "MY MESSAGE")

Categories

Resources