uWSGI has a --logformat option for building custom request loglines. The
syntax is simple:
[uwsgi]
logformat = i am a logline reporting "%(method) %(uri) %(proto)" returning with status %(status)All of the variables marked with %() are substituted using specific rules.
Three kinds of logvars are defined ("offsetof", functions, and user-defined).
These are taken blindly from the internal wsgi_request structure of the current request.
%(uri)-> REQUEST_URI%(method)-> REQUEST_METHOD%(user)-> REMOTE_USER%(addr)-> REMOTE_ADDR%(host)-> HTTP_HOST%(proto)-> SERVER_PROTOCOL%(uagent)-> HTTP_USER_AGENT (starting from 1.4.5)%(referer)-> HTTP_REFERER (starting from 1.4.5)
These are simple functions called for generating the logvar value:
%(status)-> HTTP response status code%(micros)-> response time in microseconds%(msecs)-> response time in milliseconds%(time)-> timestamp of the start of the request%(ctime)-> ctime of the start of the request%(epoch)-> the current time in Unix format%(size)-> response body size + response headers size (since 1.4.5)%(ltime) -> human-formatted (Apache style)request time (since 1.4.5)%(hsize)-> response headers size (since 1.4.5)%(rsize)-> response body size (since 1.4.5)%(cl)-> request content body size (since 1.4.5)%(pid)-> pid of the worker handling the request (since 1.4.6)%(wid)-> id of the worker handling the request (since 1.4.6)%(switches)-> number of async switches (since 1.4.6)%(vars)-> number of CGI vars in the request (since 1.4.6)%(headers)-> number of generated response headers (since 1.4.6)%(core)-> the core running the request (since 1.4.6)%(vsz)-> address space/virtual memory usage (in bytes) (since 1.4.6)%(rss)-> RSS memory usage (in bytes) (since 1.4.6)%(vszM)-> address space/virtual memory usage (in megabytes) (since 1.4.6)%(rssM)-> RSS memory usage (in megabytes) (since 1.4.6)%(pktsize)-> size of the internal request uwsgi packet (since 1.4.6)%(modifier1)-> modifier1 of the request (since 1.4.6)%(modifier2)-> modifier2 of the request (since 1.4.6)%(metric.XXX)-> access the XXX metric value (see :doc:`Metrics`)%(rerr)-> number of read errors for the request (since 1.9.21)%(werr)-> number of write errors for the request (since 1.9.21)%(ioerr)-> number of write and read errors for the request (since 1.9.21)%(tmsecs)-> timestamp of the start of the request in milliseconds since the epoch (since 1.9.21)%(tmicros)-> timestamp of the start of the request in microseconds since the epoch (since 1.9.21)%(var.XXX)-> the content of request variable XXX (like var.PATH_INFO, available from 1.9.21)
You can define logvars within your request handler. These variables live only per-request.
import uwsgi
def application(env, start_response):
uwsgi.set_logvar('foo', 'bar')
# returns 'bar'
print uwsgi.get_logvar('foo')
uwsgi.set_logvar('worker_id', str(uwsgi.worker_id()))
...With the following log format you will be able to access code-defined logvars:
uwsgi --logformat 'worker id = %(worker_id) for request "%(method) %(uri) %(proto)" test = %(foo)'To generate Apache-compatible logs:
[uwsgi]
...
log-format = %(addr) - %(user) [%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size) "%(referer)" "%(uagent)"
...(Updated to 1.9.21)
You can register new "logchunk" (the function to call for each logformat symbol) with
struct uwsgi_logchunk *uwsgi_register_logchunk(char *name, ssize_t (*func)(struct wsgi_request *, char **), int need_free);name is the name of the symbol
need_free if 1, means the pointer set by func must be free()d;
func the function to call in the log handler
static ssize_t uwsgi_lf_foobar(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->status);
return strlen(*buf);
}
static void register_logchunks() {
uwsgi_register_logchunk("foobar", uwsgi_lf_foobar, 1);
}
struct uwsgi_plugin foobar_plugin = {
.name = "foobar",
.on_load = register_logchunks,
};if you load the foobar plugin, you will be able to use the %(foobar) request logging variable (reporting the request status)