7

给定一个在多个服务器上同时执行的 Django 应用程序,该应用程序如何在不保持该文件以独占模式永久打开的情况下记录到单个共享日志文件(在网络共享中)?

当您想要利用日志流时,这种情况适用于托管在 Windows Azure 网站上的 Django 应用程序。

这个示例项目中,我尝试像这样使用ConcurrentLogHandler

settings.py 中

'ConcurrentLogHandler':{
    'level': 'DEBUG',
    'class': 'cloghandler.ConcurrentRotatingFileHandler',
    'formatter': 'verbose',
    'filename': os.getenv('LOGFILE', 'django.log')
},

view.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 将允许共享访问日志文件。这个假设是错误的吗?是否需要一些额外的配置?有替代方案吗?

4

2 回答 2

3

另一种方法是将所有 Django 日志记录发送到队列(例如 Redis 队列,使用类似this或 a multiprocessing.Queue),然后单个进程读取队列并将记录写入文件。有更多的移动部件,所以这可能适合也可能不适合您的需要,但它会消除文件争用。使用来自多个进程的日志记录时,请参阅这篇文章以获取更多选项。

当然,您也可以设置一个套接字服务器并使用 aSocketHandler将所有 Django 进程的日志事件发送到服务器,该服务器将写入文件。Python 文档包含此类服务器的工作示例

于 2013-07-28T11:39:39.620 回答
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。例如对于阿帕奇:

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);
};
于 2013-08-18T15:26:12.537 回答