Make lib.App logging more customizable #55

Merged
Jan Lindemann merged 6 commits from jan/feature/20260810-make-lib-app-logging-more-customizable into master 2026-08-10 20:34:59 +02:00 AGit

This PR brings a number of fixes and improvments to logging via the lib.log.log() framework and the way lib.App uses it. It beautifies log output, modernizes the antique log flag handling, and gives more freedom to customize the default logging behaviour for classes inheriting lib.App.

lib.log.log(): Fix early return without flags set

When position, prio, and date are all absent from the log flags, the msg variable is empty. The early return 'if not len(msg): return' would then skip printing the actual message in margs.

Fix by checking both msg and margs before returning. This ensures messages are still printed even when no prefix flags are set.

lib.log.log(): Fix superfluous message whitespace

When prefix flags (position, prio, date) are combined with message arguments, log() would double-space the output (e.g. ' Created') or omit the separator entirely (e.g. 'Created'). The root cause was that log() prepended a space to every argument, regardless of whether the prefix already ended with one.

Fix: only prepend a space before the first argument when the prefix doesn't already end with one. This produces exactly one separator between prefix and content regardless of which flags are active.

Also fix log_m(): skip empty strings (the sentinel '') so it doesn't contribute a space. And fix the early return that dropped messages when no prefix flags were set (previous commit).

lib.log.log(): Use .join() to build argument string

The argument string builder in log() previously iterated with enumerate and checked per-iteration whether to prepend a space. Replace the loop with ' '.join(str(a) for a in args), which is a single C-level operation.

Move the leading-space logic after the only_printable block so the regex transformations see the raw joined content.

lib.log.log(): Convert string-based flags to Flag

Replace the set of flag strings with a Flag enum for better type safety and bitwise operations. Add parse_flags() to convert comma-separated strings into a LogFlag value. Update set_flags() and set_log_flags() to accept str | LogFlag | None.

set_flags() and set_log_flags() don't return str anylonger which is a breaking change, but shouldn't be a problem because it's not used anywhere.

lib.App: Make default env var names overridable

Add default*_env() helper methods that return the environment variable names, and use them in init() instead of hard-coded strings. This allows subclasses to override the names.

lib.App: Make default log values overridable

The init() method reads default log configuration directly from environment variables, making it impossible for subclasses to change defaults.

Extract the defaults into _default_log_flags(), _default_log_level(), _default_log_file(), and _default_show_backtrace() methods, then call them from init(). Subclasses can now override these methods to customize defaults without needing to override the entire init() method.

This PR brings a number of fixes and improvments to logging via the lib.log.log() framework and the way lib.App uses it. It beautifies log output, modernizes the antique log flag handling, and gives more freedom to customize the default logging behaviour for classes inheriting lib.App. #### lib.log.log(): Fix early return without flags set When position, prio, and date are all absent from the log flags, the msg variable is empty. The early return 'if not len(msg): return' would then skip printing the actual message in margs. Fix by checking both msg and margs before returning. This ensures messages are still printed even when no prefix flags are set. #### lib.log.log(): Fix superfluous message whitespace When prefix flags (position, prio, date) are combined with message arguments, log() would double-space the output (e.g. '<N> Created') or omit the separator entirely (e.g. '<N>Created'). The root cause was that log() prepended a space to every argument, regardless of whether the prefix already ended with one. Fix: only prepend a space before the first argument when the prefix doesn't already end with one. This produces exactly one separator between prefix and content regardless of which flags are active. Also fix log_m(): skip empty strings (the sentinel '') so it doesn't contribute a space. And fix the early return that dropped messages when no prefix flags were set (previous commit). #### lib.log.log(): Use .join() to build argument string The argument string builder in log() previously iterated with enumerate and checked per-iteration whether to prepend a space. Replace the loop with ' '.join(str(a) for a in args), which is a single C-level operation. Move the leading-space logic after the only_printable block so the regex transformations see the raw joined content. #### lib.log.log(): Convert string-based flags to Flag Replace the set of flag strings with a Flag enum for better type safety and bitwise operations. Add parse_flags() to convert comma-separated strings into a LogFlag value. Update set_flags() and set_log_flags() to accept str | LogFlag | None. set_flags() and set_log_flags() don't return str anylonger which is a breaking change, but shouldn't be a problem because it's not used anywhere. #### lib.App: Make default env var names overridable Add _default_*_env() helper methods that return the environment variable names, and use them in __init__() instead of hard-coded strings. This allows subclasses to override the names. #### lib.App: Make default log values overridable The __init__() method reads default log configuration directly from environment variables, making it impossible for subclasses to change defaults. Extract the defaults into _default_log_flags(), _default_log_level(), _default_log_file(), and _default_show_backtrace() methods, then call them from __init__(). Subclasses can now override these methods to customize defaults without needing to override the entire __init__() method.
When position, prio, and date are all absent from the log flags, the
msg variable is empty. The early return 'if not len(msg): return'
would then skip printing the actual message in margs.

Fix by checking both msg and margs before returning. This ensures
messages are still printed even when no prefix flags are set.

Signed-off-by: Jan Lindemann <jan@janware.com>
When prefix flags (position, prio, date) are combined with message
arguments, log() would double-space the output (e.g. '<N>  Created')
or omit the separator entirely (e.g. '<N>Created'). The root cause
was that log() prepended a space to every argument, regardless of
whether the prefix already ended with one.

Fix: only prepend a space before the first argument when the prefix
doesn't already end with one. This produces exactly one separator
between prefix and content regardless of which flags are active.

Also fix log_m(): skip empty strings (the sentinel '') so it doesn't
contribute a space. And fix the early return that dropped messages
when no prefix flags were set (previous commit).

Signed-off-by: Jan Lindemann <jan@janware.com>
The argument string builder in log() previously iterated with
enumerate and checked per-iteration whether to prepend a space.
Replace the loop with ' '.join(str(a) for a in args), which is a
single C-level operation.

Move the leading-space logic after the only_printable block so the
regex transformations see the raw joined content.

Signed-off-by: Jan Lindemann <jan@janware.com>
Replace the set of flag strings with a Flag enum for better type
safety and bitwise operations. Add parse_flags() to convert
comma-separated strings into a LogFlag value. Update set_flags() and
set_log_flags() to accept str | LogFlag | None.

set_flags() and set_log_flags() don't return str anylonger which is a
breaking change, but shouldn't be a problem because it's not used
anywhere.

Signed-off-by: Jan Lindemann <jan@janware.com>
Add _default_*_env() helper methods that return the environment variable
names, and use them in __init__() instead of hard-coded strings. This
allows subclasses to override the names.

Signed-off-by: Jan Lindemann <jan@janware.com>
lib.App: Make default log values overridable
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m0s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m11s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 3m40s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 3m59s
CI / Packaging test (push) Successful in 0s
2eeaaf9681
The __init__() method reads default log configuration directly
from environment variables, making it impossible for subclasses to
change defaults.

Extract the defaults into _default_log_flags(), _default_log_level(),
_default_log_file(), and _default_show_backtrace() methods, then call
them from __init__(). Subclasses can now override these methods to
customize defaults without needing to override the entire __init__()
method.

Signed-off-by: Jan Lindemann <jan@janware.com>
Jan Lindemann scheduled this pull request to auto merge when all checks succeed 2026-08-10 20:26:43 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
janware/jw-pkg!55
No description provided.