Flask is not printing sys.stdout.write messages - python

I am running the flask app from this link using the command python app.py.
More logs printed using, sys.stdout.write are not printed on the console. However using logging.StreamHandler works for redirecting messages to stdout.
It works,
import logging
import logging.handlers
logger = logging.getLogger('kumologging')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
logger.addHandler(ch)
logger.info("hey, i am from logger obj")
It doesn't work
import sys
sys.stdout.write("hey, i am from stdout")
Does flask override sys.stdout file descriptor, redirecting the logs elsewhere?

afaik flasks app.run() uses the gunicorn web package
I believe gunicorn is the one that is actually redirecting your output
the output might be in /var/log/gunicorn/error.log (not sure where it would be on windows :/)
or its possible sys.stdout is just not flushing its buffer,
try sys.stdout.flush() after writting to it

Related

Logging failure with multiprocessing

I am trying to implement logging with multiprocessing for our application(flask). We use python2.7, I am using the concept of queues to keep log requests from all the forks and logging records present in the queue. I followed this approach. Only change from that link is I am using TimedRotatatingFileHandler instead of RotatingFileHandler. This is my dictconfig
I am initializing the logger before initializing the forks and in code in the following way
from flask import Flask
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
path = 'share/log_test/logging.yaml'
if os.path.exists(path):
with open(path, 'rt') as f:
config = yaml.load(f.read())
logging.config.dictConfig(config)
logger = logging.getLogger('debuglog') # problem starts if i keep this statement
app = Flask(__name__)
init_routes(app) # initialize our routes
server_conf = config_manager.load_config(key='server')
logger.info("Logging is set up.") # only this line gets logged and other log statement to be logged by forks in code with same logger are not writing to the file.
http_server = HTTPServer(WSGIContainer(app))
http_server.bind(server_conf.get("PORT")) # port to listen
http_server.start(server_conf.get("FORKS")) # number of forks
IOLoop.current().start()
The problem I am facing is if i use getLogger in the code before initializing the forks, the forks are not writing logs to the logfile, only log statements before initializing forks are being logged. If I remove the logging.getLogger('debuglog') , forks are logging correctly.
I paused the execution flow and verified if the handler is assigned to logger or not but that seems to be fine
Why this strange behavior is observed?
Update: when I use another logger with the same file to write and everything is working fine. But when i use same logger it's not working. Anything related to RLock?
I got a workaround for this solution finally. I removed the concept of queues in the implementation and just printing then and there itself after receiving the log record.
def emit(self, record):
try:
s = self._format_record(record)
self._handler.emit(record) #emitting here itself
# self.send(s) #stopped sending it to queue
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
which seems to be working fine with the following testing
8 workers - 200 requests - 50 concurrency

How to collect error message from stderr using a daemonized uwsgi?

I run my uwsgi with --daemonzie=~/uwsgi.log.
I use flask. In my flask app, if I print some message into stdin, it will show on uwsgi.log. If I print to stderr, uwsgi.log won't show these message. How should I enable uwsgi to collect message from stderr.
The major problem is that I can not let uwsgi.log collect the exception track after I catch some exceptions in my flask app.
Flask is catching your exceptions, make sure, you set PROPAGATE_EXCEPTIONS in config.
from flask import Flask
application = Flask(__name__)
application.config['PROPAGATE_EXCEPTIONS'] = True
#application.route('/')
def hello_world():
return 'Hello World!'
Uwsgi logging can be set with
--logto /var/log/uwsgi/app.log
or use logto2 flag if if you want to separate stdout from stderr.
There's also possibility of setting loggers plugin (forward to syslog, etc.), however these plugins have to be compiled into uwsgi.

How to output logging.info and logging.debug to console?

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)

Raven's SentryHandler is suppressing StreamHandler output to file

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.

How to log from handlers in tornado in console?

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.

Categories