From 089cded61b3b4e46b9a2605dbd5d61b284066503 Mon Sep 17 00:00:00 2001 From: Max Mehl Date: Wed, 12 Jun 2024 17:12:24 +0200 Subject: [PATCH] create total statistics about all domains --- recordmaster/_data.py | 50 +++++++++++++++++++++++++++++++++++++++++-- recordmaster/main.py | 10 +++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/recordmaster/_data.py b/recordmaster/_data.py index fb14bc0..b835cd1 100644 --- a/recordmaster/_data.py +++ b/recordmaster/_data.py @@ -63,9 +63,10 @@ def import_records(self, data: dict, domain: str = "", root: str = ""): @dataclass -class DomainStats: +class DomainStats: # pylint: disable=too-many-instance-attributes """Dataclass holding general statistics about the handling of a domain""" + domainname: str = "" total_remote: int = 0 updated: int = 0 added: int = 0 @@ -77,10 +78,11 @@ class DomainStats: def stats_calc(self, domainname: str) -> None: """Calculate the number of unchanged records based on updates and removals""" + self.domainname = domainname self.unchanged = self.total_remote - self.updated - self.deleted self.changed = self.updated + self.added + self.deleted - logging.info( + logging.debug( "[%s] Domain synchronised with %s changes: %s updated, %s added, %s deleted. " "%s ignored, %s unchanged", domainname, @@ -92,6 +94,50 @@ def stats_calc(self, domainname: str) -> None: self.unchanged, ) + def dc2dict(self) -> dict: + """Return dataclass as dict""" + return { + self.domainname: { + "changed": self.changed, + "updated": self.updated, + "added": self.added, + "deleted": self.deleted, + "ignored": self.ignored, + "unchanged": self.unchanged, + } + } + + +@dataclass +class DomainStatsSummary: + """Dataclass holding statistics about the handling of all domains""" + + stats: dict = field(default_factory=dict) + + def print_summary(self): + """Print summary of all stats""" + changed = [domain for domain, stats in self.stats.items() if stats.get("changed", -1) > 0] + + if not changed: + logging.info( + "SUMMARY: No changes were made in any of the %s handled domains", len(self.stats) + ) + else: + changestats = [] + for domain in changed: + stats = self.stats[domain] + changestats.append( + f"- {domain}: {stats['changed']} changes. {stats['updated']} updated, " + f"{stats['added']} added, {stats['deleted']} deleted. " + f"{stats['ignored']} ignored, {stats['unchanged']} unchanged" + ) + logging.info( + "SUMMARY: Changes were made in %s of the %s handled domains: \n%s", + len(changed), + len(self.stats), + "\n".join(changestats), + ) + @dataclass class Domain: diff --git a/recordmaster/main.py b/recordmaster/main.py index 0f11f25..fde5c3a 100644 --- a/recordmaster/main.py +++ b/recordmaster/main.py @@ -12,7 +12,7 @@ from . import DEFAULT_OPTIONS, __version__, configure_logger from ._api import api_login -from ._data import Domain, cache_data, convert_punycode +from ._data import Domain, DomainStatsSummary, cache_data, convert_punycode from ._get_records import ( check_local_records_config, combine_local_records, @@ -144,6 +144,9 @@ def sync( # Load domain records configuration files records_files = find_valid_local_records_files(dns_config) + # Create empty Stats Summary dataclass + statssummary = DomainStatsSummary() + # Normal procedure for domainname, records in combine_local_records(records_files).items(): # If `-d`/`--domain` given, skip all other domains @@ -226,8 +229,11 @@ def sync( len(unmatched_remote), ) - # Finally, show stats about this domain + # Finally, gather stats about this domain domain.stats.stats_calc(domain.name) + statssummary.stats.update(domain.stats.dc2dict()) + + statssummary.print_summary() def convert(