Various logging improvements and cleanups (#37040)

This commit is contained in:
Daan De Meyer
2025-04-23 15:31:44 +02:00
committed by GitHub
7 changed files with 359 additions and 523 deletions
+4 -1
View File
@@ -75,8 +75,11 @@ size_t log_context_num_fields(void);
void _reset_log_level(int *saved_log_level);
#define _LOG_CONTEXT_SET_LOG_LEVEL(level, l) \
_cleanup_(_reset_log_level) _unused_ int l = log_set_max_level(level);
#define LOG_CONTEXT_SET_LOG_LEVEL(level) \
_cleanup_(_reset_log_level) _unused_ int _saved_log_level_ = log_set_max_level(level);
_LOG_CONTEXT_SET_LOG_LEVEL(level, UNIQ_T(l, UNIQ))
#define LOG_CONTEXT_PUSH(...) \
LOG_CONTEXT_PUSH_STRV(STRV_MAKE(__VA_ARGS__))
+260 -383
View File
File diff suppressed because it is too large Load Diff
+14 -61
View File
@@ -14,6 +14,7 @@
#include "exec-util.h"
#include "fdset.h"
#include "list.h"
#include "log.h"
#include "log-context.h"
#include "namespace.h"
#include "nsflags.h"
@@ -640,6 +641,16 @@ bool exec_is_cgroup_mount_read_only(const ExecContext *context);
const char* exec_get_private_notify_socket_path(const ExecContext *context, const ExecParameters *params, bool needs_sandboxing);
static inline int exec_log_level_max(const ExecContext *context, const ExecParameters *params) {
assert(context);
assert(params);
if (params->debug_invocation)
return LOG_DEBUG;
return context->log_level_max < 0 ? log_get_max_level() : context->log_level_max;
}
/* These logging macros do the same logging as those in unit.h, but using ExecContext and ExecParameters
* instead of the unit object, so that it can be used in the sd-executor context (where the unit object is
* not available). */
@@ -649,77 +660,19 @@ const char* exec_get_private_notify_socket_path(const ExecContext *context, cons
#define LOG_EXEC_INVOCATION_ID_FIELD(ep) \
((ep)->runtime_scope == RUNTIME_SCOPE_USER ? "USER_INVOCATION_ID=" : "INVOCATION_ID=")
#define log_exec_full_errno_zerook(ec, ep, level, error, ...) \
({ \
const ExecContext *_c = (ec); \
const ExecParameters *_p = (ep); \
const int _l = (level); \
bool _do_log = _p->debug_invocation || \
_c->log_level_max < 0 || \
_c->log_level_max >= LOG_PRI(_l); \
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
_c->n_log_extra_fields); \
!_do_log ? -ERRNO_VALUE(error) : \
log_object_internal(_l, error, \
PROJECT_FILE, __LINE__, __func__, \
LOG_EXEC_ID_FIELD(_p), \
_p->unit_id, \
LOG_EXEC_INVOCATION_ID_FIELD(_p), \
_p->invocation_id_string, \
##__VA_ARGS__); \
})
#define log_exec_full_errno(ec, ep, level, error, ...) \
({ \
int _error = (error); \
ASSERT_NON_ZERO(_error); \
log_exec_full_errno_zerook(ec, ep, level, _error, ##__VA_ARGS__); \
})
#define log_exec_full(ec, ep, level, ...) (void) log_exec_full_errno_zerook(ec, ep, level, 0, __VA_ARGS__)
#define log_exec_debug(ec, ep, ...) log_exec_full(ec, ep, LOG_DEBUG, __VA_ARGS__)
#define log_exec_info(ec, ep, ...) log_exec_full(ec, ep, LOG_INFO, __VA_ARGS__)
#define log_exec_notice(ec, ep, ...) log_exec_full(ec, ep, LOG_NOTICE, __VA_ARGS__)
#define log_exec_warning(ec, ep, ...) log_exec_full(ec, ep, LOG_WARNING, __VA_ARGS__)
#define log_exec_error(ec, ep, ...) log_exec_full(ec, ep, LOG_ERR, __VA_ARGS__)
#define log_exec_debug_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_DEBUG, error, __VA_ARGS__)
#define log_exec_info_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_INFO, error, __VA_ARGS__)
#define log_exec_notice_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_NOTICE, error, __VA_ARGS__)
#define log_exec_warning_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_WARNING, error, __VA_ARGS__)
#define log_exec_error_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_ERR, error, __VA_ARGS__)
/* Like LOG_MESSAGE(), but with the unit name prefixed. */
#define LOG_EXEC_MESSAGE(ep, fmt, ...) LOG_MESSAGE("%s: " fmt, (ep)->unit_id, ##__VA_ARGS__)
#define LOG_EXEC_ID(ep) LOG_ITEM("%s%s", LOG_EXEC_ID_FIELD(ep), (ep)->unit_id)
#define LOG_EXEC_INVOCATION_ID(ep) LOG_ITEM("%s%s", LOG_EXEC_INVOCATION_ID_FIELD(ep), (ep)->invocation_id_string)
#define log_exec_struct_errno(ec, ep, level, error, ...) \
({ \
const ExecContext *_c = (ec); \
const ExecParameters *_p = (ep); \
const int _l = (level); \
bool _do_log = _p->debug_invocation || \
_c->log_level_max < 0 || \
_c->log_level_max >= LOG_PRI(_l); \
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
_c->n_log_extra_fields); \
!_do_log ? -ERRNO_VALUE(error) : \
log_struct_errno(_l, error, \
LOG_EXEC_ID(_p), \
LOG_EXEC_INVOCATION_ID(_p), \
__VA_ARGS__); \
})
#define log_exec_struct(ec, ep, level, ...) log_exec_struct_errno(ec, ep, level, 0, __VA_ARGS__)
#define _LOG_CONTEXT_PUSH_EXEC(ec, ep, p, c) \
const ExecContext *c = (ec); \
const ExecParameters *p = (ep); \
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_ID_FIELD(p), p->unit_id); \
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_INVOCATION_ID_FIELD(p), p->invocation_id_string); \
LOG_CONTEXT_PUSH_IOV(c->log_extra_fields, c->n_log_extra_fields)
LOG_CONTEXT_PUSH_IOV(c->log_extra_fields, c->n_log_extra_fields) \
LOG_CONTEXT_SET_LOG_LEVEL(exec_log_level_max(c, p)) \
LOG_SET_PREFIX(p->unit_id);
#define LOG_CONTEXT_PUSH_EXEC(ec, ep) \
_LOG_CONTEXT_PUSH_EXEC(ec, ep, UNIQ_T(p, UNIQ), UNIQ_T(c, UNIQ))
+7 -5
View File
@@ -240,6 +240,8 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to deserialize: %m");
LOG_CONTEXT_PUSH_EXEC(&context, &params);
arg_serialization = safe_fclose(arg_serialization);
fdset = fdset_free(fdset);
@@ -253,11 +255,11 @@ static int run(int argc, char *argv[]) {
const char *status = ASSERT_PTR(
exit_status_to_string(exit_status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD));
log_exec_struct_errno(&context, &params, LOG_ERR, r,
LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED_STR),
LOG_EXEC_MESSAGE(&params, "Failed at step %s spawning %s: %m",
status, command.path),
LOG_ITEM("EXECUTABLE=%s", command.path));
log_struct_errno(LOG_ERR, r,
LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED_STR),
LOG_EXEC_MESSAGE(&params, "Failed at step %s spawning %s: %m",
status, command.path),
LOG_ITEM("EXECUTABLE=%s", command.path));
} else
/* r == 0: 'skip' is chosen in the confirm spawn prompt
* r > 0: expected/ignored failure, do not log at error level */
+25 -22
View File
@@ -1018,10 +1018,22 @@ static inline bool unit_has_job_type(Unit *u, JobType type) {
return u && u->job && u->job->type == type;
}
static inline int unit_get_log_level_max(const Unit *u) {
if (u) {
if (u->debug_invocation)
return LOG_DEBUG;
ExecContext *ec = unit_get_exec_context(u);
if (ec && ec->log_level_max >= 0)
return ec->log_level_max;
}
return log_get_max_level();
}
static inline bool unit_log_level_test(const Unit *u, int level) {
assert(u);
ExecContext *ec = unit_get_exec_context(u);
return !ec || ec->log_level_max < 0 || ec->log_level_max >= LOG_PRI(level) || u->debug_invocation;
return LOG_PRI(level) <= unit_get_log_level_max(u);
}
/* unit_log_skip is for cases like ExecCondition= where a unit is considered "done"
@@ -1085,15 +1097,12 @@ OOMPolicy oom_policy_from_string(const char *s) _pure_;
({ \
const Unit *_u = (unit); \
const int _l = (level); \
bool _do_log = !(log_get_max_level() < LOG_PRI(_l) || \
(_u && !unit_log_level_test(_u, _l))); \
const ExecContext *_c = _do_log && _u ? \
unit_get_exec_context(_u) : NULL; \
LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(_u)); \
const ExecContext *_c = _u ? unit_get_exec_context(_u) : NULL; \
LOG_CONTEXT_PUSH_IOV(_c ? _c->log_extra_fields : NULL, \
_c ? _c->n_log_extra_fields : 0); \
!_do_log ? -ERRNO_VALUE(error) : \
_u ? log_object_internal(_l, error, PROJECT_FILE, __LINE__, __func__, unit_log_field(_u), _u->id, unit_invocation_log_field(_u), _u->invocation_id_string, ##__VA_ARGS__) : \
log_internal(_l, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
_u ? log_object_internal(_l, error, PROJECT_FILE, __LINE__, __func__, unit_log_field(_u), _u->id, unit_invocation_log_field(_u), _u->invocation_id_string, ##__VA_ARGS__) : \
log_internal(_l, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
})
#define log_unit_full_errno(unit, level, error, ...) \
@@ -1129,14 +1138,11 @@ OOMPolicy oom_policy_from_string(const char *s) _pure_;
({ \
const Unit *_u = (unit); \
const int _l = (level); \
bool _do_log = unit_log_level_test(_u, _l); \
const ExecContext *_c = _do_log && _u ? \
unit_get_exec_context(_u) : NULL; \
LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(_u)); \
const ExecContext *_c = _u ? unit_get_exec_context(_u) : NULL; \
LOG_CONTEXT_PUSH_IOV(_c ? _c->log_extra_fields : NULL, \
_c ? _c->n_log_extra_fields : 0); \
_do_log ? \
log_struct_errno(_l, error, __VA_ARGS__, LOG_UNIT_ID(_u)) : \
-ERRNO_VALUE(error); \
log_struct_errno(_l, error, __VA_ARGS__, LOG_UNIT_ID(_u)); \
})
#define log_unit_struct(unit, level, ...) log_unit_struct_errno(unit, level, 0, __VA_ARGS__)
@@ -1145,14 +1151,11 @@ OOMPolicy oom_policy_from_string(const char *s) _pure_;
({ \
const Unit *_u = (unit); \
const int _l = (level); \
bool _do_log = unit_log_level_test(_u, _l); \
const ExecContext *_c = _do_log && _u ? \
unit_get_exec_context(_u) : NULL; \
LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(_u)); \
const ExecContext *_c = _u ? unit_get_exec_context(_u) : NULL; \
LOG_CONTEXT_PUSH_IOV(_c ? _c->log_extra_fields : NULL, \
_c ? _c->n_log_extra_fields : 0); \
_do_log ? \
log_struct_iovec_errno(_l, error, iovec, n_iovec) : \
-ERRNO_VALUE(error); \
log_struct_iovec_errno(_l, error, iovec, n_iovec); \
})
#define log_unit_struct_iovec(unit, level, iovec, n_iovec) log_unit_struct_iovec_errno(unit, level, 0, iovec, n_iovec)
@@ -1222,7 +1225,7 @@ typedef struct UnitForEachDependencyData {
LOG_CONTEXT_PUSH_KEY_VALUE(unit_log_field(u), u->id); \
LOG_CONTEXT_PUSH_KEY_VALUE(unit_invocation_log_field(u), u->invocation_id_string); \
LOG_CONTEXT_PUSH_IOV(c ? c->log_extra_fields : NULL, c ? c->n_log_extra_fields : 0); \
LOG_CONTEXT_SET_LOG_LEVEL(c->log_level_max >= 0 ? c->log_level_max : log_get_max_level())
LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(u))
#define LOG_CONTEXT_PUSH_UNIT(unit) \
_LOG_CONTEXT_PUSH_UNIT(unit, UNIQ_T(u, UNIQ), UNIQ_T(c, UNIQ))
+26 -35
View File
@@ -31,6 +31,7 @@
#include "hwclock-util.h"
#include "list.h"
#include "log.h"
#include "log-context.h"
#include "main-func.h"
#include "memory-util.h"
#include "path-util.h"
@@ -71,33 +72,13 @@ typedef struct Context {
LIST_HEAD(UnitStatusInfo, units);
} Context;
#define log_unit_full_errno_zerook(unit, level, error, ...) \
({ \
const UnitStatusInfo *_u = (unit); \
_u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "UNIT=", _u->name, NULL, NULL, ##__VA_ARGS__) : \
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
})
#define _LOG_CONTEXT_PUSH_UNIT(unit, u) \
const UnitStatusInfo *u = (unit); \
LOG_CONTEXT_PUSH_KEY_VALUE("UNIT=", u->name); \
LOG_SET_PREFIX(u->name)
#define log_unit_full_errno(unit, level, error, ...) \
({ \
int _error = (error); \
ASSERT_NON_ZERO(_error); \
log_unit_full_errno_zerook(unit, level, _error, ##__VA_ARGS__); \
})
#define log_unit_full(unit, level, ...) (void) log_unit_full_errno_zerook(unit, level, 0, ##__VA_ARGS__)
#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, ##__VA_ARGS__)
#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, ##__VA_ARGS__)
#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, ##__VA_ARGS__)
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, ##__VA_ARGS__)
#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, ##__VA_ARGS__)
#define log_unit_debug_errno(unit, error, ...) log_unit_full_errno(unit, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_unit_info_errno(unit, error, ...) log_unit_full_errno(unit, LOG_INFO, error, ##__VA_ARGS__)
#define log_unit_notice_errno(unit, error, ...) log_unit_full_errno(unit, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, ##__VA_ARGS__)
#define log_unit_error_errno(unit, error, ...) log_unit_full_errno(unit, LOG_ERR, error, ##__VA_ARGS__)
#define LOG_CONTEXT_PUSH_UNIT(unit) \
_LOG_CONTEXT_PUSH_UNIT(unit, UNIQ_T(u, UNIQ))
static void unit_status_info_clear(UnitStatusInfo *p) {
assert(p);
@@ -155,8 +136,10 @@ static int context_add_ntp_service(Context *c, const char *s, const char *source
if (!unit->name)
return -ENOMEM;
LOG_CONTEXT_PUSH_UNIT(unit);
LIST_APPEND(units, c->units, unit);
log_unit_debug(unit, "added from %s.", source);
log_debug("added from %s.", source);
TAKE_PTR(unit);
return 0;
@@ -423,6 +406,8 @@ static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m)
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *path = NULL;
LOG_CONTEXT_PUSH_UNIT(u);
unit_status_info_clear(u);
path = unit_dbus_path_from_name(u->name);
@@ -439,7 +424,7 @@ static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m)
NULL,
u);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to get properties: %s", bus_error_message(&error, r));
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
}
return 0;
@@ -493,6 +478,8 @@ static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *erro
assert(bus);
assert(error);
LOG_CONTEXT_PUSH_UNIT(u);
r = bus_call_method(
bus,
bus_systemd_mgr,
@@ -502,8 +489,8 @@ static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *erro
"ss",
u->name,
"replace");
log_unit_full_errno_zerook(u, r < 0 ? LOG_WARNING : LOG_DEBUG, r,
"%s unit: %m", start ? "Starting" : "Stopping");
log_full_errno_zerook(r < 0 ? LOG_WARNING : LOG_DEBUG, r,
"%s unit: %m", start ? "Starting" : "Stopping");
if (r < 0)
return r;
@@ -527,12 +514,14 @@ static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
LOG_CONTEXT_PUSH_UNIT(u);
if (streq(u->unit_file_state, "enabled") == enable) {
log_unit_debug(u, "already %sd.", enable_disable(enable));
log_debug("already %sd.", enable_disable(enable));
return 0;
}
log_unit_info(u, "%s unit.", enable ? "Enabling" : "Disabling");
log_info("%s unit.", enable ? "Enabling" : "Disabling");
if (enable)
r = bus_call_method(
@@ -998,6 +987,8 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (!streq(u->load_state, "loaded"))
continue;
LOG_CONTEXT_PUSH_UNIT(u);
r = unit_enable_or_disable(u, bus, error, enable_this_one);
if (r < 0)
/* If enablement failed, don't start this unit. */
@@ -1005,9 +996,9 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
r = unit_start_or_stop(u, bus, error, enable_this_one);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to %s %sd NTP unit, ignoring: %m",
enable_this_one ? "start" : "stop",
enable_disable(enable_this_one));
log_warning_errno(r, "Failed to %s %sd NTP unit, ignoring: %m",
enable_this_one ? "start" : "stop",
enable_disable(enable_this_one));
if (enable_this_one)
selected = u;
}