]> granicus.if.org Git - php/commitdiff
- FR #52052: Added partial syslog support (on error_log only)
authorJérôme Loyet <fat@php.net>
Tue, 5 Jul 2011 19:22:45 +0000 (19:22 +0000)
committerJérôme Loyet <fat@php.net>
Tue, 5 Jul 2011 19:22:45 +0000 (19:22 +0000)
sapi/fpm/fpm/fpm_conf.c
sapi/fpm/fpm/fpm_conf.h
sapi/fpm/fpm/fpm_stdio.c
sapi/fpm/fpm/zlog.c
sapi/fpm/fpm/zlog.h
sapi/fpm/php-fpm.conf.in

index 6a37ae27f4f219df522eb5d31a95fcc0b9dc8213..a7ad4d255116906ac7030ce27dd67e49e3fc892c 100644 (file)
@@ -31,6 +31,7 @@
 #include "zend_ini_scanner.h"
 #include "zend_globals.h"
 #include "zend_stream.h"
+#include "php_syslog.h"
 
 #include "fpm.h"
 #include "fpm_conf.h"
@@ -58,8 +59,16 @@ static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset);
 static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset);
 static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset);
 static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset);
+#ifdef HAVE_SYSLOG_H
+static char *fpm_conf_set_syslog_facility(zval *value, void **config, intptr_t offset);
+#endif
 
-struct fpm_global_config_s fpm_global_config = { .daemonize = 1 };
+struct fpm_global_config_s fpm_global_config = {
+       .daemonize = 1,
+#ifdef HAVE_SYSLOG_H
+       .syslog_facility = -1
+#endif
+};
 static struct fpm_worker_pool_s *current_wp = NULL;
 static int ini_recursion = 0;
 static char *ini_filename = NULL;
@@ -67,15 +76,19 @@ static int ini_lineno = 0;
 static char *ini_include = NULL;
 
 static struct ini_value_parser_s ini_fpm_global_options[] = {
-       { "emergency_restart_threshold", &fpm_conf_set_integer,     GO(emergency_restart_threshold) },
-       { "emergency_restart_interval",  &fpm_conf_set_time,        GO(emergency_restart_interval) },
-       { "process_control_timeout",     &fpm_conf_set_time,        GO(process_control_timeout) },
-       { "daemonize",                   &fpm_conf_set_boolean,     GO(daemonize) },
-       { "pid",                         &fpm_conf_set_string,      GO(pid_file) },
-       { "error_log",                   &fpm_conf_set_string,      GO(error_log) },
-       { "log_level",                   &fpm_conf_set_log_level,   0 },
-       { "rlimit_files",                &fpm_conf_set_integer,     GO(rlimit_files) },
-       { "rlimit_core",                 &fpm_conf_set_rlimit_core, GO(rlimit_core) },
+       { "emergency_restart_threshold", &fpm_conf_set_integer,         GO(emergency_restart_threshold) },
+       { "emergency_restart_interval",  &fpm_conf_set_time,            GO(emergency_restart_interval) },
+       { "process_control_timeout",     &fpm_conf_set_time,            GO(process_control_timeout) },
+       { "daemonize",                   &fpm_conf_set_boolean,         GO(daemonize) },
+       { "pid",                         &fpm_conf_set_string,          GO(pid_file) },
+       { "error_log",                   &fpm_conf_set_string,          GO(error_log) },
+       { "log_level",                   &fpm_conf_set_log_level,       GO(log_level) },
+#ifdef HAVE_SYSLOG_H
+       { "syslog.ident",                &fpm_conf_set_string,          GO(syslog_ident) },
+       { "syslog.facility",             &fpm_conf_set_syslog_facility, GO(syslog_facility) },
+#endif
+       { "rlimit_files",                &fpm_conf_set_integer,         GO(rlimit_files) },
+       { "rlimit_core",                 &fpm_conf_set_rlimit_core,     GO(rlimit_core) },
        { 0, 0, 0 }
 };
 
@@ -252,25 +265,178 @@ static char *fpm_conf_set_time(zval *value, void **config, intptr_t offset) /* {
 static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset) /* {{{ */
 {
        char *val = Z_STRVAL_P(value);
+       int log_level;
 
        if (!strcasecmp(val, "debug")) {
-               fpm_globals.log_level = ZLOG_DEBUG;
+               log_level = ZLOG_DEBUG;
        } else if (!strcasecmp(val, "notice")) {
-               fpm_globals.log_level = ZLOG_NOTICE;
+               log_level = ZLOG_NOTICE;
        } else if (!strcasecmp(val, "warning") || !strcasecmp(val, "warn")) {
-               fpm_globals.log_level = ZLOG_WARNING;
+               log_level = ZLOG_WARNING;
        } else if (!strcasecmp(val, "error")) {
-               fpm_globals.log_level = ZLOG_ERROR;
+               log_level = ZLOG_ERROR;
        } else if (!strcasecmp(val, "alert")) {
-               fpm_globals.log_level = ZLOG_ALERT;
+               log_level = ZLOG_ALERT;
        } else {
                return "invalid value for 'log_level'";
        }
 
+       * (int *) ((char *) *config + offset) = log_level;
        return NULL;
 }
 /* }}} */
 
