Uwsgi error log

Official uWSGI docs, examples, tutorials, tips and tricks - uwsgi-docs/Logging.rst at master · unbit/uwsgi-docs

Logging

.. seealso:: :doc:`LogFormat`

Basic logging

The most basic form of logging in uWSGI is writing requests, errors, and
informational messages to stdout/stderr. This happens in the default
configuration. The most basic form of log redirection is the --logto /
--logto2 / --daemonize options which allow you to redirect logs to
files.

Basic logging to files

To log to files instead of stdout/stderr, use --logto, or to simultaneously
daemonize 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

Basic logging (connected UDP mode)

With UDP logging you can centralize cluster logging or redirect the persistence
of logs to another machine to offload disk I/O. UDP logging works in both
daemonized and interactive modes. UDP logging operaties in connected-socket
mode, so the UDP server must be available before uWSGI starts. For a more raw
approach (working in unconnected mode) see the section on socket logging.

To enable connected UDP mode pass the address of a UDP server to the
--daemonize/--logto option:

./uwsgi -s :3031 -w simple_app --daemonize 192.168.0.100:1717
./uwsgi -s :3031 -w simple_app --logto 192.168.0.100:1717

This will redirect all the stdout/stderr data to the UDP socket on
192.168.0.100, port 1717. Now you need an UDP server that will manage your UDP
messages. You could use netcat, or even uWSGI:

nc -u -p 1717 -s 192.168.0.100 -l
./uwsgi --udp 192.168.0.100:1717

The second way is a bit more useful as it will print the source (ip:port) of
every message. In case of multiple uWSGI server logging on the same UDP server
it will allow you to recognize one server from another. Naturally you can
write your own apps to manage/filter/save the logs received via udp.

Pluggable loggers

uWSGI also supports pluggable loggers, which allow you more flexibility on
where and what to log. Depending on the configuration of your uWSGI build,
some loggers may or may not be available. Some may require to be loaded as
plugins. To find out what plugins are available in your build, invoke uWSGI
with --logger-list. To set up a pluggable logger, use the --logger or
--req-logger options. --logger will set up a logger for every message
while --req-logger will set up a logger for request information messages.

This is the syntax:

--logger <plugin>[:options]
--logger "<name> <plugin>[:options]" # The quotes are only required on the command line -- config files don't use them

You may set up as many loggers as you like. Named plugins are used for log
routing. A very simple example of split request/error logging using plain text
files follows.

[uwsgi]
req-logger = file:/tmp/reqlog
logger = file:/tmp/errlog

Log routing

By default all log lines are sent to all declared loggers. If this is not what
you want, you can use --log-route (and --log-req-route for request
loggers) to specify a regular expression to route certain log messages to
different destinations.

For instance:

