1ORG.FREEDESKTOP.LOGCONTROL1o(r5g).freedesktop.LogContOrRoGl.1FREEDESKTOP.LOGCONTROL1(5)
2
3
4

NAME

6       org.freedesktop.LogControl1 - D-Bus interface to query and set logging
7       configuration
8

INTRODUCTION

10       org.freedesktop.LogControl1 is a generic interface that is intended to
11       be used by any daemon which allows the log level and target to be set
12       over D-Bus. It is implemented by various daemons that are part of the
13       systemd(1) suite.
14
15       It is assumed that those settings are global for the whole program, so
16       a fixed object path is used. The interface should always be available
17       under the path /org/freedesktop/LogControl1.
18

DESCRIPTION

20       The following interface is exposed:
21
22           node /org/freedesktop/LogControl1 {
23             interface org.freedesktop.LogControl1 {
24               properties:
25                 @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
26                 @org.freedesktop.systemd1.Privileged("true")
27                 readwrite s LogLevel = '...';
28                 @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
29                 @org.freedesktop.systemd1.Privileged("true")
30                 readwrite s LogTarget = '...';
31                 @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
32                 readonly s SyslogIdentifier = '...';
33             };
34             interface org.freedesktop.DBus.Peer { ... };
35             interface org.freedesktop.DBus.Introspectable { ... };
36             interface org.freedesktop.DBus.Properties { ... };
37           };
38
39
40
41
42
43
44   Properties
45       LogLevel describes the syslog(3)-style log-level, and should be one of
46       "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug",
47       in order of increasing verbosity.
48
49       LogTarget describes the log target (mechanism). It should be one of
50       "console" (log to the console or standard output), "kmsg" (log to the
51       kernel ring buffer), "journal" (log to the journal natively, see
52       systemd-journald.service(8)), "syslog" (log using the syslog(3) call).
53
54       Those two properties are writable, so they may be set by sufficiently
55       privileged users.
56
57       SyslogIdentifier is a read-only property that shows the "syslog
58       identifier". It is a short string that identifies the program that is
59       the source of log messages that is passed to the syslog(3) call.
60

TOOLS

62       journalctl option -p/--priority= may be used to filter log messages by
63       log level, option -t/--identifier= may be used to by the syslog
64       identifier, and filters like "_TRANSPORT=syslog", "_TRANSPORT=journal",
65       and "_TRANSPORT=kernel" may be used to filter messages by the mechanism
66       through which they reached systemd-journald.
67
68       systemctl log-level and systemctl log-target verbs may be used to query
69       and set the LogLevel and LogTarget properties of the service manager.
70       systemctl service-log-level and systemctl service-log-target may
71       similarly be used for individual services. (Services must have the
72       BusName= property set and must implement the interface described here.
73       See systemd.service(5) for details about BusName=.)
74

EXAMPLE

