Skip to content

Commit

Permalink
log_systemd: new function sd_journal_send_xavp
Browse files Browse the repository at this point in the history
creates a structured log event in journald
  • Loading branch information
camilleoudot committed Apr 12, 2016
1 parent 07f15a3 commit af869ee
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 0 deletions.
56 changes: 56 additions & 0 deletions modules/log_systemd/doc/log_systemd_admin.xml
Expand Up @@ -100,6 +100,62 @@ loadmodule "log_systemd.so"
...
sd_journal_print("LOG_INFO", "R-URI is $ru\n");
...
</programlisting>
</example>
</section>

<section id="log_systemd.f.sd_journal_send_xavp">
<title>
<function moreinfo="none">sd_journal_send_xavp(name)</function>
</title>
<para>Creates a structured log event in journald.</para>
<para>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 <emphasis>sd_journal_send()</emphasis> function, and allows to
specify as many custom fields as desired (see <emphasis>sd_journal_send(3)</emphasis>).
</para>
<para>
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.
</para>
<para>
Some field name have a default meaning for journald:
<itemizedlist>
<listitem>
<para>
<emphasis>MESSAGE</emphasis>: the human-readable message string for this entry.
</para>
</listitem>
<listitem>
<para>
<emphasis>PRIORTTY</emphasis>: integer priority value between 0 ("emerg") and 7 ("debug")
</para>
</listitem>
<listitem>
<para>
(...) (see <emphasis>systemd.journald-fields(7)</emphasis>)
</para>
</listitem>
</itemizedlist>
</para>
<para>
This function can be used from ANY_ROUTE.
</para>
<example>
<title><function>sd_journal_send_xavp</function> usage</title>
<programlisting format="linespecific">
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");
(...)
}
</programlisting>
</example>
</section>
Expand Down
123 changes: 123 additions & 0 deletions modules/log_systemd/journal_send.c
@@ -0,0 +1,123 @@
/**
* Copyright 2016 (C) Orange
* <camille.oudot@orange.com>
*
* 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 <stdio.h>
#include <systemd/sd-journal.h>

#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;
}
31 changes: 31 additions & 0 deletions modules/log_systemd/journal_send.h
@@ -0,0 +1,31 @@
/**
* Copyright 2016 (C) Orange
* <camille.oudot@orange.com>
*
* 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_ */
16 changes: 16 additions & 0 deletions modules/log_systemd/log_systemd_mod.c
Expand Up @@ -31,6 +31,8 @@
#include "../../ut.h"
#include "../../mod_fix.h"

#include "journal_send.h"

MODULE_VERSION

static int _lc_log_systemd = 0;
Expand All @@ -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}
};

Expand Down Expand Up @@ -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);
}

0 comments on commit af869ee

Please sign in to comment.