重定向print輸出到Mongo
celery 本身用到logging.info 會輸出
是celery的問題,還是logging初始化的時候就會有輸出?
好像是celery 配合logging的問題
不同位置不同地方的```logging.getLogger(logname)```,只要logname相同,就會獲取到同一個日志logging。它們設置的handler是同享的。
可以理解為,logging名相同則注冊在內存里,每次getLogger時,內存里有就指向它,沒有就新建一個。
也就是說,第一個logging.getLogger("MyLogging")設置了handler后,第二處調用logging.getLogger("MyLogging")時拿到的logging已經有handler了。如果每次初始化logging都加句柄,就會導致該句柄重復添加,重復輸出。
可以通過查看該logging的handler的方式,判斷還加不加。沒有就加,有就算了。
class Logger(object):
def __init__(self, logname="ScanDeault"):
self.logger = logging.getLogger(logname)
self.logger.setLevel(logging.DEBUG)
def getScanLogger(self):
if self.logger.handlers:
return self.logger
mon = MongoHandler(url=MONGO_SCAN_URL, database_name=MONGO_SCAN_DATABASE)
mon.setLevel(logging.WARN)
# ch = logging.StreamHandler()
# fmt = logging.Formatter('[%(asctime)s][%(levelname)-5s] %(funcName)s(%(lineno)d) : %(message)s',
# "%Y-%m-%d %H:%M:%S")
# ch.setFormatter(fmt)
# ch.setLevel(logging.INFO)
self.logger.addHandler(mon)
# self.logger.addHandler(ch)
return self.logger
這里注意,如果在其他地方把這個logname添加了個ERROR的handler,會導致這里的handler加不上了,handler失效
class MongoHandler(logging.Handler):
def __init__(self, level=logging.NOTSET, url=None, host='localhost', port=27017,
database_name='logs', collection='t_logs',
username=None, password=None, authentication_db='admin',
fail_silently=False, formatter=None, capped=False,
capped_max=1000, capped_size=1000000, reuse=True, **kwargs):
"""
Setting up mongo handler, initializing mongo database connection via
pymongo.
If reuse is set to false every handler will have it's own MongoClient.
This could hammer down your MongoDB instance, but you can still use
this option.
The default is True. As such a program with multiple handlers
that log to mongodb will have those handlers share a single connection
to MongoDB.
"""
logging.Handler.__init__(self, level)
self.url = url # changed, 新增MongoDB連接方式
self.host = host
self.port = port
self.database_name = database_name
self.collection_name = collection
self.username = username
self.password = password
self.authentication_database_name = authentication_db
self.fail_silently = fail_silently
self.connection = None
self.db = None
self.collection = None
self.authenticated = False
self.formatter = formatter or MongoFormatter()
self.capped = capped
self.capped_max = capped_max
self.capped_size = capped_size
self.reuse = reuse
self._connect(**kwargs)
def _connect(self, **kwargs):
"""Connecting to mongo database."""
global _connection
if self.reuse and _connection:
self.connection = _connection
else:
if pymongo.version_tuple[0] < 3:
try:
if self.url:
self.connection = Connection(self.url)
else:
self.connection = Connection(host=self.host,
port=self.port, **kwargs)
# pymongo >= 3.0 does not raise this error
except PyMongoError:
if self.fail_silently:
return
else:
raise
else:
if self.url:
self.connection = Connection(self.url)
else:
self.connection = Connection(host=self.host, port=self.port, **kwargs)
try:
self.connection.is_primary
except ServerSelectionTimeoutError:
if self.fail_silently:
return
else:
raise
_connection = self.connection
self.db = self.connection[self.database_name]
if self.username is not None and self.password is not None:
auth_db = self.connection[self.authentication_database_name]
self.authenticated = auth_db.authenticate(self.username,
self.password)
if self.capped:
#
# We don't want to override the capped collection
# (and it throws an error anyway)
try:
self.collection = Collection(self.db, self.collection_name,
capped=True, max=self.capped_max,
size=self.capped_size)
except OperationFailure:
# Capped collection exists, so get it.
self.collection = self.db[self.collection_name]
else:
self.collection = self.db[self.collection_name]
def close(self):
"""
If authenticated, logging out and closing mongo database connection.
"""
if self.authenticated:
self.db.logout()
if self.connection is not None:
self.connection.close()
def emit(self, record):
"""Inserting new logging record to mongo database."""
if self.collection is not None:
try:
if os.path.basename(__file__) not in record.pathname:
getattr(self.collection, write_method)(self.format(record))
except Exception:
if not self.fail_silently:
self.handleError(record)
class MyLogger(object):
def __init__(self, logname="MyRePrint"):
self.logger = logging.getLogger(logname)
self.logger.setLevel(logging.DEBUG)
if not self.logger.handlers:
mon = MongoHandler(url=MONGO_SCAN_URL, database_name=MONGO_SCAN_DATABASE)
mon.setLevel(logging.INFO) # print為INFO級別
ch = logging.StreamHandler()
ch.setFormatter(logging.Formatter('[%(asctime)s][%(levelname)-5s] %(funcName)s(%(lineno)d) : %(message)s',
"%Y-%m-%d %H:%M:%S"))
ch.setLevel(logging.INFO)
self.logger.addHandler(ch)
self.logger.addHandler(mon)
def write(self, message):
if message.strip():
self.logger.info(message)
if __name__ == '__main__':
original_stdout = sys.stdout
sys.stdout = PluginLogger(logname="MyRePrint")
print 1
sys.stdout = original_stdout