Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Bartenev <vbart@nginx.com>2015-03-19 19:29:43 +0300
committerValentin Bartenev <vbart@nginx.com>2015-03-19 19:29:43 +0300
commitcc569b92528373694ae3ebc3649b35c9fb6ba540 (patch)
treed7c730171a8f7b2c65328d6e835968192131906b /src/core/ngx_log.c
parentbabd64e344331ec4751dcb191eb4e847e3b36a4a (diff)
Core: added cyclic memory buffer support for error_log.
Example of usage: error_log memory:16m debug; This allows to configure debug logging with minimum impact on performance. It's especially useful when rare crashes are experienced under high load. The log can be extracted from a coredump using the following gdb script: set $log = ngx_cycle->log while $log->writer != ngx_log_memory_writer set $log = $log->next end set $buf = (ngx_log_memory_buf_t *) $log->wdata dump binary memory debug_log.txt $buf->start $buf->end
Diffstat (limited to 'src/core/ngx_log.c')
-rw-r--r--src/core/ngx_log.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index bfda8eea3..bf0050885 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -14,6 +14,23 @@ static char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
static void ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log);
+#if (NGX_DEBUG)
+
+static void ngx_log_memory_writer(ngx_log_t *log, ngx_uint_t level,
+ u_char *buf, size_t len);
+static void ngx_log_memory_cleanup(void *data);
+
+
+typedef struct {
+ u_char *start;
+ u_char *end;
+ u_char *pos;
+ ngx_atomic_t written;
+} ngx_log_memory_buf_t;
+
+#endif
+
+
static ngx_command_t ngx_errlog_commands[] = {
{ngx_string("error_log"),
@@ -568,6 +585,64 @@ ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head)
return NGX_CONF_ERROR;
}
+ } else if (ngx_strncmp(value[1].data, "memory:", 7) == 0) {
+
+#if (NGX_DEBUG)
+ size_t size, needed;
+ ngx_pool_cleanup_t *cln;
+ ngx_log_memory_buf_t *buf;
+
+ value[1].len -= 7;
+ value[1].data += 7;
+
+ needed = sizeof("MEMLOG :" NGX_LINEFEED)
+ + cf->conf_file->file.name.len
+ + NGX_SIZE_T_LEN
+ + NGX_INT_T_LEN
+ + NGX_MAX_ERROR_STR;
+
+ size = ngx_parse_size(&value[1]);
+
+ if (size == (size_t) NGX_ERROR || size < needed) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid buffer size \"%V\"", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
+ buf = ngx_palloc(cf->pool, sizeof(ngx_log_memory_buf_t));
+ if (buf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ buf->start = ngx_pnalloc(cf->pool, size);
+ if (buf->start == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ buf->end = buf->start + size;
+
+ buf->pos = ngx_slprintf(buf->start, buf->end, "MEMLOG %uz %V:%ui%N",
+ size, &cf->conf_file->file.name,
+ cf->conf_file->line);
+
+ ngx_memset(buf->pos, ' ', buf->end - buf->pos);
+
+ cln = ngx_pool_cleanup_add(cf->pool, 0);
+ if (cln == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ cln->data = new_log;
+ cln->handler = ngx_log_memory_cleanup;
+
+ new_log->writer = ngx_log_memory_writer;
+ new_log->wdata = buf;
+
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "nginx was built without debug support");
+ return NGX_CONF_ERROR;
+#endif
} else if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) {
peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t));
@@ -633,3 +708,48 @@ ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log)
log->next = new_log;
}
+
+
+#if (NGX_DEBUG)
+
+static void
+ngx_log_memory_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
+ size_t len)
+{
+ u_char *p;
+ size_t avail, written;
+ ngx_log_memory_buf_t *mem;
+
+ mem = log->wdata;
+
+ if (mem == NULL) {
+ return;
+ }
+
+ written = ngx_atomic_fetch_add(&mem->written, len);
+
+ p = mem->pos + written % (mem->end - mem->pos);
+
+ avail = mem->end - p;
+
+ if (avail >= len) {
+ ngx_memcpy(p, buf, len);
+
+ } else {
+ ngx_memcpy(p, buf, avail);
+ ngx_memcpy(mem->pos, buf + avail, len - avail);
+ }
+}
+
+
+static void
+ngx_log_memory_cleanup(void *data)
+{
+ ngx_log_t *log = data;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "destroy memory log buffer");
+
+ log->wdata = NULL;
+}
+
+#endif