From af869eec1cdba097a70101130c8ee3e6de3aff42 Mon Sep 17 00:00:00 2001 From: Camille Oudot Date: Thu, 7 Apr 2016 18:45:10 +0200 Subject: [PATCH 1/2] log_systemd: new function `sd_journal_send_xavp` creates a structured log event in journald --- modules/log_systemd/doc/log_systemd_admin.xml | 56 ++++++++ modules/log_systemd/journal_send.c | 123 ++++++++++++++++++ modules/log_systemd/journal_send.h | 31 +++++ modules/log_systemd/log_systemd_mod.c | 16 +++ 4 files changed, 226 insertions(+) create mode 100644 modules/log_systemd/journal_send.c create mode 100644 modules/log_systemd/journal_send.h diff --git a/modules/log_systemd/doc/log_systemd_admin.xml b/modules/log_systemd/doc/log_systemd_admin.xml index 26f7dfc0088..213a8b88743 100644 --- a/modules/log_systemd/doc/log_systemd_admin.xml +++ b/modules/log_systemd/doc/log_systemd_admin.xml @@ -100,6 +100,62 @@ loadmodule "log_systemd.so" ... sd_journal_print("LOG_INFO", "R-URI is $ru\n"); ... + + + + +
+ + <function moreinfo="none">sd_journal_send_xavp(name)</function> + + Creates a structured log event in journald. + The sd_journal_send_xavp(name) function sends a log event in journald, based on the + fields provided in the xavp whose root name is specified as parameter. This function is + a wrapper for journald's sd_journal_send() function, and allows to + specify as many custom fields as desired (see sd_journal_send(3)). + + + The xavp given as parameter must contain child AVPs with names conforming to journald's + field name policy (only uppercase letters, numbers and underscore), otherwise they will + be discarded by journald. + + + Some field name have a default meaning for journald: + + + + MESSAGE: the human-readable message string for this entry. + + + + + PRIORTTY: integer priority value between 0 ("emerg") and 7 ("debug") + + + + + (...) (see systemd.journald-fields(7)) + + + + + + This function can be used from ANY_ROUTE. + + + <function>sd_journal_send_xavp</function> usage + +request_route { + $xavp(event=>MESSAGE) = $rm + " request logged with journald"; + $xavp(event[0]=>SIP_MESSAGE) = $mb; +# don't forget the '[0]', otherwise kamailio will create and +# stack new AVPs (see pseudovariable documentation) over the previous one + $xavp(event[0]=>SIP_CALL_ID) = $ci; + $xavp(event[0]=>SIP_SRC_PORT) = $sp; + $xavp(event[0]=>PRIORITY) = 6; + sd_journal_send_xavp("event"); +(...) +}
diff --git a/modules/log_systemd/journal_send.c b/modules/log_systemd/journal_send.c new file mode 100644 index 00000000000..affe52933fa --- /dev/null +++ b/modules/log_systemd/journal_send.c @@ -0,0 +1,123 @@ +/** + * Copyright 2016 (C) Orange + * + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +#include "../../xavp.h" +#include "../../dprint.h" +#include "../../mem/pkg.h" + +#include "journal_send.h" + +int k_sd_journal_send_xavp(str *rname) +{ + struct _sr_xavp *rxavp, *nxavp; + int cnt, buflen, i, ret; + struct iovec *logv; + + rxavp = xavp_get(rname, NULL); + + if (!rxavp || rxavp->val.type != SR_XTYPE_XAVP) { + LM_ERR("not a valid xavp: %.*s?\n", rname->len, rname->s); + } + + /* first, count xavp nodes */ + for (nxavp = rxavp->val.v.xavp, cnt = 0; + nxavp; + nxavp = nxavp->next, cnt++); + + if (cnt == 0) { + /* nothing to log? */ + LM_NOTICE("empty xavp: %.*s?, no log event was sent to journald\n", + rname->len, + rname->s); + return 1; + } + + logv = pkg_malloc(cnt * sizeof (struct iovec)); + + if (!logv) { + LM_ERR("failed to allocate pkg memory\n"); + return -1; + } + + ret = -1; + + for (nxavp = rxavp->val.v.xavp, cnt = 0; + nxavp; + nxavp = nxavp->next, cnt++) + { + if (nxavp->val.type == SR_XTYPE_INT) { + buflen = snprintf(NULL, 0, + "%.*s=%d", + nxavp->name.len, nxavp->name.s, + nxavp->val.v.i); + logv[cnt].iov_base = pkg_malloc(buflen + 1/*snprintf's trailing \0*/); + if (!logv[cnt].iov_base ) { + LM_ERR("failed to allocate pkg memory\n"); + goto free; + } + logv[cnt].iov_len = buflen; + + snprintf(logv[cnt].iov_base, buflen + 1, + "%.*s=%d", + nxavp->name.len, nxavp->name.s, + nxavp->val.v.i); + } else if (nxavp->val.type == SR_XTYPE_STR) { + buflen = nxavp->name.len + 1 + nxavp->val.v.s.len; + logv[cnt].iov_base = pkg_malloc(buflen); + if (!logv[cnt].iov_base) { + LM_ERR("failed to allocate pkg memory\n"); + goto free; + } + logv[cnt].iov_len = buflen; + + memcpy(logv[cnt].iov_base, nxavp->name.s, nxavp->name.len); + ((char*)logv[cnt].iov_base)[nxavp->name.len] = '='; + memcpy(((char*)(logv[cnt].iov_base)) + nxavp->name.len + 1, + nxavp->val.v.s.s, + nxavp->val.v.s.len); + } else { + LM_NOTICE("unsupported type %d for field %.*s, skipped...\n", + nxavp->val.type, + nxavp->name.len, nxavp->name.s); + logv[cnt].iov_len = 0; + logv[cnt].iov_base = NULL; + } + LM_DBG("added io slice %d: %.*s\n", cnt, (int)logv[cnt].iov_len, (char*)logv[cnt].iov_base); + } + + if (sd_journal_sendv(logv, cnt) != 0) { + LM_ERR("sd_journal_sendv() failed\n"); + } else { + ret = 1; + } + +free: + for (i = 0 ; i < cnt ; i++) { + if (logv[i].iov_base) pkg_free(logv[i].iov_base); + } + pkg_free(logv); + return ret; +} diff --git a/modules/log_systemd/journal_send.h b/modules/log_systemd/journal_send.h new file mode 100644 index 00000000000..b5787190b82 --- /dev/null +++ b/modules/log_systemd/journal_send.h @@ -0,0 +1,31 @@ +/** + * Copyright 2016 (C) Orange + * + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _JOURNAL_SEND_H_ +#define _JOURNAL_SEND_H_ + +#include "../../str.h" + +int k_sd_journal_send_xavp(str *rname); + +#endif /* _JOURNAL_SEND_H_ */ diff --git a/modules/log_systemd/log_systemd_mod.c b/modules/log_systemd/log_systemd_mod.c index 7ac2d695b48..6a5834f665b 100644 --- a/modules/log_systemd/log_systemd_mod.c +++ b/modules/log_systemd/log_systemd_mod.c @@ -31,6 +31,8 @@ #include "../../ut.h" #include "../../mod_fix.h" +#include "journal_send.h" + MODULE_VERSION static int _lc_log_systemd = 0; @@ -41,11 +43,14 @@ static int child_init(int); static void mod_destroy(void); static int w_sd_journal_print(struct sip_msg* msg, char* lev, char* txt); +static int w_sd_journal_send_xavp(struct sip_msg* msg, char* xname, char*); static cmd_export_t cmds[]={ {"sd_journal_print", (cmd_function)w_sd_journal_print, 2, fixup_spve_spve, 0, ANY_ROUTE}, + {"sd_journal_send_xavp", (cmd_function)w_sd_journal_send_xavp, 1, fixup_spve_spve, + 0, ANY_ROUTE}, {0, 0, 0, 0, 0, 0} }; @@ -163,3 +168,14 @@ void _lc_core_log_systemd(int lpriority, const char *format, ...) va_end(arglist); sd_journal_print(priority, "%.*s", n, obuf); } + +static int w_sd_journal_send_xavp(struct sip_msg* msg, char* xname, char* foo) { + str sxname; + + if(fixup_get_svalue(msg, (gparam_t*)xname, &sxname)!=0) { + LM_ERR("unable to get xname parameter\n"); + return -1; + } + + return k_sd_journal_send_xavp(&sxname); +} From 2dbcd56c69db94543c355d936f486d2f525855e5 Mon Sep 17 00:00:00 2001 From: Camille Oudot Date: Mon, 11 Apr 2016 11:34:53 +0200 Subject: [PATCH 2/2] log_systemd: refresh README --- modules/log_systemd/README | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/modules/log_systemd/README b/modules/log_systemd/README index 36b2b5cd41a..9453ec0e7d2 100644 --- a/modules/log_systemd/README +++ b/modules/log_systemd/README @@ -27,11 +27,13 @@ Daniel-Constantin Mierla 4. Functions 4.1. sd_journal_print(level, text) + 4.2. sd_journal_send_xavp(name) List of Examples 1.1. Core Logging Replacement with Systemd 1.2. sd_journal_print usage + 1.3. sd_journal_send_xavp usage Chapter 1. Admin Guide @@ -47,6 +49,7 @@ Chapter 1. Admin Guide 4. Functions 4.1. sd_journal_print(level, text) + 4.2. sd_journal_send_xavp(name) 1. Overview @@ -88,6 +91,7 @@ loadmodule "log_systemd.so" 4. Functions 4.1. sd_journal_print(level, text) + 4.2. sd_journal_send_xavp(name) 4.1. sd_journal_print(level, text) @@ -104,3 +108,38 @@ loadmodule "log_systemd.so" ... sd_journal_print("LOG_INFO", "R-URI is $ru\n"); ... + +4.2. sd_journal_send_xavp(name) + + Creates a structured log event in journald. + + The sd_journal_send_xavp(name) function sends a log event in journald, + based on the fields provided in the xavp whose root name is specified + as parameter. This function is a wrapper for journald's + sd_journal_send() function, and allows to specify as many custom fields + as desired (see sd_journal_send(3)). + + The xavp given as parameter must contain child AVPs with names + conforming to journald's field name policy (only uppercase letters, + numbers and underscore), otherwise they will be discarded by journald. + + Some field name have a default meaning for journald: + * MESSAGE: the human-readable message string for this entry. + * PRIORTTY: integer priority value between 0 ("emerg") and 7 + ("debug") + * (...) (see systemd.journald-fields(7)) + + This function can be used from ANY_ROUTE. + + Example 1.3. sd_journal_send_xavp usage +request_route { + $xavp(event=>MESSAGE) = $rm + " request logged with journald"; + $xavp(event[0]=>SIP_MESSAGE) = $mb; +# don't forget the '[0]', otherwise kamailio will create and +# stack new AVPs (see pseudovariable documentation) over the previous one + $xavp(event[0]=>SIP_CALL_ID) = $ci; + $xavp(event[0]=>SIP_SRC_PORT) = $sp; + $xavp(event[0]=>PRIORITY) = 6; + sd_journal_send_xavp("event"); +(...) +}