]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
json-util: fine tune json_dispatch_log_level()
authorLennart Poettering <lennart@poettering.net>
Tue, 7 Jan 2025 13:24:33 +0000 (14:24 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 18 Jan 2025 22:24:29 +0000 (23:24 +0100)
Let's give the user control on how to handle JSON "null" assignments of
the log level. As one of three cases: as failure, as LOG_NULL (i.e. to
turn off logging) or as LOG_INFO (as our usual default log level).

Let's then use that in the generic SetLogLevel() call, so that callers
can use it to explicitly turn off logging in a service.

Note that this was (probably accidentally) already implemented, except
that the introspection enforcement blocked it. Let's clean this up and
make this officially a thing, since it's generally useful to turn off
logging I think.

src/basic/log.h
src/libsystemd/sd-json/json-util.c
src/shared/varlink-io.systemd.service.c

index 3859a6c41dea63744864c84b83b83e40d8413b37..02f3f509d18b59acf9576257fe582ca132f98dfe 100644 (file)
@@ -34,6 +34,7 @@ typedef enum LogTarget{
 /* This log level disables logging completely. It can only be passed to log_set_max_level() and cannot be
  * used as a regular log level. */
 #define LOG_NULL (LOG_EMERG - 1)
+assert_cc(LOG_NULL == -1);
 
 #define SYNTHETIC_ERRNO(num)                (abs(num) | (1 << 30))
 #define IS_SYNTHETIC_ERRNO(val)             (((val) >> 30) == 1)
index ea64205c14e29cdb0feb076c2cdf72c5fc7c5568..b7990411ea8e0b17b05c87c181376c5ea16b9ab5 100644 (file)
@@ -344,8 +344,15 @@ int json_dispatch_ifindex(const char *name, sd_json_variant *variant, sd_json_di
 int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
         int *log_level = ASSERT_PTR(userdata), r, t;
 
+        /* If SD_JSON_STRICT is set, we'll refuse attempts to set the log level to null. If SD_JSON_RELAX is
+         * set we'll turn null (and any negative log level) into LOG_NULL (which when used as max log level
+         * means: no logging). Otherwise we turn null into LOG_INFO (which is typically our default). */
+
         if (sd_json_variant_is_null(variant)) {
-                *log_level = -1;
+                if (FLAGS_SET(flags, SD_JSON_STRICT))
+                        return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' may not be null.", strna(name));
+
+                *log_level = FLAGS_SET(flags, SD_JSON_RELAX) ? LOG_NULL : LOG_INFO;
                 return 0;
         }
 
@@ -353,8 +360,9 @@ int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_
         if (r < 0)
                 return r;
 
-        /* If SD_JSON_RELAX is set allow a zero interface index, otherwise refuse. */
-        if (LOG_PRI(t) != t)
+        if (FLAGS_SET(flags, SD_JSON_RELAX) && t < 0)
+                t = LOG_NULL;
+        else if (LOG_PRI(t) != t)
                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid log level.", strna(name));
 
         *log_level = t;
index f34d5cfead66c8507d08a322d469ff60f84c5fb7..d029fda41badd8f9e6694028628e1b254281946e 100644 (file)
@@ -11,8 +11,8 @@ static SD_VARLINK_DEFINE_METHOD(Reload);
 
 static SD_VARLINK_DEFINE_METHOD(
                 SetLogLevel,
-                SD_VARLINK_FIELD_COMMENT("The maximum log level."),
-                SD_VARLINK_DEFINE_INPUT(level, SD_VARLINK_INT, 0));
+                SD_VARLINK_FIELD_COMMENT("The maximum log level, using BSD syslog log level integers."),
+                SD_VARLINK_DEFINE_INPUT(level, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
 
 SD_VARLINK_DEFINE_INTERFACE(
                 io_systemd_service,