mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
unit: Make sure individual unit maximum log level always takes priority
Currently LogLevelMax= can only be used to decrease the maximum log level for a unit but not to increase it. Let's make sure the latter works as well, so LogLevelMax=debug can be used to enable debug logging for specific units without enabling debug logging globally.
This commit is contained in:
@@ -3268,23 +3268,30 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
|
||||
<varlistentry>
|
||||
<term><varname>LogLevelMax=</varname></term>
|
||||
|
||||
<listitem><para>Configures filtering by log level of log messages generated by this unit. Takes a
|
||||
<command>syslog</command> log level, one of <option>emerg</option> (lowest log level, only highest priority
|
||||
messages), <option>alert</option>, <option>crit</option>, <option>err</option>, <option>warning</option>,
|
||||
<option>notice</option>, <option>info</option>, <option>debug</option> (highest log level, also lowest priority
|
||||
messages). See <citerefentry
|
||||
<listitem><para>Sets the maximum log level for log messages generated by this unit. Takes a
|
||||
<command>syslog</command> log level, one of <option>emerg</option> (lowest log level, only highest
|
||||
priority messages), <option>alert</option>, <option>crit</option>, <option>err</option>,
|
||||
<option>warning</option>, <option>notice</option>, <option>info</option>, <option>debug</option>
|
||||
(highest log level, also lowest priority messages). See <citerefentry
|
||||
project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
|
||||
details. By default, no filtering is applied (i.e. the default maximum log level is <option>debug</option>). Use
|
||||
this option to configure the logging system to drop log messages of a specific service above the specified
|
||||
level. For example, set <varname>LogLevelMax=</varname><option>info</option> in order to turn off debug logging
|
||||
of a particularly chatty unit. Note that the configured level is applied to any log messages written by any
|
||||
of the processes belonging to this unit, as well as any log messages written by the system manager process
|
||||
(PID 1) in reference to this unit, sent via any supported logging protocol. The filtering is applied
|
||||
early in the logging pipeline, before any kind of further processing is done. Moreover, messages which pass
|
||||
through this filter successfully might still be dropped by filters applied at a later stage in the logging
|
||||
subsystem. For example, <varname>MaxLevelStore=</varname> configured in
|
||||
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> might
|
||||
prohibit messages of higher log levels to be stored on disk, even though the per-unit
|
||||
details. By default, the maximum log level is not overridden.</para>
|
||||
|
||||
<para>This option can be used to configure the logging system to drop log messages of a specific
|
||||
service above the specified level. For example, set
|
||||
<varname>LogLevelMax=</varname><option>info</option> in order to turn off debug logging of a
|
||||
particularly chatty unit. Alternatively, this option can be used to enable extra logging about a
|
||||
specific unit by the system or user manager processes without changing the global log level for the
|
||||
system or user manager processes by setting <varname>LogLevelMax=</varname><option>debug</option>.
|
||||
</para>
|
||||
|
||||
<para>Note that the configured level is applied to any log messages written by any of the processes
|
||||
belonging to this unit, as well as any log messages written by the system or user manager processes
|
||||
in reference to this unit, sent via any supported logging protocol. The override is applied early in
|
||||
the logging pipeline, before any kind of further processing is done. Moreover, messages which pass
|
||||
through this filter successfully might still be dropped by filters applied at a later stage in the
|
||||
logging subsystem. For example, <varname>MaxLevelStore=</varname> configured in
|
||||
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
might prohibit messages of higher log levels to be stored on disk, even though the per-unit
|
||||
<varname>LogLevelMax=</varname> permitted it to be processed.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v236"/></listitem>
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user