You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by jk...@apache.org on 2014/07/14 07:52:46 UTC

svn commit: r1610339 - in /httpd/httpd/trunk: docs/manual/mod/mod_journald.xml modules/loggers/config.m4 modules/loggers/mod_journald.c

Author: jkaluza
Date: Mon Jul 14 05:52:45 2014
New Revision: 1610339

URL: http://svn.apache.org/r1610339
Log:
mod_journald: New module implementing error_log provider for systemd-journald.

Added:
    httpd/httpd/trunk/docs/manual/mod/mod_journald.xml   (with props)
    httpd/httpd/trunk/modules/loggers/mod_journald.c
Modified:
    httpd/httpd/trunk/modules/loggers/config.m4

Added: httpd/httpd/trunk/docs/manual/mod/mod_journald.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_journald.xml?rev=1610339&view=auto
==============================================================================
Binary file - no diff available.

Propchange: httpd/httpd/trunk/docs/manual/mod/mod_journald.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Modified: httpd/httpd/trunk/modules/loggers/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/loggers/config.m4?rev=1610339&r1=1610338&r2=1610339&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/loggers/config.m4 (original)
+++ httpd/httpd/trunk/modules/loggers/config.m4 Mon Jul 14 05:52:45 2014
@@ -4,6 +4,21 @@ dnl APACHE_MODULE(name, helptext[, objec
 
 APACHE_MODPATH_INIT(loggers)
 
+APACHE_MODULE(journald, Journald support, , , all, [
+  AC_CHECK_LIB(systemd-journal, sd_journal_sendv, JOURNALD_LIBS="-lsystemd-journal")
+  AC_CHECK_LIB(systemd-id128, sd_id128_to_string, ID128_LIBS="-lsystemd-id128")
+  AC_CHECK_HEADERS(systemd/sd-journal.h, [ap_HAVE_SD_JOURNAL_H="yes"], [ap_HAVE_SD_JOURNAL_H="no"])
+  AC_CHECK_HEADERS(systemd/sd-id128.h, [ap_HAVE_SD_ID128_H="yes"], [ap_HAVE_SD_ID128_H="no"])
+  if test $ap_HAVE_SD_JOURNAL_H = "no" || test $ap_HAVE_SD_ID128_H = "no" || test -z "${JOURNALD_LIBS}" || test -z "${ID128_LIBS}"; then
+    AC_MSG_WARN([Your system does not support Journald.])
+    enable_journald="no"
+  else
+    APR_ADDTO(MOD_JOURNALD_LDADD, [$JOURNALD_LIBS])
+    APR_ADDTO(MOD_JOURNALD_LDADD, [$ID128_LIBS])
+    enable_journald="yes"
+  fi
+])
+
 APACHE_MODULE(syslog, logging to syslog, , , all, [
   AC_CHECK_HEADERS(syslog.h, [ap_HAVE_SYSLOG_H="yes"], [ap_HAVE_SYSLOG_H="no"])
   if test $ap_HAVE_SYSLOG_H = "no"; then

Added: httpd/httpd/trunk/modules/loggers/mod_journald.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/loggers/mod_journald.c?rev=1610339&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/loggers/mod_journald.c (added)
+++ httpd/httpd/trunk/modules/loggers/mod_journald.c Mon Jul 14 05:52:45 2014
@@ -0,0 +1,275 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+#include <stdint.h>
+#include <ap_config.h>
+#include "ap_mpm.h"
+#include "ap_provider.h"
+#include <http_core.h>
+#include <httpd.h>
+#include <http_log.h>
+#include <apr_version.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include "unixd.h"
+#include "scoreboard.h"
+#include "mpm_common.h"
+#include "mod_log_config.h"
+
+#define SD_JOURNAL_SUPPRESS_LOCATION 1
+
+#include "systemd/sd-journal.h"
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define MAX_ENTRIES 15
+
+static int handle_custom_log = 0;
+
+static int journald_info_get_priority(int level)
+{
+    switch(level) {
+        /* We don't use EMERG here, because journald broadcasts EMERG messages
+         * to all terminals. APLOG_EMERG is usually not used in this context.
+         * in httpd code. */
+        case APLOG_EMERG:   return LOG_ALERT;
+        case APLOG_ALERT:   return LOG_ALERT;
+        case APLOG_CRIT:    return LOG_CRIT;
+        case APLOG_ERR:     return LOG_ERR;
+        case APLOG_WARNING: return LOG_WARNING;
+        case APLOG_NOTICE:  return LOG_NOTICE;
+        case APLOG_INFO:    return LOG_INFO;
+        case APLOG_DEBUG:   return LOG_DEBUG;
+        case -1:            return LOG_INFO;
+        default:            return LOG_DEBUG;
+    }
+    return LOG_INFO;
+}
+
+static apr_pool_t *journald_info_get_pool(const ap_errorlog_info *info)
+{
+    if (info->r && info->r->pool)
+        return info->r->pool;
+    if (info->c && info->c->pool)
+        return info->c->pool;
+    if (info->pool)
+        return info->pool;
+    if (info->s && info->s->process && info->s->process->pool)
+        return info->s->process->pool;
+    return 0;
+}
+
+static apr_status_t iovec_add_entry(apr_pool_t *pool, struct iovec *iov,
+                                    const char *format, int len, ...)
+{
+    va_list ap;
+    va_start(ap, len);
+    iov->iov_base = apr_pvsprintf(pool, format, ap);
+    va_end(ap);
+    if (!iov->iov_base) {
+        return APR_ENOMEM;
+    }
+    if (len < 0) {
+        iov->iov_len = strlen(iov->iov_base);
+    }
+    else {
+        iov->iov_len = len;
+    }
+    return APR_SUCCESS;
+}
+
+static void journald_log(apr_pool_t *pool, const char *log,
+                         const char *errstr, int len, int priority,
+                         const server_rec *s, const request_rec *r)
+{
+    apr_pool_t *subpool;
+    apr_status_t rv = APR_SUCCESS;
+    struct iovec iov[MAX_ENTRIES];
+    int iov_size = 0;
+
+    if (apr_pool_create(&subpool, pool) != APR_SUCCESS) {
+        /* We were not able to create subpool, log at least what we have. */
+        sd_journal_send("MESSAGE=%s", errstr, "LOG=%s", log,
+                    "PRIORITY=%i", priority,
+                    NULL);
+        return;
+    }
+
+    /* Adds new entry to iovec if previous additions were successful. */
+#define IOVEC_ADD_LEN(FORMAT, VAR, LEN) \
+    if (rv == APR_SUCCESS && iov_size < MAX_ENTRIES) { \
+        if ((rv = iovec_add_entry(subpool, &iov[iov_size], FORMAT, LEN, VAR)) \
+            == APR_SUCCESS) \
+                iov_size++; \
+    }
+#define IOVEC_ADD(FORMAT, VAR) IOVEC_ADD_LEN(FORMAT, VAR, -1)
+
+    IOVEC_ADD_LEN("MESSAGE=%s", errstr, len + 8);
+    IOVEC_ADD("LOG=%s", log);
+    IOVEC_ADD("PRIORITY=%i", priority);
+
+    if (s) {
+        IOVEC_ADD("SERVER_HOSTNAME=%s", s->server_hostname);
+    }
+
+    if (r) {
+        IOVEC_ADD("REQUEST_HOSTNAME=%s", r->hostname);
+        IOVEC_ADD("REQUEST_USER=%s", r->user ? r->user : "");
+        IOVEC_ADD("REQUEST_URI=%s", r->uri ? r->uri : "");
+        IOVEC_ADD("REQUEST_USERAGENT_IP=%s", r->useragent_ip);
+    }
+
+    sd_journal_sendv(iov, iov_size);
+    apr_pool_destroy(subpool);
+}
+
+static void *journald_error_log_init(apr_pool_t *p, server_rec *s)
+{
+    void *success = (void *)p; /* anything non-NULL is success */
+    return success;
+}
+
+static apr_status_t journald_error_log(const ap_errorlog_info *info,
+                                       void *handle, const char *errstr,
+                                       apr_size_t len)
+{
+    const server_rec *s = info->s;
+    const request_rec *r = info->r;
+    apr_pool_t *pool;
+    const char *log_name = (s && s->error_fname && *s->error_fname) ?
+                            s->error_fname : "error_log";
+
+    pool = journald_info_get_pool(info);
+    if (!pool) {
+        /* We don't have any pool, so at least log the message without
+         * any additional data. */
+        sd_journal_send("MESSAGE=%s", errstr, "LOG=%s", "log_name",
+                    "PRIORITY=%i", journald_info_get_priority(info->level),
+                    NULL);
+        return APR_SUCCESS;
+    }
+
+    journald_log(pool, log_name, errstr, len,
+                 journald_info_get_priority(info->level), s, r);
+
+    return APR_SUCCESS;
+}
+
+static const char *journald_error_log_parse(cmd_parms *cmd, const char *arg)
+{
+    return NULL;
+}
+
+static apr_status_t journald_log_writer(request_rec *r,
+                           void *handle,
+                           const char **strs,
+                           int *strl,
+                           int nelts,
+                           apr_size_t len)
+
+{
+    char *str;
+    char *s;
+    int i;
+    apr_status_t rv = APR_SUCCESS;
+
+    str = apr_palloc(r->pool, len + 1);
+
+    /* Last string is always \n, so skipt it */
+    for (i = 0, s = str; i < nelts - 1; ++i) {
+        memcpy(s, strs[i], strl[i]);
+        s += strl[i];
+    }
+
+    journald_log(r->pool, (char *) handle, str, len,
+                 LOG_INFO, r->server, r);
+
+    return rv;
+}
+
+static void *journald_log_writer_init(apr_pool_t *p, server_rec *s,
+                                        const char* name)
+{
+    char *log_name = apr_pstrdup(p, name);
+    return log_name;
+}
+
+static int journald_open_logs(apr_pool_t *p, apr_pool_t *plog,
+                               apr_pool_t *ptemp, server_rec *s)
+{
+    APR_OPTIONAL_FN_TYPE(ap_log_set_writer_init) *log_set_writer_init;
+    APR_OPTIONAL_FN_TYPE(ap_log_set_writer) *log_set_writer;
+
+    if (!handle_custom_log) {
+        return OK;
+    }
+
+    log_set_writer_init = APR_RETRIEVE_OPTIONAL_FN(ap_log_set_writer_init);
+    log_set_writer = APR_RETRIEVE_OPTIONAL_FN(ap_log_set_writer);
+
+    if (log_set_writer_init) {
+        log_set_writer_init(&journald_log_writer_init);
+    }
+
+    if (log_set_writer) {
+        log_set_writer(&journald_log_writer);
+    }
+
+    return OK;
+}
+
+static void journald_register_hooks(apr_pool_t *p)
+{
+    static const ap_errorlog_provider journald_provider = {
+        &journald_error_log_init,
+        &journald_error_log,
+        &journald_error_log_parse,
+        0
+    };
+
+    ap_register_provider(p, AP_ERRORLOG_PROVIDER_GROUP, "journald",
+                         AP_ERRORLOG_PROVIDER_VERSION,
+                         &journald_provider);
+
+    ap_hook_open_logs(journald_open_logs, NULL, NULL, APR_HOOK_FIRST);
+}
+
+static const char *set_custom_log_on(cmd_parms *parms, void *dummy, int flag)
+{
+    handle_custom_log = flag;
+    return NULL;
+}
+
+static const command_rec journald_cmds[] =
+{
+AP_INIT_FLAG("JournaldCustomLog", set_custom_log_on, NULL, RSRC_CONF,
+     "Enable logging of CustomLog/TransferLog to journald"),
+    {NULL}
+};
+
+AP_DECLARE_MODULE(journald) =
+{
+    STANDARD20_MODULE_STUFF,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    journald_cmds,
+    journald_register_hooks,
+};



Re: svn commit: r1610339 - in /httpd/httpd/trunk: docs/manual/mod/mod_journald.xml modules/loggers/config.m4 modules/loggers/mod_journald.c

Posted by Jan Kaluža <jk...@redhat.com>.
On 07/14/2014 09:52 AM, Ruediger Pluem wrote:
>
>
> jkaluza@apache.org wrote:
>> Author: jkaluza
>> Date: Mon Jul 14 05:52:45 2014
>> New Revision: 1610339
>>
>> URL: http://svn.apache.org/r1610339
>> Log:
>> mod_journald: New module implementing error_log provider for systemd-journald.
>>
>> Added:
>>      httpd/httpd/trunk/docs/manual/mod/mod_journald.xml   (with props)
>>      httpd/httpd/trunk/modules/loggers/mod_journald.c
>> Modified:
>>      httpd/httpd/trunk/modules/loggers/config.m4
>>
>
>> Added: httpd/httpd/trunk/modules/loggers/mod_journald.c
>> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/loggers/mod_journald.c?rev=1610339&view=auto
>> ==============================================================================
>> --- httpd/httpd/trunk/modules/loggers/mod_journald.c (added)
>> +++ httpd/httpd/trunk/modules/loggers/mod_journald.c Mon Jul 14 05:52:45 2014
>
>> +static apr_status_t journald_log_writer(request_rec *r,
>> +                           void *handle,
>> +                           const char **strs,
>> +                           int *strl,
>> +                           int nelts,
>> +                           apr_size_t len)
>> +
>> +{
>> +    char *str;
>> +    char *s;
>> +    int i;
>> +    apr_status_t rv = APR_SUCCESS;
>> +
>> +    str = apr_palloc(r->pool, len + 1);
>
> Why +1?

That's taken from ap_default_log_writer(...) and it's also in 
ap_buffered_log_writer(...). When thinking about it now, it's probably 
useless, because "len" is sum of strlen() of each string in strs, so it 
does not include '\0', but my log_writer (and also the 
ap_default_log_writer/ap_buffered_log_writer) does not actually use/set 
that last zero byte.

I think we can remove that "len + 1" in all three cases then?

Jan Kaluza

> Regards
>
> Rüdiger
>


Re: svn commit: r1610339 - in /httpd/httpd/trunk: docs/manual/mod/mod_journald.xml modules/loggers/config.m4 modules/loggers/mod_journald.c

Posted by Ruediger Pluem <rp...@apache.org>.

jkaluza@apache.org wrote:
> Author: jkaluza
> Date: Mon Jul 14 05:52:45 2014
> New Revision: 1610339
> 
> URL: http://svn.apache.org/r1610339
> Log:
> mod_journald: New module implementing error_log provider for systemd-journald.
> 
> Added:
>     httpd/httpd/trunk/docs/manual/mod/mod_journald.xml   (with props)
>     httpd/httpd/trunk/modules/loggers/mod_journald.c
> Modified:
>     httpd/httpd/trunk/modules/loggers/config.m4
> 

> Added: httpd/httpd/trunk/modules/loggers/mod_journald.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/loggers/mod_journald.c?rev=1610339&view=auto
> ==============================================================================
> --- httpd/httpd/trunk/modules/loggers/mod_journald.c (added)
> +++ httpd/httpd/trunk/modules/loggers/mod_journald.c Mon Jul 14 05:52:45 2014

> +static apr_status_t journald_log_writer(request_rec *r,
> +                           void *handle,
> +                           const char **strs,
> +                           int *strl,
> +                           int nelts,
> +                           apr_size_t len)
> +
> +{
> +    char *str;
> +    char *s;
> +    int i;
> +    apr_status_t rv = APR_SUCCESS;
> +
> +    str = apr_palloc(r->pool, len + 1);

Why +1?

Regards

Rüdiger