#!/usr/bin/env python3 """ CLI tool to check a log line against policy error patterns. """ import argparse import re import sys import yaml import os from .stress_policy.utils import load_policy def add_check_log_pattern_parser(subparsers): """Adds the parser for the 'check-log-pattern' command.""" parser = subparsers.add_parser( 'check-log-pattern', help='Check a log line against policy error patterns.', description='Checks a given log line against the fatal and tolerated error patterns defined in a policy file to determine how it would be classified.' ) parser.add_argument('--policy', required=True, help='Path to the YAML policy file.') parser.add_argument('--policy-name', help='Name of the policy to use from a multi-policy file.') parser.add_argument( '--policy-section', default='direct_docker_cli_policy', help="The top-level key in the policy where error patterns are defined (e.g., 'direct_docker_cli_policy'). Default: direct_docker_cli_policy" ) parser.add_argument('log_line', help='The log line to check.') def main_check_log_pattern(args): """Main logic for the 'check-log-pattern' command.""" policy = load_policy(args.policy, args.policy_name) if not policy: return 1 policy_section = policy.get(args.policy_section, {}) if not policy_section: print(f"Error: Policy section '{args.policy_section}' not found in the policy.", file=sys.stderr) return 1 fatal_patterns = policy_section.get('fatal_error_patterns', []) tolerated_patterns = policy_section.get('tolerated_error_patterns', []) print(f"--- Checking Log Line ---") print(f"Policy: {args.policy}" + (f" (name: {args.policy_name})" if args.policy_name else "")) print(f"Policy Section: {args.policy_section}") print(f"Log Line: '{args.log_line}'") print("-" * 25) # 1. Check for fatal patterns. These take precedence. for pattern in fatal_patterns: if re.search(pattern, args.log_line, re.IGNORECASE): print(f"Result: FATAL") print(f"Reason: Matched fatal pattern: '{pattern}'") return 0 # 2. Check for tolerated patterns. This is only relevant for lines that look like errors. # The logic in stress_policy_tool checks for 'ERROR:' before checking tolerated patterns. if 'ERROR:' in args.log_line: for pattern in tolerated_patterns: if re.search(pattern, args.log_line, re.IGNORECASE): print(f"Result: TOLERATED") print(f"Reason: Matched tolerated pattern: '{pattern}'") return 0 # 3. If it's an ERROR line and not tolerated, it's a failure. print(f"Result: FAILURE") print(f"Reason: Contains 'ERROR:' but did not match any tolerated patterns.") return 0 # 4. If it's not an error line and didn't match fatal, it's neutral. print(f"Result: NEUTRAL") print(f"Reason: Does not contain 'ERROR:' and did not match any fatal patterns.") return 0