[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

This will log each 500 level error to /tmp/errors, while listen queue full errors
will end up in /tmp/foobar. This is somewhat similar to the
:doc:`AlarmSubsystem`, though alarms are usually heavier and should only be
used for critical situations.

Logging to files

logfile plugin — embedded by default.

uwsgi --socket :3031 --logger file:/tmp/uwsgi.log

You can optionally configure automatic log rotation:

uwsgi --socket :3031 --logger file:logfile=/tmp/uwsgi.log,maxsize=2000000

This will rotate the log file once it reaches 2 million bytes. The new name
will be the original log file with the extension replaced with a timestamp.

You can also specify the backupname instead of allowing uWSGI to autogenerate
one.

Logging to sockets

logsocket plugin — embedded by default.

You can log to an unconnected UNIX or UDP socket using --logger socket:...
(or --log-socket ...).

uwsgi --socket :3031 --logger socket:/tmp/uwsgi.logsock

will send log entries to the Unix socket /tmp/uwsgi.logsock.

uwsgi --socket :3031 --logger socket:192.168.173.19:5050

will send log datagrams to the UDP address 192.168.173.19 on port 5050. You
may also multicast logs to multiple log servers by passing the multicast
address:

uwsgi --socket :3031 --logger socket:225.1.1.1:1717

Logging to syslog

syslog plugin — embedded by default

The syslog plugin routes logs to Unix standard syslog. You may pass an
optional ID to send and the «facility» for the log entry.

uwsgi --socket :3031 --logger syslog:uwsgi1234

or

uwsgi --socket :3031 --logger syslog:uwsgi1234,local6

to send to the local6 facility

Logging to remote syslog

rsyslog plugin — embedded by default

The rsyslog plugin routes logs to Unix standard syslog residing on a
remote server. In addtition to the address+port of the remote syslog server,
you may pass an optional ID to send as the «facility» parameter for the log
entry.

uwsgi --socket :3031 --logger rsyslog:12.34.56.78:12345,uwsgi1234

Redis logger

redislog plugin — embedded by default.

By default the redislog plugin will ‘publish’ each logline to a redis
pub/sub queue. The logger plugin syntax is:

--logger redislog[:<host>,<command>,<prefix>]

By default host is mapped to 127.0.0.1:6379, command is mapped to
«publish uwsgi» and prefix is empty. To publish to a queue called foobar,
use redislog:127.0.0.1:6379,publish foobar. Redis logging is not limited
to pub/sub. You could for instance push items into a list, as in the next
example.

--logger redislog:/tmp/redis.sock,rpush foo,example.com

As error situations could cause the master to block while writing a log line to
a remote server, it’s a good idea to use --threaded-logger to offload log
writes to a secondary thread.

MongoDB logger

mongodblog plugin — embedded by default.

The logger syntax for MongoDB logging (mongodblog) is

--logger mongodblog[:<host>,<collection>,<node>]

Where host is the address of the MongoDB instance (default
127.0.0.1:27017), collection names the collection to write log lines
into (default uwsgi.logs) and node is an identification string for the
instance sending logs (default: server hostname).

Will run the logger with default values, while

--logger mongodblog:127.0.0.1:9090,foo.bar

Will write logs to the mongodb server 127.0.0.1:9090 in the collection
foo.bar using the default node name. As with the Redis logger, offloading
log writes to a dedicated thread is a good choice.

[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 logging

As with UDP logging you can centralize/distribute logging via ZeroMQ. Build
your logger daemon using a 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,

Now run your uWSGI server:

uwsgi --logger zeromq:tcp://192.168.173.18:9191 --socket :3031 --module werkzeug.testapp:test_app

(--log-zeromq is an alias for this logger.)

Crypto logger (plugin)

If you host your applications on cloud services without persistent storage you
may want to send your logs to external systems. However logs often contain
sensitive information that should not be transferred in clear. The
logcrypto plugin logger attempts to solve this issue by encrypting each log
packet before sending it over UDP to a server able to decrypt it. The next
example will send each log packet to a UDP server available at
192.168.173.22:1717 encrypting the text with the secret key ciaociao with
Blowfish in CBC mode.

uwsgi --plugin logcrypto --logger crypto:addr=192.168.173.22:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031

An example server is available at
https://github.com/unbit/uwsgi/blob/master/contrib/cryptologger.rb

Graylog2 logger (plugin)

graylog2 plugin — not compiled by default.

This plugin will send logs to a Graylog2 server in Graylog2’s native GELF format.

uwsgi --plugin graylog2 --logger graylog2:127.0.0.1:1234,dsfargeg

Systemd logger (plugin)

systemd_logger plugin — not compiled by default.

This plugin will write log entries into the Systemd journal.

uwsgi --plugin systemd_logger --logger systemd

Writing your own logger plugins

This plugin, foolog.c will write your messages in the file specified with
—logto/—daemonize with a simple prefix using 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,
};

Basic logging¶

The most basic form of logging in uWSGI is writing requests, errors, and
informational messages to stdout/stderr. This happens in the default
configuration. The most basic form of log redirection is the --logto /
--logto2 / --daemonize options which allow you to redirect logs to
files.

Basic logging to files¶

To log to files instead of stdout/stderr, use --logto, or to simultaneously
daemonize 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

Basic logging (connected UDP mode)¶

With UDP logging you can centralize cluster logging or redirect the persistence
of logs to another machine to offload disk I/O. UDP logging works in both
daemonized and interactive modes. UDP logging operaties in connected-socket
mode, so the UDP server must be available before uWSGI starts. For a more raw
approach (working in unconnected mode) see the section on socket logging.

To enable connected UDP mode pass the address of a UDP server to the
--daemonize/--logto option:

./uwsgi -s :3031 -w simple_app --daemonize 192.168.0.100:1717
./uwsgi -s :3031 -w simple_app --logto 192.168.0.100:1717

This will redirect all the stdout/stderr data to the UDP socket on
192.168.0.100, port 1717. Now you need an UDP server that will manage your UDP
messages. You could use netcat, or even uWSGI:

nc -u -p 1717 -s 192.168.0.100 -l
./uwsgi --udp 192.168.0.100:1717

The second way is a bit more useful as it will print the source (ip:port) of
every message. In case of multiple uWSGI server logging on the same UDP server
it will allow you to recognize one server from another. Naturally you can
write your own apps to manage/filter/save the logs received via udp.

Pluggable loggers¶

uWSGI also supports pluggable loggers, which allow you more flexibility on
where and what to log. Depending on the configuration of your uWSGI build,
some loggers may or may not be available. Some may require to be loaded as
plugins. To find out what plugins are available in your build, invoke uWSGI
with --logger-list. To set up a pluggable logger, use the --logger or
--req-logger options. --logger will set up a logger for every message
while --req-logger will set up a logger for request information messages.

This is the syntax:

--logger <plugin>[:options]
--logger "<name> <plugin>[:options]" # The quotes are only required on the command line -- config files don't use them

You may set up as many loggers as you like. Named plugins are used for log
routing. A very simple example of split request/error logging using plain text
files follows.

[uwsgi]
req-logger = file:/tmp/reqlog
logger = file:/tmp/errlog

Log routing¶

By default all log lines are sent to all declared loggers. If this is not what
you want, you can use --log-route (and --log-req-route for request
loggers) to specify a regular expression to route certain log messages to
different destinations.

For instance:

[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

This will log each 500 level error to /tmp/errors, while listen queue full errors
will end up in /tmp/foobar. This is somewhat similar to the
The uWSGI alarm subsystem (from 1.3), though alarms are usually heavier and should only be
used for critical situations.

Logging to files¶

logfile plugin – embedded by default.

uwsgi --socket :3031 --logger file:/tmp/uwsgi.log

You can optionally configure automatic log rotation:

uwsgi --socket :3031 --logger file:logfile=/tmp/uwsgi.log,maxsize=2000000

This will rotate the log file once it reaches 2 million bytes. The new name
will be the original log file with the extension replaced with a timestamp.

You can also specify the backupname instead of allowing uWSGI to autogenerate
one.

Logging to sockets¶

logsocket plugin – embedded by default.

You can log to an unconnected UNIX or UDP socket using --logger socket:...
(or --log-socket ...).

uwsgi --socket :3031 --logger socket:/tmp/uwsgi.logsock

will send log entries to the Unix socket /tmp/uwsgi.logsock.

uwsgi --socket :3031 --logger socket:192.168.173.19:5050

will send log datagrams to the UDP address 192.168.173.19 on port 5050. You
may also multicast logs to multiple log servers by passing the multicast
address:

uwsgi --socket :3031 --logger socket:225.1.1.1:1717

Logging to syslog¶

syslog plugin – embedded by default

The syslog plugin routes logs to Unix standard syslog. You may pass an
optional ID to send and the “facility” for the log entry.

uwsgi --socket :3031 --logger syslog:uwsgi1234

or

uwsgi --socket :3031 --logger syslog:uwsgi1234,local6

to send to the local6 facility

Logging to remote syslog¶

rsyslog plugin – embedded by default

The rsyslog plugin routes logs to Unix standard syslog residing on a
remote server. In addtition to the address+port of the remote syslog server,
you may pass an optional ID to send as the “facility” parameter for the log
entry.

uwsgi --socket :3031 --logger rsyslog:12.34.56.78:12345,uwsgi1234

Redis logger¶

redislog plugin – embedded by default.

By default the redislog plugin will ‘publish’ each logline to a redis
pub/sub queue. The logger plugin syntax is:

--logger redislog[:<host>,<command>,<prefix>]

By default host is mapped to 127.0.0.1:6379, command is mapped to
“publish uwsgi” and prefix is empty. To publish to a queue called foobar,
use redislog:127.0.0.1:6379,publish foobar. Redis logging is not limited
to pub/sub. You could for instance push items into a list, as in the next
example.

--logger redislog:/tmp/redis.sock,rpush foo,example.com

As error situations could cause the master to block while writing a log line to
a remote server, it’s a good idea to use --threaded-logger to offload log
writes to a secondary thread.

MongoDB logger¶

mongodblog plugin – embedded by default.

The logger syntax for MongoDB logging (mongodblog) is

--logger mongodblog[:<host>,<collection>,<node>]

Where host is the address of the MongoDB instance (default
127.0.0.1:27017), collection names the collection to write log lines
into (default uwsgi.logs) and node is an identification string for the
instance sending logs (default: server hostname).

Will run the logger with default values, while

--logger mongodblog:127.0.0.1:9090,foo.bar

Will write logs to the mongodb server 127.0.0.1:9090 in the collection
foo.bar using the default node name. As with the Redis logger, offloading
log writes to a dedicated thread is a good choice.

[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 logging¶

As with UDP logging you can centralize/distribute logging via ZeroMQ. Build
your logger daemon using a 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,

Now run your uWSGI server:

uwsgi --logger zeromq:tcp://192.168.173.18:9191 --socket :3031 --module werkzeug.testapp:test_app

(--log-zeromq is an alias for this logger.)

Crypto logger (plugin)¶

If you host your applications on cloud services without persistent storage you
may want to send your logs to external systems. However logs often contain
sensitive information that should not be transferred in clear. The
logcrypto plugin logger attempts to solve this issue by encrypting each log
packet before sending it over UDP to a server able to decrypt it. The next
example will send each log packet to a UDP server available at
192.168.173.22:1717 encrypting the text with the secret key ciaociao with
Blowfish in CBC mode.

uwsgi --plugin logcrypto --logger crypto:addr=192.168.173.22:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031

An example server is available at
https://github.com/unbit/uwsgi/blob/master/contrib/cryptologger.rb

Graylog2 logger (plugin)¶

graylog2 plugin – not compiled by default.

This plugin will send logs to a Graylog2 server in Graylog2’s native GELF format.

uwsgi --plugin graylog2 --logger graylog2:127.0.0.1:1234,dsfargeg

Systemd logger (plugin)¶

systemd_logger plugin – not compiled by default.

This plugin will write log entries into the Systemd journal.

uwsgi --plugin systemd_logger --logger systemd

Writing your own logger plugins¶

This plugin, foolog.c will write your messages in the file specified with
–logto/–daemonize with a simple prefix using 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,
};

Базовое ведение журнала

Самая простая форма ведения журнала (логирования) в uWSGI — это запись запросов, ошибок и информационных сообщений в stdout/stderr. Это происходит в конфигурации по умолчанию. Самой простой формой перенаправления логов являются параметры:

  • —logto
  • —logto2
  • —daemonize

которые позволяют перенаправлять журналы в файлы.

Базовое ведение журнала в файлы

Для записи в файлы вместо stdout/stderr используйте —logto или для одновременной демонизации uWSGI —daemonize.

./uwsgi -s :3031 -w simple_app --daemonize /tmp/mylog.log
./uwsgi -s :3031 -w simple_app --logto /tmp/mylog.log
# logto2 открывает файл журнала только после того, как привилегии были снижены до указанного uid/gid.
./uwsgi -s :3031 -w simple_app --uid 1001 --gid 1002 --logto2 /tmp/mylog.log

Базовое ведение журнала (подключенный режим UDP)

С помощью ведения журнала UDP вы можете централизовать ведение журнала кластера или перенаправить сохранение журналов на другую машину, чтобы разгрузить дисковый ввод-вывод (I/O). Ведение журнала UDP работает как в демоническом, так и в интерактивном режимах. Ведение журнала UDP работает в режиме подключенного сокета, поэтому сервер UDP должен быть доступен до запуска uWSGI. Более простой подход (работа в режиме без подключения) см. в разделе, посвященном ведению журнала сокетов.

Чтобы включить подключенный режим 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

Это перенаправит все данные stdout/stderr в сокет UDP на 192.168.0.100, порт 1717. Теперь вам нужен сервер 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 некоторые регистраторы могут быть доступны или недоступны.

Некоторые могут потребоваться для загрузки в виде подключаемых модулей. доступны в вашей сборке, вызовите uWSGI с параметром —logger-list.

Чтобы настроить подключаемый регистратор, используйте параметры —logger или —req-logger.

—logger настроит регистратор для каждого сообщения.

—req-logger настроит регистратор для информационных сообщений запроса.

Это синтаксис:

--logger <plugin>[:options]
--logger "<name> <plugin>[:options]" # Кавычки требуются только в командной строке — файлы конфигурации их не используют.

Вы можете настроить любое количество регистраторов. Именованные плагины используются для маршрутизации журналов. Ниже приведён очень простой пример разделённого журнала запросов/ошибок с использованием текстовых файлов.

[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 — встроен по умолчанию.

uwsgi --socket :3031 --logger file:/tmp/uwsgi.log

При желании можно настроить автоматическую ротацию логов:

uwsgi --socket :3031 --logger file:logfile=/tmp/uwsgi.log,maxsize=2000000

Это заменит файл журнала, как только он достигнет 2 млн байт. Новое имя будет исходным файлом журнала с заменой расширения на метку времени.

Вы также можете указать имя резервной копии вместо того, чтобы позволять uWSGI создавать ее автоматически.

Ведение журнала в сокеты

Плагин logsocket — встроен по умолчанию.

Вы можете войти в несвязанный сокет UNIX или UDP, используя —logger socket:… (или —log-socket …).

uwsgi --socket :3031 --logger socket:/tmp/uwsgi.logsock

будет отправлять записи журнала в сокет Unix /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 — встроен по умолчанию

Плагин системного журнала syslog направляет журналы в стандартный системный журнал Unix.Вы можете передать необязательный идентификатор для отправки и «средство» (facility) для записи в журнале.

uwsgi --socket :3031 --logger syslog:uwsgi1234

или

uwsgi --socket :3031 --logger syslog:uwsgi1234,local6

для отправки на объект local6

Ведение журнала в удалённый системный журнал

Плагин rsyslog — встроен по умолчанию

Плагин rsyslog направляет журналы в стандартный системный журнал Unix, расположенный на удаленном сервере.В дополнение к адресу и порту удаленного сервера системного журнала вы можете передать необязательный идентификатор для отправки в качестве параметра «средство» (facility) для записи журнала.

uwsgi --socket :3031 --logger rsyslog:12.34.56.78:12345,uwsgi1234

Ведение журнала через Redis

Плагин redislog — встроен по умолчанию.

По умолчанию подключаемый модуль redislog «публикует»(publish) каждую строку журнала в очереди публикации/подписки redis Синтаксис подключаемого модуля регистратора:

--logger redislog[:<host>,<command>,<prefix>]

По умолчанию хост host сопоставляется с 127.0.0.1:6379, команда command сопоставляется с «публикацией uwsgi», а префикс prefix пуст. Чтобы опубликовать в очередь с именем foobar, используйте redislog:127.0.0.1:6379,publish foobar. Ведение журнала Redis не ограничивается pub/sub. Например, вы можете поместить элементы в список, как в следующем примере.

--logger redislog:/tmp/redis.sock,rpush foo,example.com

Поскольку ошибки могут привести к блокировке главного сервера при записи строки журнала на удаленный сервер, рекомендуется использовать параметр —threaded-logger, чтобы разгрузить запись журнала во вторичный поток.

Ведение журнала через MongoDB

Плагин mongodblog — встроен по умолчанию.

Синтаксис регистратора для ведения журнала MongoDB (mongodblog):

--logger mongodblog[:<host>,<collection>,<node>]

Где host — это адрес экземпляра MongoDB (по умолчанию 127.0.0.1:27017), имена коллекций collection, в которые записываются строки журнала (по умолчанию uwsgi.logs), а node — это идентификационная строка для экземпляра, отправляющего журналы (по умолчанию: имя хоста сервера).

--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:

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 logger»

Если вы размещаете свои приложения в облачных службах без постоянного хранилища, вы можете отправлять свои журналы во внешние системы. Однако журналы часто содержат конфиденциальную информацию, которую не следует передавать в открытом виде. Регистратор подключаемого модуля logcrypto пытается решить эту проблему, шифруя каждый пакет журнала перед отправкой его по UDP на сервер, способный расшифровать его. В следующем примере каждый пакет журнала будет отправлен на сервер UDP, доступный по адресу 192.168.173.22:1717, с шифрованием текста секретным ключом ciaociao с Blowfish в режиме CBC.

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 logger»

Плагин graylog2 — по умолчанию не скомпилирован.

Этот плагин будет отправлять журналы на сервер Graylog2 в родном для Graylog2 формате GELF.

uwsgi --plugin graylog2 --logger graylog2:127.0.0.1:1234,dsfargeg

Плагин «Systemd logger»

Плагин systemd_logger — по умолчанию не скомпилирован.

Этот плагин будет записывать записи журнала в журнал Systemd.

uwsgi --plugin systemd_logger --logger systemd

Написание собственных плагинов для логгеров

Этот плагин, foolog.c, будет записывать ваши сообщения в файл, указанный с помощью –logto/–daemonize, с простым префиксом, используя векторный ввод-вывод.

#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,
};

Информационные ссылки

Стандарт uWSGI — Раздел «Logging» — https://uwsgi-docs.readthedocs.io/en/latest/Logging.html

Задать вопрос

Nyppy

@Nyppy

django

  • Django

  • uWSGI

Подскажите, как в uwsgi просмотерть логи проекта ?


  • Вопрос задан

    более года назад

  • 247 просмотров


Комментировать

Подписаться

1



Простой

Комментировать


Решения вопроса 1

dimonchik2013

Dimonchik

@dimonchik2013

non progredi est regredi

все надо задавать явно

https://uwsgi-docs.readthedocs.io/en/latest/Loggin…
https://djbook.ru/rel1.9/topics/logging.html

из неявного только логи nginx и suoervisord (или что изспользуешь для демонизации), нередко их (error которые) достаточно для понимания что не работает

Ответ написан

более года назад


Комментировать


Комментировать

Пригласить эксперта


Ответы на вопрос 0


Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации


Похожие вопросы

  • django

    • Django




    Простой

    Создание программы планирования расписания с Django, что использовать для редактора расписания(сетки с занятиями)?


    • 1 подписчик
    • 10 часов назад


    • 36 просмотров

    1

    ответ

  • django

    • Django

    • +1 ещё




    Простой

    Почему не запускается сервер после подключения БД к docker?


    • 1 подписчик
    • 12 часов назад


    • 47 просмотров

    0

    ответов

  • html

    • HTML

    • +2 ещё




    Простой

    Transition почему то не работает в обратную сторону, почему?


    • 1 подписчик
    • 14 часов назад


    • 27 просмотров

    2

    ответа

  • django

    • Django




    Простой

    Как отобразить связанное поле в Django admin?


    • 1 подписчик
    • 18 часов назад


    • 34 просмотра

    1

    ответ

  • django

    • Django

    • +1 ещё




    Простой

    После подключения бд в Docker все данные стерлись, это нормально?


    • 1 подписчик
    • 21 час назад


    • 57 просмотров

    1

    ответ

  • django

    • Django




    Простой

    Как установить coockie или headers при Redirect?


    • 1 подписчик
    • вчера


    • 62 просмотра

    1

    ответ

  • django

    • Django




    Простой

    ModuleNotFoundError at /adminlogin/ No module named ‘main.apployment_site’ В чём ошибка?


    • 1 подписчик
    • вчера


    • 40 просмотров

    1

    ответ

  • django

    • Django




    Простой

    ImportError at / main doesn’t look like a module path как исправить?


    • 1 подписчик
    • вчера


    • 67 просмотров

    0

    ответов

  • django

    • Django

    • +1 ещё




    Средний

    Что делать если функция views не обрабатывает POST метод django?


    • 1 подписчик
    • вчера


    • 51 просмотр

    0

    ответов

  • html

    • HTML

    • +3 ещё




    Средний

    Почему Django не выводит картинку?


    • 1 подписчик
    • 07 февр.


    • 64 просмотра

    0

    ответов


  • Показать ещё
    Загружается…

Вакансии с Хабр Карьеры

Разработчик Django/Django Rest Framework

Кортекс

от 40 000 до 60 000 ₽

Web разработчик backend (Django)

BST Digital

от 60 000 ₽

Разработчик-Python (Django, DRF)

Fabrique

от 180 000 до 350 000 ₽

Ещё вакансии

Заказы с Хабр Фриланса

Требуется помощь в анализе текста отзывов покупателей

10 февр. 2023, в 04:49

50000 руб./за проект

Парсер/граббер постов Вконтакте по ключевым словам

10 февр. 2023, в 02:20

3000 руб./за проект

Объединить 200 разных файлов xls и csv в одну базу данных

10 февр. 2023, в 01:33

1500 руб./за проект

Ещё заказы

Минуточку внимания

Присоединяйтесь к сообществу, чтобы узнавать новое и делиться знаниями

Зарегистрироваться

Войдите на сайт

Чтобы задать вопрос и получить на него квалифицированный ответ.

Войти через центр авторизации

Tech Blog: JSON logging in uWSGI

By Ivan Borko on February 5, 2020


Velebit AI was recently preparing a new production environment from scratch, and one of the major tasks we had to solve was logging. Our team already had experience with ELK stack (ElasticSearch, Logstash, Kibana) to parse, store, and analyze logs. Starting without legacy gave us the opportunity to choose a new stack.

This blog post is a part of the Velebit AI Tech Blog series where we discuss good practices for a scalable and robust production deployment.

Formatting logs:

  • JSON logging in uWSGI
  • JSON logging in Python
  • How to configure JSON logging in nginx?

Collecting logs:

  • Collecting logs in docker clusters

Visualizing logs:

  • Connecting Elasticsearch logs to Grafana and Kibana

ELK Stack and Grafana

We searched for possible alternatives to ELK stack because the open-source version lacked some features we wanted. For example, both user management and alerting are available only as paid X-Pack plugins. We decided to use Grafana, a good alternative to Kibana with built-in support for user management and alerting.

The second issue we wanted to fix was the fact that Logstash log parsing consumes a lot of CPU. Our solution was: don’t parse logs! :) Configure all apps and services to output their logs as JSON. This way you can simply collect logs from docker containers using fluentbit and send them to ElasticSearch cluster.

JSON logging everywhere

Most of our services are Python APIs, so the first task was to switch all Python logs to JSON. We built a custom module that reconfigures Python logging to convert logging messages to JSON. Also, we use Nginx as a load balancer and it is the main source of quality logs used to:

  1. calculate different metrics such as average response times, throughput, etc
  2. enable detection of faulty services (status 500)

Nginx logging subsystem has support for JSON-escaping of variables and we used it to switch logging to our custom JSON format. This blog post is the first in a series of blog posts explaining how exactly we configured Python logging and Nginx logging to use JSON encoding.

uWSGI logging

The last thing to switch to JSON logging was uWSGI. We use it as a WSGI server that serves our Flask and Falcon REST APIs. As we already had a few years of experience working with uWSGI, we were aware of the vast amount of settings and options uWSGI has, and we were confident that JSON logging shouldn’t be a big deal since uWSGI has built-in support for JSON log encoder.

uWSGI has 3 sources of log messages:

  1. Application logs (python logs in our use case)
  2. uWSGI server logs (information about server startup, errors, warnings)
  3. Request logs

1. Application logs

Application logs are already JSON formatted, so uWSGI just has to pass it through. We define custom logger (applogger) and filter logs starting with the left curly bracket.

logger = applogger stdio
log-route = applogger {
log-encoder = format:applogger ${msg}

2. uWSGI server logs

uWSGI server logs are simple text messages by default. We use route regex to filter all logs that don’t start with curly braces (to differentiate them from application logs) They can be simply wrapped in JSON using built-it JSON log encoder.

logger = default stdio
log-route = default ^((?!{).)*$
log-encoder = json:default {"time":"${micros}", "source":"uwsgi", "message":"${msg}"}
log-encoder = nl

3. Request Logs

Built-in JSON log encoder supports only message (msg, msgnl) and time variables (unix, micros, strftime). Since we wanted additional information related to the request encoded in separate JSON fields we had to come up with a different solution for log formatting.

Default uWSGI request log format looks like this:

log-format = [pid: %(pid)|app: -|req: -/-] %(addr) (%(user)) {%(vars) vars in %(pktsize) bytes} [%(ctime)] %(method) %(uri) => generated %(rsize) bytes in %(msecs) msecs (%(proto) %(status)) %(headers) headers in %(hsize) bytes (%(switches) switches on core %(core))

uWSGI offers many variables with useful information that we would like to log. As mentioned before, JSON encoder allows only a small set of log variables. Here is an example of JSON logging encoder configuration:

log-encoder = json {"unix":${unix}, "msg":"${msg}", "date":"${strftime:%%d/%%m/%%Y %%H:%%M:%%S}"}

To overcome this limitation, we define log-format as a JSON-like text containing request related variables:

log-format = "address":"%(addr)", "host":"%(host)", "method":"%(method)", "uri":"%(uri)"

and wrap that text to a JSON using

log-req-encoder = format {"time":"${micros}", "source":"uwsgi-req", ${msg}}

The problem is that host and uri variables can contain characters that would mess-up JSON format.

We’ve found this issue referencing the same problem. Solution offered by the commenter was to write a uWSGI plugin that defined new JSON-escaped variables that can be used to define text of a request, but in a form a JSON.

uWSGI logging plugin

There is a really short example of a uWSGI logging plugin here . When the documentation for writing a plugin is only 3 blocks of text, one is unfortunately left with just a source code as the source of meaningful information.

Nevertheless, we decided to write uWSGI plugin that defines custom JSON-escaped variables json_uri and json_host. These variables can be used to configure JSON logging of requests.

Now you can use these new variables in log-format:

log-format = "address":"%(addr)", "host":"%(json_host)", "method":"%(method)", "uri":"%(json_uri)"

The resulting plugin is available in our repo.

Uwsgi plugin can be built using this command:

uwsgi --build-plugin <filename.c>

And you can use it with uwsgi server using command:

uwsgi --plugin <filename_plugin.so> …

Resulting uWSGI config file looks like this:

[uwsgi]
plugin = escape_json_plugin.so
; this will encode uwsgi messages into JSON, encode requests to JSON and leave application output unchanged
logger = default stdio
logger = applogger stdio
log-route = applogger {
log-route = default ^((?!{).)*$
log-encoder = json:default {"time":"${micros}", "source":"uwsgi", "message":"${msg}"}
log-encoder = format:applogger ${msg}
log-encoder = nl
logger-req = stdio
; json_uri and json_host are json-escaped fields defined in `escape_json_plugin.so`
log-format = "address":"%(addr)", "host":"%(json_host)", "method":"%(method)", "uri":"%(json_uri)", "protocol":"%(proto)", "resp_size":%(size), "req_body_size":%(cl), "resp_status":%(status), "resp_time":%(secs)"
log-req-encoder = format {"time":"${micros}", "source":"uwsgi-req", ${msg}}
log-req-encoder = nl

This way we managed to format all 3 types of logs coming out of uWSGI as JSON.

Follow Velebit AI on LinkedIn.


Recent blog posts

Tech Blog: JSON logging in uWSGI

How Disruptive Is ChatGPT And Why?

Open AI’s ChatGPT, Chat Generative Pre-trained Transformer, is an advanced chatbot currently getting a lot of public attention. Innovative methods behind it enabled unprecedented alignment with human intent and values. Let’s explore how ChatGPT, and even more so the principles behind it, will become disruptive for many.

Read more

Tech Blog: JSON logging in uWSGI

Tech Blog: How to configure JSON logging in nginx?

In previous posts from this series, we discussed how we formatted UWSGI and Python logs in JSON format. We still have one important production component left: the Nginx server. This blog post will describe how the Nginx logging module works, and showcase a simple logging configuration where Nginx logger is configured to output JSON logs.

Read more

Понравилась статья? Поделить с друзьями:
  • Uvscreencamera acmformatsuggest error
  • Uv overlap unity как исправить
  • Utweb ошибка при запуске приложения 0xc000007b
  • Utweb exe системная ошибка как исправить avcodec 58 dll
  • Utweb exe системная ошибка avformat 58 dll