Skip to content

Commit 323ddb1

Browse files
committed
add log files
1 parent e41b57f commit 323ddb1

1 file changed

Lines changed: 98 additions & 9 deletions

File tree

modlog_wiki_publisher.py

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import argparse
77
import json
88
import logging
9+
import logging.handlers
910
import re
1011
import sqlite3
1112
import sys
@@ -17,11 +18,18 @@
1718

1819
import praw
1920

20-
# Configure logging
21-
logging.basicConfig(
22-
level=logging.INFO,
23-
format='%(asctime)s - %(levelname)s - %(message)s'
24-
)
21+
# Global logger setup - will be enhanced with per-subreddit loggers
22+
root_logger = logging.getLogger()
23+
root_logger.setLevel(logging.INFO)
24+
25+
# Console handler for general output
26+
console_handler = logging.StreamHandler()
27+
console_handler.setLevel(logging.INFO)
28+
console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
29+
console_handler.setFormatter(console_formatter)
30+
root_logger.addHandler(console_handler)
31+
32+
# Main logger
2533
logger = logging.getLogger(__name__)
2634

2735

@@ -220,6 +228,8 @@ def __init__(self, config_path: str = "config.json", cli_args: Optional[argparse
220228
self.db = ModlogDatabase(retention_days=self.config.get('retention_days', 30))
221229
self.wiki_char_limit = 524288
222230
self.batch_size = self.config.get('batch_size', 100)
231+
self.subreddit_loggers = {}
232+
self._setup_subreddit_logging()
223233

224234
def _load_config(self, config_path: str, cli_args: argparse.Namespace) -> dict:
225235
"""Load JSON config, then override with CLI args"""
@@ -268,6 +278,54 @@ def _validate_config(self, config: dict) -> None:
268278
logger.warning("Unusual retention_days: %s, using 30", retention)
269279
config['retention_days'] = 30
270280

281+
def _setup_subreddit_logging(self):
282+
"""Setup per-subreddit logging with rotation"""
283+
# Create logs directory if it doesn't exist
284+
log_dir = Path(self.config.get('log_directory', 'logs'))
285+
log_dir.mkdir(exist_ok=True)
286+
287+
# Get subreddits to set up logging for
288+
subreddits = [self.config['source_subreddit']]
289+
if 'target_subreddit' in self.config and self.config['target_subreddit'] != self.config['source_subreddit']:
290+
subreddits.append(self.config['target_subreddit'])
291+
292+
for subreddit in subreddits:
293+
# Create logger for this subreddit
294+
sub_logger = logging.getLogger(f"modlog.{subreddit}")
295+
sub_logger.setLevel(logging.DEBUG) # Let handlers control level
296+
297+
# Prevent adding handlers multiple times
298+
if sub_logger.handlers:
299+
continue
300+
301+
# Create rotating file handler
302+
log_file = log_dir / f"{subreddit}_modlog.log"
303+
file_handler = logging.handlers.RotatingFileHandler(
304+
log_file,
305+
maxBytes=self.config.get('log_max_bytes', 10 * 1024 * 1024), # 10MB default
306+
backupCount=self.config.get('log_backup_count', 5), # Keep 5 backups
307+
encoding='utf-8'
308+
)
309+
310+
# Create formatter for subreddit logs
311+
file_formatter = logging.Formatter(
312+
'%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
313+
)
314+
file_handler.setFormatter(file_formatter)
315+
file_handler.setLevel(logging.DEBUG)
316+
317+
# Add handler to logger
318+
sub_logger.addHandler(file_handler)
319+
320+
# Store reference
321+
self.subreddit_loggers[subreddit] = sub_logger
322+
323+
logger.info("Setup logging for subreddit: %s -> %s", subreddit, log_file)
324+
325+
def get_subreddit_logger(self, subreddit: str) -> logging.Logger:
326+
"""Get logger for specific subreddit"""
327+
return self.subreddit_loggers.get(subreddit, logger)
328+
271329
def _init_reddit(self) -> praw.Reddit:
272330
"""Initialize Reddit API connection"""
273331
reddit_config = self.config['reddit']
@@ -543,15 +601,19 @@ def _process_modlog_entry(self, entry) -> Optional[Dict]:
543601
def fetch_modlog_entries(self, limit: int = 100) -> List[Dict]:
544602
"""Fetch and process modlog entries with rate limit handling"""
545603
subreddit = self.reddit.subreddit(self.config['source_subreddit'])
604+
sub_logger = self.get_subreddit_logger(self.config['source_subreddit'])
546605
entries = []
547606

607+
sub_logger.info("Starting to fetch modlog entries, limit: %s", limit)
548608
try:
549609
for entry in subreddit.mod.log(limit=limit):
550610
try:
551611
processed = self._process_modlog_entry(entry)
552612
if processed:
553613
processed['subreddit'] = subreddit.display_name
554614
entries.append(processed)
615+
sub_logger.debug("Processed entry: %s [%s] by %s",
616+
processed['id'], processed['action_type'], processed['moderator'])
555617
# Mark as processed
556618
self.db.mark_processed(
557619
processed['id'],
@@ -565,15 +627,17 @@ def fetch_modlog_entries(self, limit: int = 100) -> List[Dict]:
565627
import re
566628
match = re.search(r'(\d+) minute', str(e))
567629
wait_time = int(match.group(1)) * 60 if match else 60
568-
logger.warning("Rate limited, waiting %s seconds", wait_time)
630+
sub_logger.warning("Rate limited, waiting %s seconds", wait_time)
569631
time.sleep(wait_time)
570632
else:
571633
raise
572634

573635
# Sort by timestamp (newest first)
574636
entries.sort(key=lambda x: x['timestamp'], reverse=True)
637+
sub_logger.info("Successfully fetched %s modlog entries", len(entries))
575638

576639
except Exception as e:
640+
sub_logger.error("Error fetching modlog: %s", e)
577641
logger.error("Error fetching modlog: %s", e)
578642

579643
return entries
@@ -691,20 +755,27 @@ def generate_wiki_content(self, entries: List[Dict]) -> str:
691755

692756
def update_wiki(self, new_entries: List[Dict]) -> bool:
693757
"""Merge with existing wiki content and update"""
758+
target_sub = self.config['target_subreddit']
759+
sub_logger = self.get_subreddit_logger(target_sub)
760+
694761
try:
695-
subreddit = self.reddit.subreddit(self.config['target_subreddit'])
762+
subreddit = self.reddit.subreddit(target_sub)
696763
wiki_page = self.config.get('wiki_page', 'modlog')
764+
765+
sub_logger.info("Updating wiki page: /r/%s/wiki/%s", target_sub, wiki_page)
697766

698767
# Get current wiki content (for logging purposes)
699768
try:
700769
existing_content = subreddit.wiki[wiki_page].content_md
701-
logger.debug("Existing wiki content size: %s characters", len(existing_content))
770+
sub_logger.debug("Existing wiki content size: %s characters", len(existing_content))
702771
except Exception:
703-
logger.info("Wiki page doesn't exist yet, will create new")
772+
sub_logger.info("Wiki page doesn't exist yet, will create new")
704773

705774
# Only use DB entries; wiki parsing no longer needed
706775
cutoff = time.time() - self.config.get('retention_days', 30) * 86400
707776
retained = self.db.get_recent_entries(cutoff, subreddit=self.config['source_subreddit'])
777+
778+
sub_logger.debug("Retrieved %s entries from database for retention period", len(retained))
708779

709780
# Sort newest first
710781
retained.sort(key=lambda x: x['timestamp'], reverse=True)
@@ -717,22 +788,29 @@ def update_wiki(self, new_entries: List[Dict]) -> bool:
717788
content=content,
718789
reason="Rolling modlog update with retention"
719790
)
791+
sub_logger.info("Wiki page updated with %s entries, content size: %s chars", len(retained), len(content))
720792
logger.info("Wiki page updated with %s entries.", len(retained))
721793
return True
722794

723795
except praw.exceptions.APIException as e:
724796
if e.error_type == "RATELIMIT":
797+
sub_logger.error("Rate limited when updating wiki: %s", e)
725798
logger.error("Rate limited when updating wiki: %s", e)
726799
return False
727800
else:
728801
raise
729802
except Exception as e:
803+
sub_logger.error("Failed to update wiki: %s", e)
730804
logger.error("Failed to update wiki: %s", e)
731805
return False
732806

733807
def run_once(self):
734808
"""Run a single update cycle"""
809+
source_sub = self.config['source_subreddit']
810+
sub_logger = self.get_subreddit_logger(source_sub)
811+
735812
logger.info("Starting modlog update cycle...")
813+
sub_logger.info("=== Starting update cycle for /r/%s ===", source_sub)
736814

737815
# Cleanup old database entries
738816
self.db.cleanup_old_entries()
@@ -742,10 +820,14 @@ def run_once(self):
742820

743821
if entries:
744822
logger.info("Processing %s new modlog entries", len(entries))
823+
sub_logger.info("Processing %s new modlog entries", len(entries))
745824
# Update wiki with current database content
746825
self.update_wiki(entries)
747826
else:
748827
logger.info("No new modlog entries to process")
828+
sub_logger.info("No new modlog entries to process")
829+
830+
sub_logger.info("=== Completed update cycle for /r/%s ===", source_sub)
749831

750832
def run_continuous(self):
751833
"""Run continuously with interval"""
@@ -764,6 +846,13 @@ def run_continuous(self):
764846
def cleanup(self):
765847
"""Cleanup resources"""
766848
self.db.close()
849+
850+
# Close all subreddit loggers
851+
for subreddit, sub_logger in self.subreddit_loggers.items():
852+
for handler in sub_logger.handlers[:]:
853+
handler.close()
854+
sub_logger.removeHandler(handler)
855+
logger.debug("Closed logging for subreddit: %s", subreddit)
767856

768857

769858
def main():

0 commit comments

Comments
 (0)