blob: 2e86feb6523c4bc07501904f0e2f62de457417f1 [file] [log] [blame]
Vadim Yanitskiye7bf4352020-09-09 03:36:48 +07001/*
2 * (C) 2020 by Vadim Yanitskiy <axilirator@gmail.com>
3 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
Vadim Yanitskiye7bf4352020-09-09 03:36:48 +070017 */
18
19/*! \addtogroup logging
20 * @{
21 * \file logging_systemd.c */
22
23#include <stdio.h>
24#include <syslog.h>
25
26/* Do not use this file as location in sd_journal_print() */
27#define SD_JOURNAL_SUPPRESS_LOCATION
28
29#include <systemd/sd-journal.h>
30
31#include <osmocom/core/talloc.h>
32#include <osmocom/core/utils.h>
33#include <osmocom/core/logging.h>
34
35/* FIXME: copy-pasted from logging_syslog.c */
36static int logp2syslog_level(unsigned int level)
37{
38 if (level >= LOGL_FATAL)
39 return LOG_CRIT;
40 else if (level >= LOGL_ERROR)
41 return LOG_ERR;
42 else if (level >= LOGL_NOTICE)
43 return LOG_NOTICE;
44 else if (level >= LOGL_INFO)
45 return LOG_INFO;
46 else
47 return LOG_DEBUG;
48}
49
50static void _systemd_output(struct log_target *target,
51 unsigned int level, const char *log)
52{
53 /* systemd accepts the same level constants as syslog */
54 sd_journal_print(logp2syslog_level(level), "%s", log);
55}
56
57static void _systemd_raw_output(struct log_target *target, int subsys,
58 unsigned int level, const char *file,
59 int line, int cont, const char *format,
60 va_list ap)
61{
62 char buf[4096];
63 int rc;
64
65 rc = vsnprintf(buf, sizeof(buf), format, ap);
66 if (rc < 0) {
67 sd_journal_print(LOG_ERR, "vsnprintf() failed to render a message "
68 "originated from %s:%d (rc=%d)\n",
69 file, line, rc);
70 return;
71 }
72
73 sd_journal_send("CODE_FILE=%s, CODE_LINE=%d", file, line,
74 "PRIORITY=%d", logp2syslog_level(level),
75 "OSMO_SUBSYS=%s", log_category_name(subsys),
76 "OSMO_SUBSYS_HEX=%4.4x", subsys,
77 "MESSAGE=%s", buf,
78 NULL);
79}
80
81/*! Create a new logging target for systemd journal logging.
82 * \param[in] raw whether to offload rendering of the meta information
83 * (location, category) to systemd-journal.
84 * \returns Log target in case of success, NULL in case of error.
85 */
86struct log_target *log_target_create_systemd(bool raw)
87{
88 struct log_target *target;
89
90 target = log_target_create();
91 if (!target)
92 return NULL;
93
94 target->type = LOG_TGT_TYPE_SYSTEMD;
95 log_target_systemd_set_raw(target, raw);
96
97 return target;
98}
99
100/*! Change meta information handling of an existing logging target.
101 * \param[in] target logging target to be modified.
102 * \param[in] raw whether to offload rendering of the meta information
103 * (location, category) to systemd-journal.
104 */
105void log_target_systemd_set_raw(struct log_target *target, bool raw)
106{
107 target->sd_journal.raw = raw;
108 if (raw) {
109 target->raw_output = _systemd_raw_output;
110 target->output = NULL;
111 } else {
112 target->output = _systemd_output;
113 target->raw_output = NULL;
114 }
115}
116
117/* @} */