]> git.saurik.com Git - redis.git/commitdiff
syslog support
authorJonah H. Harris <jonah.harris@gmail.com>
Thu, 9 Dec 2010 16:10:21 +0000 (11:10 -0500)
committerJonah H. Harris <jonah.harris@gmail.com>
Thu, 9 Dec 2010 16:10:21 +0000 (11:10 -0500)
redis.conf
src/config.c
src/redis.c
src/redis.h

index 5ec2d0295dd373c957a5c862782d9a4d2d0bb3cb..05374ed7ea3adb482298edb65b7ef0bbe81b0577 100644 (file)
@@ -50,6 +50,16 @@ loglevel verbose
 # output for logging but daemonize, logs will be sent to /dev/null
 logfile stdout
 
+# To enable logging to the system logger, just set 'syslog-enabled' to yes,
+# and optionally update the other syslog parameters to suit your needs.
+# syslog-enabled no
+
+# Specify the syslog identity.
+# syslog-ident redis
+
+# Specify the syslog facility.  Must be USER or between LOCAL0-LOCAL7.
+# syslog-facility local0
+
 # Set the number of databases. The default database is DB 0, you can select
 # a different one on a per-connection basis using SELECT <dbid> where
 # dbid is a number between 0 and 'databases'-1
index ad60cced36affb06772c45b07cdfe781af66d262..a45acdb733cd6648565676a887fec57078fa1a1c 100644 (file)
@@ -114,6 +114,46 @@ void loadServerConfig(char *filename) {
                 }
                 fclose(logfp);
             }
+        } else if (!strcasecmp(argv[0],"syslog-enabled") && argc == 2) {
+            if ((server.syslog_enabled = yesnotoi(argv[1])) == -1) {
+                err = "argument must be 'yes' or 'no'"; goto loaderr;
+            }
+        } else if (!strcasecmp(argv[0],"syslog-ident") && argc == 2) {
+            if (server.syslog_ident) zfree(server.syslog_ident);
+            server.syslog_ident = zstrdup(argv[1]);
+        } else if (!strcasecmp(argv[0],"syslog-facility") && argc == 2) {
+            struct {
+                const char     *name;
+                const int       value;
+            } validSyslogFacilities[] = {
+                {"user",    LOG_USER},
+                {"local0",  LOG_LOCAL0},
+                {"local1",  LOG_LOCAL1},
+                {"local2",  LOG_LOCAL2},
+                {"local3",  LOG_LOCAL3},
+                {"local4",  LOG_LOCAL4},
+                {"local5",  LOG_LOCAL5},
+                {"local6",  LOG_LOCAL6},
+                {"local7",  LOG_LOCAL7},
+                {NULL, 0}
+            };
+            int i;
+
+            for (i = 0; validSyslogFacilities[i].name; i++) {
+                if (!strcasecmp(validSyslogFacilities[i].name, argv[1])) {
+                    server.syslog_facility = validSyslogFacilities[i].value;
+                    break;
+                }
+            }
+
+            if (!validSyslogFacilities[i].name) {
+                err = "Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7";
+                goto loaderr;
+            }
+        } else if (!strcasecmp(argv[0],"syslog-ident") && argc == 2) {
+            
+
+            server.syslog_ident = zstrdup(argv[1]);
         } else if (!strcasecmp(argv[0],"databases") && argc == 2) {
             server.dbnum = atoi(argv[1]);
             if (server.dbnum < 1) {
index 5b39c011f537e5e4e6845e483c3b4b90449e1bc1..14923bc88983e11b463cf128e2f97eecd45fbb68 100644 (file)
@@ -188,11 +188,13 @@ struct redisCommand readonlyCommandTable[] = {
 /*============================ Utility functions ============================ */
 
 void redisLog(int level, const char *fmt, ...) {
+    const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };
+    const char *c = ".-*#";
+    time_t now = time(NULL);
     va_list ap;
     FILE *fp;
-    char *c = ".-*#";
     char buf[64];
-    time_t now;
+    char msg[REDIS_MAX_LOGMSG_LEN];
 
     if (level < server.verbosity) return;
 
@@ -200,15 +202,16 @@ void redisLog(int level, const char *fmt, ...) {
     if (!fp) return;
 
     va_start(ap, fmt);
-    now = time(NULL);
-    strftime(buf,64,"%d %b %H:%M:%S",localtime(&now));
-    fprintf(fp,"[%d] %s %c ",(int)getpid(),buf,c[level]);
-    vfprintf(fp, fmt, ap);
-    fprintf(fp,"\n");
-    fflush(fp);
+    vsnprintf(msg, sizeof(msg), fmt, ap);
     va_end(ap);
 
+    strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now));
+    fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
+    fflush(fp);
+
     if (server.logfile) fclose(fp);
+
+    if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
 }
 
 /* Redis generally does not try to recover from out of memory conditions
@@ -743,6 +746,9 @@ void initServerConfig() {
     server.saveparams = NULL;
     server.loading = 0;
     server.logfile = NULL; /* NULL = log on standard output */
+    server.syslog_enabled = 0;
+    server.syslog_ident = zstrdup("redis");
+    server.syslog_facility = LOG_LOCAL0;
     server.glueoutputbuf = 1;
     server.daemonize = 0;
     server.appendonly = 0;
@@ -813,6 +819,11 @@ void initServer() {
     signal(SIGPIPE, SIG_IGN);
     setupSigSegvAction();
 
+    if (server.syslog_enabled) {
+        openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,
+            server.syslog_facility);
+    }
+
     server.mainthread = pthread_self();
     server.clients = listCreate();
     server.slaves = listCreate();
index e5db917e44ef1219947b4497139bd3eadb25258c..cecf01811bfd37f06eaf8e8373429affa5bed0ba 100644 (file)
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <pthread.h>
+#include <syslog.h>
 
 #include "ae.h"     /* Event driven programming library */
 #include "sds.h"    /* Dynamic safe strings */
@@ -47,6 +48,7 @@
 #define REDIS_REQUEST_MAX_SIZE (1024*1024*256) /* max bytes in inline command */
 #define REDIS_SHARED_INTEGERS 10000
 #define REDIS_REPLY_CHUNK_BYTES (5*1500) /* 5 TCP packets with default MTU */
+#define REDIS_MAX_LOGMSG_LEN    1024 /* Default maximum length of syslog messages */
 
 /* If more then REDIS_WRITEV_THRESHOLD write packets are pending use writev */
 #define REDIS_WRITEV_THRESHOLD      3
@@ -402,6 +404,9 @@ struct redisServer {
     struct saveparam *saveparams;
     int saveparamslen;
     char *logfile;
+    int syslog_enabled;
+    char *syslog_ident;
+    int syslog_facility;
     char *dbfilename;
     char *appendfilename;
     char *requirepass;