summaryrefslogtreecommitdiffstats
path: root/modules/loggers
diff options
context:
space:
mode:
authorPaul Querna <pquerna@apache.org>2018-04-23 17:49:16 +0200
committerPaul Querna <pquerna@apache.org>2018-04-23 17:49:16 +0200
commit43e8216b894c02b87aad2d969fb9d9c3431280ac (patch)
tree5646ad9aed2aa6b3dbd97dfb02137ebd76272e4f /modules/loggers
parentMove APACHE_CHECK_JANSSON m4 macro to general includes so additional modules ... (diff)
downloadapache2-43e8216b894c02b87aad2d969fb9d9c3431280ac.tar.xz
apache2-43e8216b894c02b87aad2d969fb9d9c3431280ac.zip
Add mod_log_json
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1829898 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/loggers')
-rw-r--r--modules/loggers/config.m411
-rw-r--r--modules/loggers/mod_log_json.c169
2 files changed, 180 insertions, 0 deletions
diff --git a/modules/loggers/config.m4 b/modules/loggers/config.m4
index 30318626ba..f4e908fe24 100644
--- a/modules/loggers/config.m4
+++ b/modules/loggers/config.m4
@@ -36,6 +36,17 @@ APACHE_MODULE(syslog, logging to syslog, , , all, [
fi
])
+
+APACHE_MODULE(log_json, logging in jsonn, , , most, [
+ APACHE_CHECK_JANSSON
+ if test "x$ac_cv_jansson" != "xyes" ; then
+ AC_MSG_WARN([libjansson not found])
+ enable_log_json="no"
+ else
+ enable_log_json="yes"
+ fi
+])
+
APACHE_MODULE(log_config, logging configuration. You won't be able to log requests to the server without this module., , , yes)
APACHE_MODULE(log_debug, configurable debug logging, , , most)
APACHE_MODULE(log_forensic, forensic logging)
diff --git a/modules/loggers/mod_log_json.c b/modules/loggers/mod_log_json.c
new file mode 100644
index 0000000000..c7d70d8be1
--- /dev/null
+++ b/modules/loggers/mod_log_json.c
@@ -0,0 +1,169 @@
+/* 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 "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+
+#include <mod_ssl.h>
+#include <mod_log_config.h>
+
+#include "apr_strings.h"
+
+#include <jansson.h>
+
+APLOG_USE_MODULE(log_json);
+
+module AP_MODULE_DECLARE_DATA log_json_module;
+
+static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *log_json_ssl_lookup = NULL;
+static APR_OPTIONAL_FN_TYPE(ssl_is_https) *log_json_ssl_is_https = NULL;
+static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_json_register = NULL;
+
+static const char *crit_error =
+ "{\"mod_log_json_error\": \"critical error during serialization: see error "
+ "log\"}";
+
+static int
+log_json_dump_bb(const char *buffer, size_t size, void *baton)
+{
+ apr_bucket_brigade *bb = baton;
+ apr_brigade_write(bb, NULL, NULL, buffer, size);
+ return 0;
+}
+
+static const char *
+log_json(request_rec *r, char *a)
+{
+ apr_size_t olen;
+ apr_status_t rv;
+ int err;
+ char *out;
+ apr_bucket_brigade *bb;
+ json_t *obj;
+
+ obj = json_object();
+
+ json_object_set_new_nocheck(obj, "log_id",
+ r->log_id != NULL ? json_string(r->log_id) : json_null());
+ json_object_set_new_nocheck(
+ obj, "vhost", json_string(r->server->server_hostname));
+ json_object_set_new_nocheck(
+ obj, "status", json_string(apr_itoa(r->pool, r->status)));
+ json_object_set_new_nocheck(obj, "proto", json_string(r->protocol));
+ json_object_set_new_nocheck(obj, "method", json_string(r->method));
+ json_object_set_new_nocheck(obj, "uri", json_string(r->uri));
+ json_object_set_new_nocheck(obj, "srcip", json_string(r->useragent_ip));
+ json_object_set_new_nocheck(obj, "bytes_sent", json_integer(r->bytes_sent));
+
+ if (r->user != NULL) {
+ json_object_set_new_nocheck(obj, "user", json_string(r->user));
+ }
+
+ json_t *hdrs = json_object();
+ json_object_set_new_nocheck(hdrs, "user-agent",
+ json_string(apr_table_get(r->headers_in, "User-Agent")));
+ json_object_set_new_nocheck(obj, "hdrs", hdrs);
+
+ if (log_json_ssl_is_https != NULL && log_json_ssl_lookup != NULL &&
+ log_json_ssl_is_https(r->connection)) {
+ json_t *tls = json_object();
+
+ json_object_set_new_nocheck(tls, "v",
+ json_string(log_json_ssl_lookup(
+ r->pool, r->server, r->connection, r, "SSL_PROTOCOL")));
+ json_object_set_new_nocheck(tls, "cipher",
+ json_string(log_json_ssl_lookup(
+ r->pool, r->server, r->connection, r, "SSL_COPHER")));
+ json_object_set_new_nocheck(tls, "client_verify",
+ json_string(log_json_ssl_lookup(
+ r->pool, r->server, r->connection, r, "SSL_CLIENT_VERIFY")));
+ json_object_set_new_nocheck(tls, "sni",
+ json_string(log_json_ssl_lookup(
+ r->pool, r->server, r->connection, r, "SSL_TLS_SNI")));
+
+ json_object_set_new_nocheck(obj, "tls", tls);
+ }
+
+ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ err = json_dump_callback(
+ obj, log_json_dump_bb, bb, JSON_ENSURE_ASCII | JSON_COMPACT);
+ if (err != 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ APLOGNO(10125) "json_dump_callback failed: %d", err);
+ apr_brigade_destroy(bb);
+ return crit_error;
+ }
+
+ rv = apr_brigade_pflatten(bb, &out, &olen, r->pool);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ APLOGNO(10126) "apr_brigade_pflatten failed");
+ apr_brigade_destroy(bb);
+ return crit_error;
+ }
+ apr_brigade_destroy(bb);
+ return out;
+}
+
+static int
+log_json_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
+{
+ log_json_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
+ log_json_register(p, "^JS", log_json, 0);
+ return OK;
+}
+
+static int
+log_json_post_config(
+ apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+{
+ apr_status_t rv;
+ server_rec *snxt;
+ void *userdata_data = NULL;
+ const char *userdata_key = "log_json_init";
+
+ apr_pool_userdata_get(&userdata_data, userdata_key, s->process->pool);
+ if (userdata_data == NULL) {
+ apr_pool_userdata_set((const void *)1, userdata_key,
+ apr_pool_cleanup_null, s->process->pool);
+ return OK;
+ }
+
+ log_json_ssl_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
+ log_json_ssl_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
+
+ /* http://jansson.readthedocs.io/en/2.8/portability.html#portability-thread-safety
+ */
+ json_object_seed(0);
+
+ return OK;
+}
+
+static const command_rec directives[] = {{NULL}};
+
+static void
+register_hooks(apr_pool_t *pool)
+{
+ ap_hook_pre_config(log_json_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config(log_json_post_config, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA log_json_module = {STANDARD20_MODULE_STUFF, NULL,
+ NULL, NULL, NULL, directives, register_hooks};