Add stderr log support in mod_fastcgi (split lines from backend in log.c)
This commit is contained in:
parent
159a03f19b
commit
5c797977c6
|
@ -34,7 +34,9 @@ LI_API const char *remove_path(const char *path);
|
|||
#define _DEBUG(srv, vr, fmt, ...) \
|
||||
log_write_(srv, vr, LOG_LEVEL_INFO, LOG_FLAG_TIMESTAMP, "(debug) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
|
||||
#define _BACKEND(srv, vr, fmt, ...) \
|
||||
log_write_(srv, vr, LOG_LEVEL_BACKEND, LOG_FLAG_TIMESTAMP)
|
||||
log_write_(srv, vr, LOG_LEVEL_BACKEND, LOG_FLAG_TIMESTAMP, "(backend) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
|
||||
#define _BACKEND_LINES(srv, vr, txt, fmt, ...) \
|
||||
log_split_lines_(srv, vr, LOG_LEVEL_BACKEND, LOG_FLAG_TIMESTAMP, txt, "(backend) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
|
||||
|
||||
|
||||
#define VR_SEGFAULT(vr, fmt, ...) _SEGFAULT(vr->con->srv, vr, fmt, __VA_ARGS__)
|
||||
|
@ -42,21 +44,20 @@ LI_API const char *remove_path(const char *path);
|
|||
#define VR_WARNING(vr, fmt, ...) _WARNING(vr->con->srv, vr, fmt, __VA_ARGS__)
|
||||
#define VR_INFO(vr, fmt, ...) _INFO(vr->con->srv, vr, fmt, __VA_ARGS__)
|
||||
#define VR_DEBUG(vr, fmt, ...) _DEBUG(vr->con->srv, vr, fmt, __VA_ARGS__)
|
||||
#define VR_BACKEND(vr, fmt, ...) _BACKEND(vr->con->srv, vr, fmt, __VA_ARGS__)
|
||||
#define VR_BACKEND(vr, fmt, ...) _BACKEND(vr->con->srv, vr, fmt, __VA_ARGS__)
|
||||
#define VR_BACKEND_LINES(vr, txt, fmt, ...) _BACKEND_LINES(vr->con->srv, vr, txt, fmt, __VA_ARGS__)
|
||||
|
||||
#define SEGFAULT(srv, fmt, ...) _SEGFAULT(srv, NULL, fmt, __VA_ARGS__)
|
||||
#define ERROR(srv, fmt, ...) _ERROR(srv, NULL, fmt, __VA_ARGS__)
|
||||
#define WARNING(srv, fmt, ...) _WARNING(srv, NULL, fmt, __VA_ARGS__)
|
||||
#define INFO(srv, fmt, ...) _INFO(srv, NULL, fmt, __VA_ARGS__)
|
||||
#define DEBUG(srv, fmt, ...) _DEBUG(srv, NULL, fmt, __VA_ARGS__)
|
||||
#define BACKEND(srv, fmt, ...) _BACKEND(srv, NULL, fmt, __VA_ARGS__)
|
||||
#define BACKEND(srv, fmt, ...) _BACKEND(srv, NULL, fmt, __VA_ARGS__)
|
||||
|
||||
|
||||
/* TODO: perhaps make portable (detect if cc supports) */
|
||||
#define __ATTRIBUTE_PRINTF_FORMAT(fmt, arg) __attribute__ ((__format__ (__printf__, fmt, arg)))
|
||||
|
||||
/*LI_API int log_write(server *srv, connection *con, const char *fmt, ...) __ATTRIBUTE_PRINTF_FORMAT(3, 4);*/
|
||||
|
||||
|
||||
struct log_t;
|
||||
typedef struct log_t log_t;
|
||||
|
@ -152,7 +153,12 @@ LI_API void log_write(server *srv, log_t *log, GString *msg);
|
|||
/* log_write_ is used to write to the errorlog */
|
||||
LI_API gboolean log_write_(server *srv, vrequest *vr, log_level_t log_level, guint flags, const gchar *fmt, ...) __ATTRIBUTE_PRINTF_FORMAT(5, 6);
|
||||
|
||||
log_timestamp_t *log_timestamp_new(server *srv, GString *format);
|
||||
gboolean log_timestamp_free(server *srv, log_timestamp_t *ts);
|
||||
LI_API log_timestamp_t *log_timestamp_new(server *srv, GString *format);
|
||||
LI_API gboolean log_timestamp_free(server *srv, log_timestamp_t *ts);
|
||||
|
||||
/* replaces '\r' and '\n' with '\0' */
|
||||
LI_API void log_split_lines(server *srv, vrequest *vr, log_level_t log_level, guint flags, gchar *txt, const gchar *prefix);
|
||||
LI_API void log_split_lines_(server *srv, vrequest *vr, log_level_t log_level, guint flags, gchar *txt, const gchar *fmt, ...) __ATTRIBUTE_PRINTF_FORMAT(6, 7);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
36
src/log.c
36
src/log.c
|
@ -535,3 +535,39 @@ gboolean log_timestamp_free(server *srv, log_timestamp_t *ts) {
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void log_split_lines(server *srv, vrequest *vr, log_level_t log_level, guint flags, gchar *txt, const gchar *prefix) {
|
||||
gchar *start;
|
||||
|
||||
start = txt;
|
||||
while ('\0' != *txt) {
|
||||
if ('\r' == *txt || '\n' == *txt) {
|
||||
*txt = '\0';
|
||||
if (txt - start > 1) { /* skip empty lines*/
|
||||
log_write_(srv, vr, log_level, flags, "%s%s", prefix, start);
|
||||
}
|
||||
txt++;
|
||||
while (*txt == '\n' || *txt == '\r') txt++;
|
||||
start = txt;
|
||||
} else {
|
||||
txt++;
|
||||
}
|
||||
}
|
||||
if (txt - start > 1) { /* skip empty lines*/
|
||||
log_write_(srv, vr, log_level, flags, "%s%s", prefix, start);
|
||||
}
|
||||
}
|
||||
|
||||
void log_split_lines_(server *srv, vrequest *vr, log_level_t log_level, guint flags, gchar *txt, const gchar *fmt, ...) {
|
||||
va_list ap;
|
||||
GString *prefix;
|
||||
|
||||
prefix = g_string_sized_new(0);
|
||||
va_start(ap, fmt);
|
||||
g_string_vprintf(prefix, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log_split_lines(srv, vr, log_level, flags, txt, prefix->str);
|
||||
|
||||
g_string_free(prefix, TRUE);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,42 @@
|
|||
/*
|
||||
* mod_fastcgi - connect to fastcgi backends for generating content
|
||||
*
|
||||
* Description:
|
||||
* mod_fastcgi connects to a backend over tcp oder unix sockets
|
||||
*
|
||||
* Setups:
|
||||
* none
|
||||
* Options:
|
||||
* fastcgi.log_plain_errors <value> - whether to prepend timestamp and other info to
|
||||
* fastcgi stderr lines in the "backend" log.
|
||||
* type: boolean
|
||||
* Actions:
|
||||
* fastcgi <socket> - connect to backend at <socket>
|
||||
* socket: string, either "ip:port" or "unix:/path"
|
||||
*
|
||||
* Example config:
|
||||
* fastcgi "127.0.0.1:9090"
|
||||
*
|
||||
* Todo:
|
||||
* - reuse fastcgi connections (keepalive)
|
||||
* - send more infos to backend (http headers, auth info)
|
||||
* - option for alternative doc-root?
|
||||
*
|
||||
* Author:
|
||||
* Copyright (c) 2009 Stefan Bühler
|
||||
*/
|
||||
|
||||
#include <lighttpd/base.h>
|
||||
#include <lighttpd/plugin_core.h>
|
||||
|
||||
enum fastcgi_options_t {
|
||||
FASTCGI_OPTION_LOG_PLAIN_ERRORS = 0,
|
||||
};
|
||||
|
||||
#define FASTCGI_OPTION(idx) _FASTCGI_OPTION(vr, idx)
|
||||
#define _FASTCGI_OPTION(vr, idx) _OPTION_ABS(vr, p->opt_base_index + idx)
|
||||
|
||||
|
||||
LI_API gboolean mod_fastcgi_init(modules *mods, module *mod);
|
||||
LI_API gboolean mod_fastcgi_free(modules *mods, module *mod);
|
||||
|
||||
|
@ -401,12 +436,14 @@ static gboolean fastcgi_get_packet(fastcgi_connection *fcon) {
|
|||
}
|
||||
|
||||
static gboolean fastcgi_parse_response(fastcgi_connection *fcon) {
|
||||
vrequest *vr = fcon->vr;
|
||||
plugin *p = fcon->ctx->plugin;
|
||||
while (fastcgi_get_packet(fcon)) {
|
||||
if (fcon->fcgi_in_record.version != FCGI_VERSION_1) {
|
||||
VR_ERROR(fcon->vr, "Unknown fastcgi protocol version %i", (gint) fcon->fcgi_in_record.version);
|
||||
VR_ERROR(vr, "Unknown fastcgi protocol version %i", (gint) fcon->fcgi_in_record.version);
|
||||
close(fcon->fd);
|
||||
fcon->fd = -1;
|
||||
vrequest_error(fcon->vr);
|
||||
vrequest_error(vr);
|
||||
return FALSE;
|
||||
}
|
||||
chunkqueue_skip(fcon->fcgi_in, FCGI_HEADER_LEN);
|
||||
|
@ -422,8 +459,17 @@ static gboolean fastcgi_parse_response(fastcgi_connection *fcon) {
|
|||
chunkqueue_steal_len(fcon->stdout, fcon->fcgi_in, fcon->fcgi_in_record.contentLength);
|
||||
}
|
||||
break;
|
||||
case FCGI_STDERR:
|
||||
chunkqueue_extract_to(vr, fcon->fcgi_in, fcon->fcgi_in_record.contentLength, vr->con->wrk->tmp_str);
|
||||
if (FASTCGI_OPTION(FASTCGI_OPTION_LOG_PLAIN_ERRORS).boolean) {
|
||||
log_split_lines(vr->con->srv, vr, LOG_LEVEL_BACKEND, 0, vr->con->wrk->tmp_str->str, "");
|
||||
} else {
|
||||
VR_BACKEND_LINES(vr, vr->con->wrk->tmp_str->str, "%s", "(fcgi-stderr) ");
|
||||
}
|
||||
chunkqueue_skip(fcon->fcgi_in, fcon->fcgi_in_record.contentLength);
|
||||
break;
|
||||
default:
|
||||
VR_WARNING(fcon->vr, "Unhandled fastcgi record type %i", (gint) fcon->fcgi_in_record.type);
|
||||
VR_WARNING(vr, "Unhandled fastcgi record type %i", (gint) fcon->fcgi_in_record.type);
|
||||
chunkqueue_skip(fcon->fcgi_in, fcon->fcgi_in_record.contentLength);
|
||||
break;
|
||||
}
|
||||
|
@ -645,6 +691,8 @@ static action* fastcgi_create(server *srv, plugin* p, value *val) {
|
|||
}
|
||||
|
||||
static const plugin_option options[] = {
|
||||
{ "fastcgi.log_plain_errors", VALUE_BOOLEAN, GINT_TO_POINTER(FALSE), NULL, NULL },
|
||||
|
||||
{ NULL, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -941,7 +941,7 @@ static action* core_physical_is_dir(server *srv, plugin* p, value *val) {
|
|||
}
|
||||
|
||||
static const plugin_option options[] = {
|
||||
{ "debug.log_request_handling", VALUE_BOOLEAN, NULL, NULL, NULL },
|
||||
{ "debug.log_request_handling", VALUE_BOOLEAN, GINT_TO_POINTER(FALSE), NULL, NULL },
|
||||
|
||||
{ "log.timestamp", VALUE_STRING, NULL, core_option_log_timestamp_parse, core_option_log_timestamp_free },
|
||||
{ "log", VALUE_HASH, NULL, core_option_log_parse, core_option_log_free },
|
||||
|
|
Loading…
Reference in New Issue