From 85c60c26b593f77924d71c0cd7c26648d755d705 Mon Sep 17 00:00:00 2001 From: benoitc Date: Sun, 19 Feb 2012 16:06:06 +0100 Subject: [PATCH] redirect stdout & stderr to logging error file when output is different from '-' . Useful to collect some errors. --- examples/test.py | 5 ++++- gunicorn/glogging.py | 46 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/examples/test.py b/examples/test.py index f972a635..e7db581a 100644 --- a/examples/test.py +++ b/examples/test.py @@ -1,17 +1,20 @@ # -*- coding: utf-8 - # -# This file is part of gunicorn released under the MIT license. +# This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. # # Example code from Eventlet sources from wsgiref.validate import validator +import sys #@validator def app(environ, start_response): """Simplest possible application object""" data = 'Hello, World!\n' status = '200 OK' + print("print to stdout in test app") + sys.stderr.write("stderr, print to stderr in test app") response_headers = [ ('Content-type','text/plain'), ('Content-Length', str(len(data))) diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index 2193ede8..c2303e25 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -8,9 +8,46 @@ import logging logging.Logger.manager.emittedNoHandlerWarning = 1 import sys import traceback +import threading from gunicorn import util +class LazyWriter(object): + + """ + File-like object that opens a file lazily when it is first written + to. + """ + + def __init__(self, filename, mode='w'): + self.filename = filename + self.fileobj = None + self.lock = threading.Lock() + self.mode = mode + + def open(self): + if self.fileobj is None: + self.lock.acquire() + try: + if self.fileobj is None: + self.fileobj = open(self.filename, self.mode) + finally: + self.lock.release() + return self.fileobj + + def write(self, text): + fileobj = self.open() + fileobj.write(text) + fileobj.flush() + + def writelines(self, text): + fileobj = self.open() + fileobj.writelines(text) + fileobj.flush() + + def flush(self): + self.open().flush() + class Logger(object): LOG_LEVELS = { @@ -38,6 +75,14 @@ class Logger(object): self.cfg = cfg loglevel = self.LOG_LEVELS.get(cfg.loglevel.lower(), logging.INFO) + + if cfg.errorlog != "-": + # if an error log file is set redirect stdout & stderr to + # this log file. + stdout_log = LazyWriter(cfg.errorlog, 'a') + sys.stdout = stdout_log + sys.stderr = stdout_log + self.error_log.setLevel(loglevel) # always info in access log @@ -46,7 +91,6 @@ class Logger(object): self._set_handler(self.error_log, cfg.errorlog, logging.Formatter(self.error_fmt, self.datefmt)) - if cfg.accesslog is not None: self._set_handler(self.access_log, cfg.accesslog, fmt=logging.Formatter(self.access_fmt))