Fixing the double logging issue with a logging.filter
22 May 2025 10:22
I finally fixed a very annoying issue with frontmatter-check.
The problem
frontmatter-check currently has two levels:
WARN
- generates a warning if a frontmatter key is missingERROR
- generates an error instead
To break in this we actually have a few logging handlers:
- stdout - Pass Warnings to stdout
- stderr - Pass Errors to stderr
- MemoryHandler - pass Errors to MemoryHandler so that those errors can be used in frontmatter-check itself.
The problem here lived in stdout
. Logging operates on levels:
- 10 DEBUG
- 20 INFO
- 30 WARNING
- 40 ERROR
Any level higher than the level set will also show. This meant that ERROR
messages were appearing in both stdout and stderr which is why Errors would show twice.
❯ pre-commit try-repo ../frontmatter-check
[INFO] Initializing environment for ../frontmatter-check.
===============================================================================
Using config:
===============================================================================
repos:
- repo: ../frontmatter-check
rev: 258bcb39385a76ac54610121bf89abb04c9b904e
hooks:
- id: frontmatter-check
===============================================================================
[INFO] Installing environment for ../frontmatter-check.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
frontmatter check........................................................Failed
- hook id: frontmatter-check
- exit code: 1
Checking File: content/test-content-fm-check.md
ERROR - Missing field: 'description'
ERROR - Missing field: 'description'
ERROR - Missing field: 'date'
ERROR - Missing field: 'date'
The solution
I added a filter to the stdout_handler
.
class WarningOnlyFilter(logging.Filter):
def filter(self, record):
return record.levelno == logging.WARNING
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.WARNING)
stdout_handler.setFormatter(formatter)
stdout_handler.addFilter(WarningOnlyFilter())
This means that ONLY WARNING
messages will pass through stdout
.
Considerations
The only concern I have here is that if you are trying to specifically capture message you have to capture BOTH stdout
and stderr
.
You can see this change and more in PR #42.