鉴于正在多个服务器上同时执行的Django应用程序,该应用程序如何记录到单个共享日志文件(在网络共享中),而不保持此文件在独占模式下永久打开?
当您想要利用日志流时,这种情况适用于托管在Windows Azure网站上的Django应用程序。
在this sample project上,我尝试使用ConcurrentLogHandler,如下所示:
settings.py中的:
'ConcurrentLogHandler':{
'level': 'DEBUG',
'class': 'cloghandler.ConcurrentRotatingFileHandler',
'formatter': 'verbose',
'filename': os.getenv('LOGFILE', 'django.log')
},
views.py中的:
from time import gmtime, strftime
import logging
from django.http import HttpResponse
logger = logging.getLogger(__name__)
def home(request):
current_time = strftime("%Y-%m-%d %H:%M:%S", gmtime())
logger.info('home ' + current_time)
return HttpResponse("Hello from Django! It is now " + current_time + ".\n")
日志已写入,但网站运行时似乎没有刷新文件。此外,如果我尝试使用FTP读取文件,我会收到以下消息:“550进程无法访问该文件,因为它正被另一个进程使用。”
如果我停止应用程序,文件将关闭,我可以读取该文件并查看其中的所有日志。
我假设ConcurrentLogHandler允许对日志文件的共享访问。这个假设是错的吗?是否需要一些额外的配置?还有其他选择吗?
答案 0 :(得分:3)
另一种方法是将所有Django日志记录发送到队列(例如Redis队列,使用this或multiprocessing.Queue
之类的东西)然后单个进程读取队列并写入记录到文件。有更多移动部件,因此这可能适合您的需要,也可能不适合,但它会消除文件争用。有关使用多个进程记录的更多选项,请参阅this post。
您当然也可以设置套接字服务器并使用SocketHandler
将所有Django进程的日志记录事件发送到写入文件的服务器。 Python文档包含working example这样的服务器。
答案 1 :(得分:2)
可以使用syslog-ng
实现可扩展的纯日志记录方法(如仅使用系统日志记录组件)syslog-ng是syslog ++,所以它不会破坏任何syslog配置和日志记录,如果你已经有了。在Ubuntu上安装非常简单:
sudo apt-get install syslog-ng
要在Windows上安装,请参阅:http://www.syslog.org/logged/running-syslog-ng-on-windows/
多个django应用程序或多个服务器登录到syslog-ng,它使用UDP或TCP(取决于您的配置)将其发送到中央syslog-ng服务器,该服务器将其记录在该计算机上。您可以使用基本正则表达式来识别syslog-ng中的应用程序并进行相应的路由。
Django日志记录配置
'syslog-verbose': {
'format': 'myapp %(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
}
'ConcurrentLogHandler':{
'level': 'DEBUG',
'class': 'logging.handlers.SysLogHandler',
'formatter': 'syslog-verbose',
},
请注意添加到格式化程序中的“myapp”字符串,以通过syslog-ng识别应用程序。
您甚至可以配置nginx,apache和其他服务器来登录syslog-ng。例如。对于apache:
CustomLog "| /usr/bin/logger -t 'apache' -u /var/run/apache_access_log.socket" combined
Syslog-ng客户端配置
将此附加到/etc/syslog-ng/syslog-ng.conf的末尾
filter filter_loghostclient {
program("^myapp$");
};
destination dest_loghostclient {
tcp("destination_logserver.example.com" port (514));
};
log {
source(s_all);
filter(filter_loghostclient);
destination(dest_loghostclient);
};
source s_apache_access {
#apache access logs getting written directly to a socket (as described above)
unix-stream("/var/run/apache_access_log.socket" max-connections(512) keep-alive(yes));
};
log{
source(s_apache_access);
destination(dest_loghostclient);
};
filter f_apache_err {
#Apache error logs
program("apache") and level(err);
};
log{
source(s_all);
filter(f_apache_err);
destination(dest_loghostclient);
};
Syslog-ng聚合器配置
将以下内容附加到destination_logserver.example.com上的syslog-ng配置文件
source src_loghostserver {
tcp(port(514) keep-alive(yes) max_connections(1000));
};
destination dest_loghostserver {
file("/var/log/myproject/request_\$R_YEAR\$R_MONTH\$R_DAY.log");
};
log {
source(src_loghostserver);
destination(dest_loghostserver);
};