+#ifdef HAVE_SYSLOG_H
+static char *fpm_conf_set_syslog_facility(zval *value, void **config, intptr_t offset) /* {{{ */
+{
+       char *val = Z_STRVAL_P(value);
+       int *conf = (int *) ((char *) *config + offset);
+
+#ifdef LOG_AUTH
+       if (!strcasecmp(val, "AUTH")) {
+               *conf = LOG_AUTH;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_AUTHPRIV
+       if (!strcasecmp(val, "AUTHPRIV")) {
+               *conf = LOG_AUTHPRIV;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_CRON
+       if (!strcasecmp(val, "CRON")) {
+               *conf = LOG_CRON;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_DAEMON
+       if (!strcasecmp(val, "DAEMON")) {
+               *conf = LOG_DAEMON;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_FTP
+       if (!strcasecmp(val, "FTP")) {
+               *conf = LOG_FTP;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_KERN
+       if (!strcasecmp(val, "KERN")) {
+               *conf = LOG_KERN;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LPR
+       if (!strcasecmp(val, "LPR")) {
+               *conf = LOG_LPR;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_MAIL
+       if (!strcasecmp(val, "MAIL")) {
+               *conf = LOG_MAIL;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_NEWS
+       if (!strcasecmp(val, "NEWS")) {
+               *conf = LOG_NEWS;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_SYSLOG
+       if (!strcasecmp(val, "SYSLOG")) {
+               *conf = LOG_SYSLOG;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_USER
+       if (!strcasecmp(val, "USER")) {
+               *conf = LOG_USER;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_UUCP
+       if (!strcasecmp(val, "UUCP")) {
+               *conf = LOG_UUCP;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL0
+       if (!strcasecmp(val, "LOCAL0")) {
+               *conf = LOG_LOCAL0;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL1
+       if (!strcasecmp(val, "LOCAL1")) {
+               *conf = LOG_LOCAL1;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL2
+       if (!strcasecmp(val, "LOCAL2")) {
+               *conf = LOG_LOCAL2;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL3
+       if (!strcasecmp(val, "LOCAL3")) {
+               *conf = LOG_LOCAL3;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL4
+       if (!strcasecmp(val, "LOCAL4")) {
+               *conf = LOG_LOCAL4;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL5
+       if (!strcasecmp(val, "LOCAL5")) {
+               *conf = LOG_LOCAL5;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL6
+       if (!strcasecmp(val, "LOCAL6")) {
+               *conf = LOG_LOCAL6;
+               return NULL;
+       }
+#endif
+
+#ifdef LOG_LOCAL7
+       if (!strcasecmp(val, "LOCAL7")) {
+               *conf = LOG_LOCAL7;
+               return NULL;
+       }
+#endif
+
+       return "invalid value";
+}
+/* }}} */
+#endif
+
 static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset) /* {{{ */
 {
        char *val = Z_STRVAL_P(value);
@@ -794,11 +960,26 @@ static int fpm_conf_post_process(TSRMLS_D) /* {{{ */
                fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0);
        }
 
+       fpm_globals.log_level = fpm_global_config.log_level;
+
        if (!fpm_global_config.error_log) {
                fpm_global_config.error_log = strdup("log/php-fpm.log");
        }
 
-       fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0);
+#ifdef HAVE_SYSLOG_H
+       if (!fpm_global_config.syslog_ident) {
+               fpm_global_config.syslog_ident = strdup("php-fpm");
+       }
+
+       if (fpm_global_config.syslog_facility < 0) {
+               fpm_global_config.syslog_facility = LOG_DAEMON;
+       }
+
+       if (strcasecmp(fpm_global_config.error_log, "syslog") != 0)
+#endif
+       {
+               fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0);
+       }
 
        if (0 > fpm_stdio_open_error_log(0)) {
                return -1;
@@ -832,6 +1013,10 @@ static void fpm_conf_cleanup(int which, void *arg) /* {{{ */
        free(fpm_global_config.error_log);
        fpm_global_config.pid_file = 0;
        fpm_global_config.error_log = 0;
+#ifdef HAVE_SYSLOG_H
+       free(fpm_global_config.syslog_ident);
+       fpm_global_config.syslog_ident = 0;
+#endif
        free(fpm_globals.config);
 }
 /* }}} */
@@ -1152,6 +1337,10 @@ static void fpm_conf_dump() /* {{{ */
        zlog(ZLOG_NOTICE, "\tdaemonize = %s",                   BOOL2STR(fpm_global_config.daemonize));
        zlog(ZLOG_NOTICE, "\terror_log = %s",                   STR2STR(fpm_global_config.error_log));
        zlog(ZLOG_NOTICE, "\tlog_level = %s",                   zlog_get_level_name(fpm_globals.log_level));
+#ifdef HAVE_SYSLOG_H
+       zlog(ZLOG_NOTICE, "\tsyslog.ident = %s",                STR2STR(fpm_global_config.syslog_ident));
+       zlog(ZLOG_NOTICE, "\tsyslog.facility = %d",             fpm_global_config.syslog_facility); /* FIXME: convert to string */
+#endif
        zlog(ZLOG_NOTICE, "\tprocess_control_timeout = %ds",    fpm_global_config.process_control_timeout);
        zlog(ZLOG_NOTICE, "\temergency_restart_interval = %ds", fpm_global_config.emergency_restart_interval);
        zlog(ZLOG_NOTICE, "\temergency_restart_threshold = %d", fpm_global_config.emergency_restart_threshold);
index 2152527eea41a6678169ab1984c25fe6e2322753..87a5cd332b6f3b0de24f1f8b26cbf2efcbbf31a8 100644 (file)
@@ -25,6 +25,11 @@ struct fpm_global_config_s {
        int daemonize;
        char *pid_file;
        char *error_log;
+       int log_level;
+#ifdef HAVE_SYSLOG_H
+       char *syslog_ident;
+       int syslog_facility;
+#endif
        int rlimit_files;
        int rlimit_core;
 };
index 571f3074b53afe3ad3fad4b2817679b4284af875..4948194f84ff33e115868ec29d78b837ab8b2aed 100644 (file)
@@ -11,6 +11,8 @@
 #include <unistd.h>
 #include <errno.h>
 
+#include "php_syslog.h"
+
 #include "fpm.h"
 #include "fpm_children.h"
 #include "fpm_events.h"
@@ -42,8 +44,10 @@ int fpm_stdio_init_main() /* {{{ */
 int fpm_stdio_init_final() /* {{{ */
 {
        if (fpm_global_config.daemonize) {
-               if (fpm_globals.error_log_fd != STDERR_FILENO) {
-                       /* there might be messages to stderr from libevent, we need to log them all */
+               /* prevent duping if logging to syslog */
+               if (fpm_globals.error_log_fd > 0 && fpm_globals.error_log_fd != STDERR_FILENO) {
+
+                       /* there might be messages to stderr from other parts of the code, we need to log them all */
                        if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) {
                                zlog(ZLOG_SYSERROR, "dup2() failed");
                                return -1;
@@ -57,7 +61,14 @@ int fpm_stdio_init_final() /* {{{ */
 
 int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
 {
-       close(fpm_globals.error_log_fd);
+#ifdef HAVE_SYSLOG_H
+       if (fpm_globals.error_log_fd == ZLOG_SYSLOG) {
+               closelog(); /* ensure to close syslog not to interrupt with PHP syslog code */
+       } else
+#endif
+       if (fpm_globals.error_log_fd > 0) {
+               close(fpm_globals.error_log_fd);
+       }
        fpm_globals.error_log_fd = -1;
        zlog_set_fd(-1);
 
@@ -249,6 +260,17 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
 {
        int fd;
 
+#ifdef HAVE_SYSLOG_H
+       if (!strcasecmp(fpm_global_config.error_log, "syslog")) {
+               openlog(fpm_global_config.syslog_ident, LOG_PID | LOG_CONS, fpm_global_config.syslog_facility);
+               fpm_globals.error_log_fd = ZLOG_SYSLOG;
+               if (fpm_global_config.daemonize) {
+                       zlog_set_fd(fpm_globals.error_log_fd);
+               }
+               return 0;
+       }
+#endif
+
        fd = open(fpm_global_config.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
        if (0 > fd) {
                zlog(ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_config.error_log);
index 6b062eb8ae22fc5818a908b00a24e90481f00e52..b127ec16f67a0103df8ba5e6997a6ba53f91cded 100644 (file)
@@ -12,6 +12,8 @@
 #include <sys/time.h>
 #include <errno.h>
 
+#include "php_syslog.h"
+
 #include "zlog.h"
 #include "fpm.h"
 
@@ -22,12 +24,22 @@ static int zlog_level = ZLOG_NOTICE;
 static int launched = 0;
 
 static const char *level_names[] = {
-       [ZLOG_DEBUG]            = "DEBUG",
-       [ZLOG_NOTICE]           = "NOTICE",
-       [ZLOG_WARNING]          = "WARNING",
-       [ZLOG_ERROR]            = "ERROR",
-       [ZLOG_ALERT]            = "ALERT",
+       [ZLOG_DEBUG]   = "DEBUG",
+       [ZLOG_NOTICE]  = "NOTICE",
+       [ZLOG_WARNING] = "WARNING",
+       [ZLOG_ERROR]   = "ERROR",
+       [ZLOG_ALERT]   = "ALERT",
+};
+
+#ifdef HAVE_SYSLOG_H
+const int syslog_priorities[] = {
+       [ZLOG_DEBUG]   = LOG_DEBUG,
+       [ZLOG_NOTICE]  = LOG_NOTICE,
+       [ZLOG_WARNING] = LOG_WARNING,
+       [ZLOG_ERROR]   = LOG_ERR,
+       [ZLOG_ALERT]   = LOG_ALERT,
 };
+#endif
 
 const char *zlog_get_level_name(int log_level) /* {{{ */
 {
@@ -94,18 +106,30 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
        }
 
        saved_errno = errno;
-       if (!fpm_globals.is_child) {
-               gettimeofday(&tv, 0);
-               len = zlog_print_time(&tv, buf, buf_size);
-       }
-       if (zlog_level == ZLOG_DEBUG) {
+#ifdef HAVE_SYSLOG_H
+       if (zlog_fd == ZLOG_SYSLOG /* && !fpm_globals.is_child */) {
+               len = 0;
+               if (zlog_level == ZLOG_DEBUG) {
+                       len += snprintf(buf, buf_size, "[%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
+               } else {
+                       len += snprintf(buf, buf_size, "[%s] ", level_names[flags & ZLOG_LEVEL_MASK]);
+               }
+       } else
+#endif
+       {
                if (!fpm_globals.is_child) {
-                       len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line);
+                       gettimeofday(&tv, 0);
+                       len = zlog_print_time(&tv, buf, buf_size);
+               }
+               if (zlog_level == ZLOG_DEBUG) {
+                       if (!fpm_globals.is_child) {
+                               len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line);
+                       } else {
+                               len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
+                       }
                } else {
-                       len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
+                       len += snprintf(buf + len, buf_size - len, "%s: ", level_names[flags & ZLOG_LEVEL_MASK]);
                }
-       } else {
-               len += snprintf(buf + len, buf_size - len, "%s: ", level_names[flags & ZLOG_LEVEL_MASK]);
        }
 
        if (len > buf_size - 1) {
@@ -135,9 +159,19 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
                len = buf_size - 1;
        }
 
-       buf[len++] = '\n';
-       write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
-       if (zlog_fd != STDERR_FILENO && zlog_fd > -1 && !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) {
+#ifdef HAVE_SYSLOG_H
+       if (zlog_fd == ZLOG_SYSLOG) {
+               buf[len] = '\0';
+               php_syslog(syslog_priorities[zlog_level], "%s", buf);
+               buf[len++] = '\n';
+       } else 
+#endif
+       {
+               buf[len++] = '\n';
+               write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
+       }
+
+       if (zlog_fd != STDERR_FILENO && zlog_fd != -1 && !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) {
                write(STDERR_FILENO, buf, len);
        }
 }
index a83e329023e4a7fca79a49db26c0db70e593a2fe..e6a5c019a88407cae3f2242cfbe82709792b14ec 100644 (file)
@@ -19,6 +19,10 @@ size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
 void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
                __attribute__ ((format(printf,4,5)));
 
+#ifdef HAVE_SYSLOG_H
+extern const int syslog_priorities[];
+#endif
+
 enum {
        ZLOG_DEBUG                      = 1,
        ZLOG_NOTICE                     = 2,
@@ -33,4 +37,8 @@ enum {
 
 #define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO)
 
+#ifdef HAVE_SYSLOG_H
+#define ZLOG_SYSLOG -2
+#endif
+
 #endif
index 2997ac67f92d66a2a272edb314455810af6c8502..00db9e340e788d4e1e1a3c1ad1a1b7e83d978c09 100644 (file)
 ;pid = run/php-fpm.pid
 
 ; Error log file
+; If it's set to "syslog", log is sent to syslogd instead of being written
+; in a local file.
 ; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@
 ; Default Value: log/php-fpm.log
 ;error_log = log/php-fpm.log
 
+; syslog_facility is used to specify what type of program is logging the
+; message. This lets syslogd specify that messages from different facilities
+; will be handled differently.
+; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON)
+; Default Value: daemon
+;syslog.facility = daemon
+
+; syslog_ident is prepended to every message. If you have multiple FPM
+; instances running on the same server, you can change the default value
+; which must suit common needs.
+; Default Value: php-fpm
+;syslog.ident = php-fpm
+
 ; Log level
 ; Possible Values: alert, error, warning, notice, debug
 ; Default Value: notice