76       Example 1. Create a simple listener on the bus that implements
77       LogControl1
78
79           /* SPDX-License-Identifier: MIT-0 */
80
81           /* Implements the LogControl1 interface as per specification:
82            * https://www.freedesktop.org/software/systemd/man/org.freedesktop.LogControl1.html
83            *
84            * Compile with 'cc logcontrol-example.c $(pkg-config --libs --cflags libsystemd)'
85            *
86            * To get and set properties via busctl:
87            *
88            * $ busctl --user get-property org.freedesktop.Example \
89            *                              /org/freedesktop/LogControl1 \
90            *                              org.freedesktop.LogControl1 \
91            *                              SyslogIdentifier
92            *   s "example"
93            * $ busctl --user get-property org.freedesktop.Example \
94            *                              /org/freedesktop/LogControl1 \
95            *                              org.freedesktop.LogControl1 \
96            *                              LogTarget
97            *   s "journal"
98            * $ busctl --user get-property org.freedesktop.Example \
99            *                              /org/freedesktop/LogControl1 \
100            *                              org.freedesktop.LogControl1 \
101            *                              LogLevel
102            *   s "info"
103            * $ busctl --user set-property org.freedesktop.Example \
104            *                              /org/freedesktop/LogControl1 \
105            *                              org.freedesktop.LogControl1 \
106            *                              LogLevel \
107            *                              "s" debug
108            * $ busctl --user get-property org.freedesktop.Example \
109            *                              /org/freedesktop/LogControl1 \
110            *                              org.freedesktop.LogControl1 \
111            *                              LogLevel
112            *   s "debug"
113            */
114
115           #include <errno.h>
116           #include <stdlib.h>
117           #include <stdio.h>
118           #include <syslog.h>
119           #include <systemd/sd-bus.h>
120           #include <systemd/sd-journal.h>
121
122           #define _cleanup_(f) __attribute__((cleanup(f)))
123
124           #define check(log_level, x) ({                  \
125             int _r = (x);                                 \
126             errno = _r < 0 ? -_r : 0;                     \
127             sd_journal_print((log_level), #x ": %m");     \
128             if (_r < 0)                                   \
129               return EXIT_FAILURE;                        \
130             })
131
132           typedef enum LogTarget {
133             LOG_TARGET_JOURNAL,
134             LOG_TARGET_KMSG,
135             LOG_TARGET_SYSLOG,
136             LOG_TARGET_CONSOLE,
137             _LOG_TARGET_MAX,
138           } LogTarget;
139
140           static const char* const log_target_table[_LOG_TARGET_MAX] = {
141             [LOG_TARGET_JOURNAL] = "journal",
142             [LOG_TARGET_KMSG]    = "kmsg",
143             [LOG_TARGET_SYSLOG]  = "syslog",
144             [LOG_TARGET_CONSOLE] = "console",
145           };
146
147           static const char* const log_level_table[LOG_DEBUG + 1] = {
148             [LOG_EMERG]   = "emerg",
149             [LOG_ALERT]   = "alert",
150             [LOG_CRIT]    = "crit",
151             [LOG_ERR]     = "err",
152             [LOG_WARNING] = "warning",
153             [LOG_NOTICE]  = "notice",
154             [LOG_INFO]    = "info",
155             [LOG_DEBUG]   = "debug",
156           };
157
158           typedef struct object {
159             const char *syslog_identifier;
160             LogTarget log_target;
161             int log_level;
162           } object;
163
164           static int property_get(
165                           sd_bus *bus,
166                           const char *path,
167                           const char *interface,
168                           const char *property,
169                           sd_bus_message *reply,
170                           void *userdata,
171                           sd_bus_error *error) {
172
173             object *o = userdata;
174
175             if (strcmp(property, "LogLevel") == 0)
176               return sd_bus_message_append(reply, "s", log_level_table[o->log_level]);
177
178             if (strcmp(property, "LogTarget") == 0)
179               return sd_bus_message_append(reply, "s", log_target_table[o->log_target]);
180
181             if (strcmp(property, "SyslogIdentifier") == 0)
182               return sd_bus_message_append(reply, "s", o->syslog_identifier);
183
184             return sd_bus_error_setf(error,
185                                      SD_BUS_ERROR_UNKNOWN_PROPERTY,
186                                      "Unknown property '%s'",
187                                      property);
188           }
189
190           static int property_set(
191                           sd_bus *bus,
192                           const char *path,
193                           const char *interface,
194                           const char *property,
195                           sd_bus_message *message,
196                           void *userdata,
197                           sd_bus_error *error) {
198
199             object *o = userdata;
200             const char *value;
201             int r;
202
203             r = sd_bus_message_read(message, "s", &value);
204             if (r < 0)
205               return r;
206
207             if (strcmp(property, "LogLevel") == 0) {
208               for (int i = 0; i < LOG_DEBUG + 1; i++)
209                 if (strcmp(value, log_level_table[i]) == 0) {
210                   o->log_level = i;
211                   setlogmask(LOG_UPTO(i));
212                   return 0;
213                 }
214
215               return sd_bus_error_setf(error,
216                                        SD_BUS_ERROR_INVALID_ARGS,
217                                        "Invalid value for LogLevel: '%s'",
218                                        value);
219             }
220
221             if (strcmp(property, "LogTarget") == 0) {
222               for (LogTarget i = 0; i < _LOG_TARGET_MAX; i++)
223                 if (strcmp(value, log_target_table[i]) == 0) {
224                   o->log_target = i;
225                   return 0;
226                 }
227
228               return sd_bus_error_setf(error,
229                                        SD_BUS_ERROR_INVALID_ARGS,
230                                        "Invalid value for LogTarget: '%s'",
231                                        value);
232             }
233
234             return sd_bus_error_setf(error,
235                                      SD_BUS_ERROR_UNKNOWN_PROPERTY,
236                                      "Unknown property '%s'",
237                                      property);
238           }
239
240           /* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
241            */
242           static const sd_bus_vtable vtable[] = {
243             SD_BUS_VTABLE_START(0),
244             SD_BUS_WRITABLE_PROPERTY(
245               "LogLevel", "s",
246               property_get, property_set,
247               0,
248               0),
249             SD_BUS_WRITABLE_PROPERTY(
250               "LogTarget", "s",
251               property_get, property_set,
252               0,
253               0),
254             SD_BUS_PROPERTY(
255               "SyslogIdentifier", "s",
256               property_get,
257               0,
258               SD_BUS_VTABLE_PROPERTY_CONST),
259             SD_BUS_VTABLE_END
260           };
261
262           int main(int argc, char **argv) {
263             /* The bus should be relinquished before the program terminates. The cleanup
264              * attribute allows us to do it nicely and cleanly whenever we exit the
265              * block.
266              */
267             _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
268
269             object o = {
270               .log_level = LOG_INFO,
271               .log_target = LOG_TARGET_JOURNAL,
272               .syslog_identifier = "example",
273             };
274
275             /* https://man7.org/linux/man-pages/man3/setlogmask.3.html
276              * Programs using syslog() instead of sd_journal can use this API to cut logs
277              * emission at the source.
278              */
279             setlogmask(LOG_UPTO(o.log_level));
280
281             /* Acquire a connection to the bus, letting the library work out the details.
282              * https://www.freedesktop.org/software/systemd/man/sd_bus_default.html
283              */
284             check(o.log_level, sd_bus_default(&bus));
285
286             /* Publish an interface on the bus, specifying our well-known object access
287              * path and public interface name.
288              * https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
289              * https://dbus.freedesktop.org/doc/dbus-tutorial.html
290              */
291             check(o.log_level, sd_bus_add_object_vtable(bus, NULL,
292                                                         "/org/freedesktop/LogControl1",
293                                                         "org.freedesktop.LogControl1",
294                                                         vtable,
295                                                         &o));
296
297             /* By default the service is assigned an ephemeral name. Also add a fixed
298              * one, so that clients know whom to call.
299              * https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
300              */
301             check(o.log_level, sd_bus_request_name(bus, "org.freedesktop.Example", 0));
302
303             for (;;) {
304               /* https://www.freedesktop.org/software/systemd/man/sd_bus_wait.html
305                */
306               check(o.log_level, sd_bus_wait(bus, UINT64_MAX));
307               /* https://www.freedesktop.org/software/systemd/man/sd_bus_process.html
308                */
309               check(o.log_level, sd_bus_process(bus, NULL));
310             }
311
312             /* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html
313              */
314             check(o.log_level, sd_bus_release_name(bus, "org.freedesktop.Example"));
315
316             return 0;
317           }
318
319       This creates a simple server on the bus. It implements the LogControl1
320       interface by providing the required properties and allowing to set the
321       writable ones. It logs at the configured log level using
322       sd_journal_print(3).
323

SEE ALSO

325       systemd(1), journalctl(1), systemctl(1), systemd.service(5), syslog(3)
326
327
328
329systemd 254                                     ORG.FREEDESKTOP.LOGCONTROL1(5)
Impressum