日志记录¶
参见
基本的日志记录¶
uWSGI中最基本的日志记录的形式是将请求、错误和信息消息写到标准输出/标准错误。这是默认配置中使用的方式。日志重定向的最基本的形式是 --logto
/
--logto2
/ --daemonize
选项,它们允许你重定向日志到文件中。
基本记录日志到文件¶
要将日志写到文件中,而不是标准输出/标准错误,则使用 --logto
,或者同时守护uWSGI, --daemonize
。
./uwsgi -s :3031 -w simple_app --daemonize /tmp/mylog.log
./uwsgi -s :3031 -w simple_app --logto /tmp/mylog.log
# logto2 only opens the log file after privileges have been dropped to the specified uid/gid.
./uwsgi -s :3031 -w simple_app --uid 1001 --gid 1002 --logto2 /tmp/mylog.log
基本日志记录 (连接UDP模式)¶
使用UDP日志记录,你可以集中集群日志记录,或者重定向日志的持久化到其他机器上,以卸载磁盘I/O。UDP日志记录可以工作在守护模式和互动模式下。UDP日志记录是在连接socket模式下进行的,因此,UDP服务器必须在uWSGI启动前可用。对于更原始的方法(在未连接模式下工作),见socket日志记录部分。
要启用连接UDP模式,则传递UDP服务器的地址到 --daemonize
/--logto
选项:
./uwsgi -s :3031 -w simple_app --daemonize 192.168.0.100:1717
./uwsgi -s :3031 -w simple_app --logto 192.168.0.100:1717
这将会重定向所有的标准输出/标准错误数据到192.168.0.100,端口1717上的UDP socket。现在,你需要一个UDP服务器,它将管理你的UDP消息。你可以使用netcat,甚至是uWSGI:
nc -u -p 1717 -s 192.168.0.100 -l
./uwsgi --udp 192.168.0.100:1717
第二种方式更有用一点,因为它将打印每条消息的来源 (ip:port)。在多个uWSGI服务器将日志记录在同一个UDP服务器上的情况下,它将让你区分服务器。当然,你可以编写你自己的应用来管理/过滤/保存通过UDP接收到的日志。
可插拔记录器¶
uWSGI还支持可插拔记录器,这让你在何处以及如何记录更具灵活性。取决于于你的uWSGI构建的配置,一些记录器可能/可能没有用。一些也许要求作为插件加载。要找出你的构建中哪些插件可用,请带 --logger-list
调用uWSGI。要设置一个可插拔记录器,则使用 --logger
或者
--req-logger
选项。 --logger
将为每条消息设置一个记录器,而 --req-logger
将会为请求信息消息设置一个记录器。
这是语法:
--logger <plugin>[:options]
--logger "<name> <plugin>[:options]" # The quotes are only required on the command line -- config files don't use them
只要你喜欢,你可以设置尽可能多的记录器。命名插件用于日志路由,下面是使用纯文本文件分割请求/错误日志记录的一个非常简单的例子。
[uwsgi]
req-logger = file:/tmp/reqlog
logger = file:/tmp/errlog
日志路由¶
默认情况下,所有的日志行会被发送到所有声明的记录器。如果你不想要这样,那么你可以使用 --log-route
(以及用于请求记录器的 --log-req-route
),指定一个正则表达式来路由某些日志消息到不同的目的地。
例如:
[uwsgi]
logger = mylogger1 syslog
logger = theredisone redislog:127.0.0.1:6269
logger = theredistwo redislog:127.0.0.1:6270
logger = file:/tmp/foobar # This logger will log everything else, as it's not named
logger = internalservererror file:/tmp/errors
# ...
log-route = internalservererror (HTTP/1.\d 500)
log-route = mylogger1 uWSGI listen queue of socket .* full
这将会记录每个500错误到/tmp/errors,而监听队列满错误将会出现在/tmp/foobar中。这有点类似于 uWSGI告警子系统 (自1.3起) ,虽然告警通常更重,应该只用于紧急情况。
写日志到文件中¶
logfile
插件 —— 默认嵌入。
写日志到socket¶
logsocket
插件 —— 默认嵌入。
你可以使用 --logger socket:...
(或者 --log-socket ...
) 写日志到一个未连接UNIX/UDP socket。
uwsgi --socket :3031 --logger socket:/tmp/uwsgi.logsock
将会发送日志项到Unix socket /tmp/uwsgi.logsock
.
uwsgi --socket :3031 --logger socket:192.168.173.19:5050
将会发送日志数据报到UDP地址192.168.173.19,端口是5050.你也可以通过传递多播地址,多播日志到多个日志服务器上:
uwsgi --socket :3031 --logger socket:225.1.1.1:1717
写日志到syslog¶
logsyslog
插件 —— 默认嵌入。
logsyslog
插件路由日志到Unix标准的syslog中。你可以传递一个用于发送的可选的ID,作为日志项的”facility”参数。
uwsgi --socket :3031 --logger syslog:uwsgi1234
或者
uwsgi --socket :3031 --logger syslog:uwsgi1234,local6
发送到local6 facility
写日志到远程syslog¶
logrsyslog
插件 —— 默认嵌入。
logrsyslog
插件路由日志到位于远程服务器的Unix标准syslog上。除了远程syslog服务器的address+port外,你可以传递一个用于发送的可选的ID,作为日志项的”facility”参数。
uwsgi --socket :3031 --logger rsyslog:12.34.56.78:12345,uwsgi1234
Redis记录器¶
redislog
插件 —— 默认嵌入。
默认情况下, redislog
插件将会“发布”每个日志行到一个redis pub/sub队列中。该记录器插件的语法如下:
--logger redislog[:<host>,<command>,<prefix>]
默认, host
会被映射到 127.0.0.1:6379
, command
会被映射到”publish uwsgi” 并且 prefix
是空的。要发布到一个名为foobar的队列,则使用 redislog:127.0.0.1:6379,publish foobar
。Redis日记记录不只限于pub/sub。例如,你可以推送项到一个列表中,如下所示。
--logger redislog:/tmp/redis.sock,rpush foo,example.com
当将一个日志行写入到一个远程服务器的时候,一个错误的场景会导致阻塞master,好的办法是使用 --threaded-logger
来卸载日志写入到第二个线程中。
MongoDB记录器¶
mongodblog
插件 —— 默认嵌入。.
MongoDB日志记录(mongodblog
)的记录器语法是
--logger mongodblog[:<host>,<collection>,<node>]
其中, host
是MongoDB实例的地址 (默认 127.0.0.1:27017
), collection
命名要写入日志行的集合 (默认是 uwsgi.logs
),而 node
是用于实例发送日志的身份字符串 (默认是server hostname)。
--logger mongodblog
将会用默认值运行记录器,而
--logger mongodblog:127.0.0.1:9090,foo.bar
将会写入日志到mongodb服务器127.0.0.1:9090的集合 foo.bar
中,使用默认的节点名。就如Redis记录器一样,卸载日志写入到一个专用的线程是个好的选择。
[uwsgi]
threaded-logger = true
logger = mongodblog:127.0.0.1:27017,uwsgi.logs_of_foobar
# As usual, you could have multiple loggers:
# logger = mongodblog:192.168.173.22:27017,uwsgi.logs_of_foobar
socket = :3031
ZeroMQ日志记录¶
就如UDP日志记录一样,你可以通过ZeroMQ集中/分布日志记录。使用 ZMQ_PULL
socket构建你的日志记录守护程序:
import zmq
ctx = zmq.Context()
puller = ctx.socket(zmq.PULL)
puller.bind("tcp://192.168.173.18:9191")
while True:
message = puller.recv()
print message,
现在,运行你的uWSGI服务器:
uwsgi --logger zeromq:tcp://192.168.173.18:9191 --socket :3031 --module werkzeug.testapp:test_app
(--log-zeromq
是这个记录器的一个别名。)
Crypto记录器 (插件)¶
如果你在云服务商托管你的应用,并且不使用持久化存储,那么你也许想要发送你的日志到一个外部系统。然而,日志通常包含敏感信息,并应该将那些信息明文传输。
logcrypto
插件记录器试图通过在发送之前加密每个日志包,然后通过UDP发送到一个能够解密它的服务器,从而解决这个问题。下一个例子将会发送每个日志包到192.168.173.22:1717上的一个UDP服务器,每个日志包都会用CBC模式中的Blowfish算法,通过密钥 ciaociao
进行加密。
uwsgi --plugin logcrypto --logger crypto:addr=192.168.173.22:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031
一个样例服务器如下: https://github.com/unbit/uwsgi/blob/master/contrib/cryptologger.rb
Graylog2记录器 (插件)¶
graylog2
插件 —— 非默认编译。
这个插件将会发送日志的到一个Graylog2服务器上,使用Graylog2的原生GELF格式。
uwsgi --plugin graylog2 --logger graylog2:127.0.0.1:1234,dsfargeg
Systemd记录器 (插件)¶
systemd_logger
插件 —— 非默认编译。
这个插件将会将日志项写入到Systemd journal中。
uwsgi --plugin systemd_logger --logger systemd
编写你自己的日志记录插件¶
这个插件, foolog.c
将会把你的消息写入到由–logto/–daemonize指定的文件中,带有一个简单前缀,并使用vector IO。
#include <uwsgi.h>
ssize_t uwsgi_foolog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
struct iovec iov[2];
iov[0].iov_base = "[foo] ";
iov[0].iov_len = 6;
iov[1].iov_base = message;
iov[1].iov_len = len;
return writev(uwsgi.original_log_fd, iov, 2);
}
void uwsgi_foolog_register() {
uwsgi_register_logger("syslog", uwsgi_syslog_logger);
}
struct uwsgi_plugin foolog_plugin = {
.name = "foolog",
.on_load = uwsgi_foolog_register,
};