Refactor ghostscript error message deduplicating

This commit is contained in:
James R. Barlow
2023-09-24 20:22:04 -07:00
parent 8d12ecb798
commit 7018e2b247
2 changed files with 68 additions and 11 deletions
+29 -10
View File
@@ -42,6 +42,30 @@ COLOR_CONVERSION_STRATEGIES = frozenset(
log = logging.getLogger(__name__)
class DuplicateFilter(logging.Filter):
"""Filter out duplicate log messages."""
def __init__(self, logger: logging.Logger):
self.last: logging.LogRecord | None = None
self.count = 0
self.logger = logger
def filter(self, record):
if self.last and record.msg == self.last.msg:
self.count += 1
return False
else:
if self.count >= 1:
rep_msg = f"(previous message repeated {self.count} times)"
self.count = 0 # Avoid infinite recursion
self.logger.log(self.last.levelno, rep_msg)
self.last = record
return True
log.addFilter(DuplicateFilter(log))
# Ghostscript executable - gswin32c is not supported
GS = 'gswin64c' if os.name == 'nt' else 'gs'
@@ -252,14 +276,9 @@ def generate_pdfa(
# If there is an error we log the whole stderr, except for filtering
# duplicates.
if _gs_error_reported(stderr):
last_part = None
repcount = 0
# Ghostscript outputs the pattern **** Error: .... frequently.
# Occasionally the error message is spammed many times. We filter
# out duplicates of this message using the filter above. We use
# the **** pattern to split the stderr into parts.
for part in stderr.split('****'):
if part != last_part:
if repcount > 1:
log.error(f"(previous error message repeated {repcount} times)")
repcount = 0
log.error(part)
else:
repcount += 1
last_part = part
log.error(part)
+39 -1
View File
@@ -12,7 +12,7 @@ import pikepdf
import pytest
from PIL import Image, UnidentifiedImageError
from ocrmypdf._exec.ghostscript import rasterize_pdf
from ocrmypdf._exec.ghostscript import DuplicateFilter, rasterize_pdf
from ocrmypdf.exceptions import ExitCode
from ocrmypdf.helpers import Resolution
@@ -141,3 +141,41 @@ def test_rasterize_pdf_errors(resources, no_outpdf, caplog):
)
assert "this is an error" in caplog.text
assert "invalid page image file" in caplog.text
class TestDuplicateFilter:
@pytest.fixture(scope='class', autouse=True)
def duplicate_filter_logger(self):
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addFilter(DuplicateFilter(logger))
return logger
def test_filter_duplicate_messages(self, duplicate_filter_logger, caplog):
log = duplicate_filter_logger
log.error("test error message")
log.error("test error message")
log.error("test error message")
log.error("another error message")
log.error("another error message")
log.error("yet another error message")
assert len(caplog.records) == 5
assert caplog.records[0].msg == "test error message"
assert caplog.records[1].msg == "(previous message repeated 2 times)"
assert caplog.records[2].msg == "another error message"
assert caplog.records[3].msg == "(previous message repeated 1 times)"
assert caplog.records[4].msg == "yet another error message"
def test_filter_does_not_affect_unique_messages(
self, duplicate_filter_logger, caplog
):
log = duplicate_filter_logger
log.error("test error message")
log.error("another error message")
log.error("yet another error message")
assert len(caplog.records) == 3
assert caplog.records[0].msg == "test error message"
assert caplog.records[1].msg == "another error message"
assert caplog.records[2].msg == "yet another error message"