SiamCafe.net Blog
Technology

WordPress WooCommerce Post-mortem Analysis

wordpress woocommerce post mortem analysis
WordPress WooCommerce Post-mortem Analysis | SiamCafe Blog
2025-12-06· อ. บอม — SiamCafe.net· 1,446 คำ

WordPress WooCommerce Post-mortem Analysis คืออะไร

WordPress WooCommerce เป็น e-commerce platform ยอดนิยมที่ขับเคลื่อนร้านค้าออนไลน์กว่า 5 ล้านเว็บไซต์ทั่วโลก Post-mortem Analysis คือกระบวนการวิเคราะห์หลังเกิดเหตุการณ์ (incident) เพื่อหา root cause ป้องกันไม่ให้เกิดซ้ำ สำหรับ WooCommerce incidents อาจรวมถึง site downtime, checkout failures, payment gateway errors, performance degradation และ security breaches บทความนี้อธิบายวิธีทำ post-mortem สำหรับ WooCommerce อย่างเป็นระบบ พร้อม Python tools สำหรับวิเคราะห์ logs และ metrics

Common WooCommerce Incidents

# woo_incidents.py — Common WooCommerce incidents
import json

class WooCommerceIncidents:
    INCIDENTS = {
        "checkout_failure": {
            "name": "Checkout Failure",
            "severity": "P1 — Critical",
            "symptoms": "ลูกค้าไม่สามารถชำระเงินได้ — abandoned carts เพิ่มขึ้นผิดปกติ",
            "common_causes": [
                "Payment gateway API down หรือ credentials expired",
                "SSL certificate expired — mixed content errors",
                "Plugin conflict — checkout JS errors",
                "WooCommerce session timeout — cart หาย",
            ],
        },
        "performance_degradation": {
            "name": "Performance Degradation",
            "severity": "P2 — High",
            "symptoms": "Page load > 5 วินาที, TTFB > 2 วินาที, conversion rate ลดลง",
            "common_causes": [
                "Database queries ช้า — ไม่มี index, autoload options bloated",
                "Plugin ทำ external API calls ทุก page load",
                "Image optimization ไม่ดี — ไม่มี lazy loading/WebP",
                "Hosting resources ไม่พอ — RAM, CPU spike",
            ],
        },
        "security_breach": {
            "name": "Security Breach",
            "severity": "P1 — Critical",
            "symptoms": "Malware injection, admin access unauthorized, customer data leak",
            "common_causes": [
                "Outdated WordPress/WooCommerce/plugins — known vulnerabilities",
                "Weak admin passwords — brute force attack",
                "Nulled/pirated themes/plugins — backdoors",
                "SQL injection ผ่าน vulnerable plugin",
            ],
        },
        "inventory_sync": {
            "name": "Inventory Sync Failure",
            "severity": "P2 — High",
            "symptoms": "Stock ไม่ตรง — overselling, out-of-stock แต่ยังขายได้",
            "common_causes": [
                "Webhook failures ระหว่าง WooCommerce กับ ERP/POS",
                "Race condition — หลาย orders พร้อมกัน",
                "Caching ทำให้ stock count เก่า",
                "API rate limiting จาก third-party systems",
            ],
        },
    }

    def show_incidents(self):
        print("=== Common WooCommerce Incidents ===\n")
        for key, inc in self.INCIDENTS.items():
            print(f"[{inc['severity']}] {inc['name']}")
            print(f"  Symptoms: {inc['symptoms']}")
            for cause in inc['common_causes'][:3]:
                print(f"    • {cause}")
            print()

incidents = WooCommerceIncidents()
incidents.show_incidents()

Post-mortem Process

# postmortem_process.py — WooCommerce post-mortem process
import json

class PostMortemProcess:
    STEPS = {
        "detect": {
            "name": "1. Detection & Alert",
            "actions": [
                "UptimeRobot/Pingdom: site availability monitoring",
                "WooCommerce Status Dashboard: checkout success rate",
                "Google Analytics Real-time: traffic drops",
                "Server monitoring: CPU, RAM, disk alerts",
            ],
        },
        "respond": {
            "name": "2. Incident Response",
            "actions": [
                "Acknowledge incident — notify team via Slack",
                "Assess severity — P1: checkout down, P2: slow, P3: minor",
                "Assign incident commander + communication lead",
                "Start incident timeline documentation",
            ],
        },
        "mitigate": {
            "name": "3. Mitigation",
            "actions": [
                "Enable maintenance mode ถ้าจำเป็น",
                "Rollback recent deployments (plugins/themes/core updates)",
                "Switch to backup payment gateway ถ้ามี",
                "Scale up hosting resources ถ้า traffic spike",
            ],
        },
        "investigate": {
            "name": "4. Root Cause Investigation",
            "actions": [
                "Check error logs: /wp-content/debug.log",
                "Check server logs: access.log, error.log",
                "Check database: slow query log, table sizes",
                "Check recent changes: plugin updates, code deployments",
                "Reproduce issue in staging environment",
            ],
        },
        "resolve": {
            "name": "5. Resolution",
            "actions": [
                "Apply fix (code change, config update, plugin patch)",
                "Test fix in staging first",
                "Deploy to production",
                "Verify fix — checkout test, monitoring green",
            ],
        },
        "document": {
            "name": "6. Post-mortem Document",
            "actions": [
                "Write timeline of events",
                "Document root cause + contributing factors",
                "List action items with owners + deadlines",
                "Share with team — blameless culture",
            ],
        },
    }

    def show_process(self):
        print("=== Post-mortem Process ===\n")
        for key, step in self.STEPS.items():
            print(f"[{step['name']}]")
            for action in step['actions'][:3]:
                print(f"  • {action}")
            print()

process = PostMortemProcess()
process.show_process()

Python Log Analyzer

# log_analyzer.py — WooCommerce log analysis
import json

class WooLogAnalyzer:
    CODE = """
# woo_log_analyzer.py — Analyze WooCommerce logs for post-mortem
import re
import json
from collections import Counter
from datetime import datetime, timedelta

class WooCommerceLogAnalyzer:
    def __init__(self, debug_log_path="/var/www/html/wp-content/debug.log"):
        self.log_path = debug_log_path
        self.entries = []
    
    def parse_log(self):
        '''Parse WordPress debug.log'''
        with open(self.log_path) as f:
            current_entry = None
            for line in f:
                # Match: [DD-Mon-YYYY HH:MM:SS UTC] PHP type: message
                match = re.match(
                    r'\\[(\\d{2}-\\w{3}-\\d{4} \\d{2}:\\d{2}:\\d{2} \\w+)\\] (.+)',
                    line
                )
                if match:
                    if current_entry:
                        self.entries.append(current_entry)
                    
                    timestamp_str = match.group(1)
                    message = match.group(2)
                    
                    current_entry = {
                        'timestamp': timestamp_str,
                        'message': message,
                        'type': 'error' if 'Fatal' in message or 'Error' in message else
                                'warning' if 'Warning' in message else
                                'notice' if 'Notice' in message else 'info',
                    }
                elif current_entry:
                    current_entry['message'] += '\\n' + line.strip()
            
            if current_entry:
                self.entries.append(current_entry)
        
        return len(self.entries)
    
    def errors_by_type(self):
        '''Count errors by type'''
        return Counter(e['type'] for e in self.entries)
    
    def errors_by_plugin(self):
        '''Identify which plugins cause errors'''
        plugin_errors = Counter()
        for entry in self.entries:
            match = re.search(r'/plugins/([\\w-]+)/', entry['message'])
            if match:
                plugin_errors[match.group(1)] += 1
        return plugin_errors.most_common(10)
    
    def checkout_errors(self):
        '''Find checkout-related errors'''
        keywords = ['checkout', 'payment', 'wc_gateway', 'order', 'cart']
        return [e for e in self.entries
                if any(kw in e['message'].lower() for kw in keywords)]
    
    def errors_in_window(self, hours=24):
        '''Get errors within time window'''
        # Filter by timestamp (simplified)
        return [e for e in self.entries if e['type'] in ('error', 'warning')]
    
    def generate_report(self):
        '''Generate post-mortem log report'''
        total = len(self.entries)
        by_type = self.errors_by_type()
        by_plugin = self.errors_by_plugin()
        checkout = self.checkout_errors()
        
        return {
            'total_entries': total,
            'by_type': dict(by_type),
            'top_plugins': by_plugin[:5],
            'checkout_errors': len(checkout),
            'sample_errors': [e['message'][:100] for e in self.entries[:5]],
        }

# analyzer = WooCommerceLogAnalyzer('/path/to/debug.log')
# analyzer.parse_log()
# report = analyzer.generate_report()
# print(json.dumps(report, indent=2))
"""

    def show_code(self):
        print("=== Log Analyzer ===")
        print(self.CODE[:600])

analyzer = WooLogAnalyzer()
analyzer.show_code()

Database Health Check

# db_health.py — WooCommerce database health check
import json
import random

class DBHealthCheck:
    CODE = """
# woo_db_health.py — Database health check for WooCommerce
import mysql.connector
import json

class WooDatabaseHealth:
    def __init__(self, host, user, password, database):
        self.conn = mysql.connector.connect(
            host=host, user=user, password=password, database=database
        )
        self.cursor = self.conn.cursor(dictionary=True)
    
    def check_table_sizes(self):
        '''Check database table sizes'''
        self.cursor.execute('''
            SELECT table_name,
                   ROUND(data_length / 1024 / 1024, 2) AS data_mb,
                   ROUND(index_length / 1024 / 1024, 2) AS index_mb,
                   table_rows
            FROM information_schema.tables
            WHERE table_schema = DATABASE()
            ORDER BY data_length DESC
            LIMIT 20
        ''')
        return self.cursor.fetchall()
    
    def check_autoloaded_options(self):
        '''Check bloated autoloaded options'''
        self.cursor.execute('''
            SELECT option_name,
                   LENGTH(option_value) AS size_bytes,
                   ROUND(LENGTH(option_value) / 1024, 1) AS size_kb
            FROM wp_options
            WHERE autoload = 'yes'
            ORDER BY LENGTH(option_value) DESC
            LIMIT 20
        ''')
        return self.cursor.fetchall()
    
    def check_transients(self):
        '''Check expired transients'''
        self.cursor.execute('''
            SELECT COUNT(*) AS expired_transients
            FROM wp_options
            WHERE option_name LIKE '_transient_timeout_%'
            AND option_value < UNIX_TIMESTAMP()
        ''')
        return self.cursor.fetchone()
    
    def check_post_revisions(self):
        '''Check post revisions bloat'''
        self.cursor.execute('''
            SELECT post_type, COUNT(*) AS count
            FROM wp_posts
            WHERE post_type = 'revision'
            OR post_status = 'auto-draft'
        ''')
        return self.cursor.fetchall()
    
    def check_slow_queries(self):
        '''Check for slow queries'''
        self.cursor.execute("SHOW VARIABLES LIKE 'slow_query_log'")
        status = self.cursor.fetchone()
        
        self.cursor.execute("SHOW VARIABLES LIKE 'long_query_time'")
        threshold = self.cursor.fetchone()
        
        return {"slow_log": status, "threshold": threshold}
    
    def optimize_tables(self):
        '''Optimize WooCommerce tables'''
        tables = [
            'wp_posts', 'wp_postmeta', 'wp_options',
            'wp_woocommerce_sessions', 'wp_woocommerce_order_items',
        ]
        results = []
        for table in tables:
            self.cursor.execute(f"OPTIMIZE TABLE {table}")
            results.append(self.cursor.fetchone())
        return results
    
    def full_health_check(self):
        return {
            'table_sizes': self.check_table_sizes()[:5],
            'autoloaded_options': self.check_autoloaded_options()[:5],
            'expired_transients': self.check_transients(),
            'slow_queries': self.check_slow_queries(),
        }

# health = WooDatabaseHealth('localhost', 'root', 'password', 'wordpress')
# report = health.full_health_check()
"""

    def show_code(self):
        print("=== DB Health Check ===")
        print(self.CODE[:600])

    def sample_report(self):
        print(f"\n=== DB Health Report ===")
        print(f"  wp_posts: {random.randint(50, 500)}MB ({random.randint(5000, 50000)} rows)")
        print(f"  wp_postmeta: {random.randint(100, 800)}MB ({random.randint(100000, 1000000)} rows)")
        print(f"  wp_options: {random.randint(10, 100)}MB (autoload: {random.randint(5, 30)}MB)")
        print(f"  Expired transients: {random.randint(100, 5000)}")
        print(f"  Post revisions: {random.randint(1000, 20000)}")
        print(f"  Slow queries (24h): {random.randint(0, 50)}")

db = DBHealthCheck()
db.show_code()
db.sample_report()

Prevention & Monitoring

# prevention.py — Prevent WooCommerce incidents
import json

class Prevention:
    MONITORING = {
        "uptime": {
            "name": "Uptime Monitoring",
            "tools": ["UptimeRobot (free)", "Better Uptime", "Pingdom"],
            "check": "HTTP check ทุก 1-5 นาที + checkout page monitoring",
        },
        "performance": {
            "name": "Performance Monitoring",
            "tools": ["Query Monitor plugin", "New Relic", "Google PageSpeed"],
            "check": "TTFB < 500ms, page load < 3s, Core Web Vitals",
        },
        "security": {
            "name": "Security Monitoring",
            "tools": ["Wordfence", "Sucuri", "WP Activity Log"],
            "check": "Failed login attempts, file changes, malware scan",
        },
        "orders": {
            "name": "Order Monitoring",
            "tools": ["WooCommerce Analytics", "Custom dashboard", "Slack alerts"],
            "check": "Checkout success rate, payment failures, abandoned carts",
        },
    }

    BEST_PRACTICES = [
        "อัพเดท WordPress, WooCommerce, plugins ทุกสัปดาห์",
        "Staging environment — ทดสอบก่อน deploy production",
        "Automated backups ทุกวัน — UpdraftPlus, BlogVault",
        "Security headers + WAF (Cloudflare, Sucuri)",
        "Database optimization ทุกสัปดาห์ — WP-Optimize plugin",
        "CDN สำหรับ static assets — Cloudflare, BunnyCDN",
        "Object caching — Redis/Memcached",
        "Incident response playbook — ทุกู้คืนในทีมรู้ว่าต้องทำอะไร",
    ]

    def show_monitoring(self):
        print("=== Monitoring Setup ===\n")
        for key, mon in self.MONITORING.items():
            print(f"[{mon['name']}]")
            print(f"  Tools: {', '.join(mon['tools'])}")
            print(f"  Check: {mon['check']}")
            print()

    def show_practices(self):
        print("=== Best Practices ===")
        for bp in self.BEST_PRACTICES[:5]:
            print(f"  • {bp}")

prev = Prevention()
prev.show_monitoring()
prev.show_practices()

FAQ - คำถามที่พบบ่อย

Q: Post-mortem ควรทำเมื่อไหร่?

A: ทุก P1/P2 incident: ภายใน 48 ชั่วโมงหลัง resolution P3 (recurring): ถ้าเกิดซ้ำ 3+ ครั้ง Near-miss: เกือบเกิดปัญหา — ทำ mini post-mortem สำคัญ: blameless culture — โฟกัสที่ process ไม่ใช่คน เก็บ post-mortem documents ใน wiki/Notion — เรียนรู้จากอดีต

Q: debug.log เปิดใช้งานยังไง?

A: เพิ่มใน wp-config.php: define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); Log จะอยู่ที่: /wp-content/debug.log สำคัญ: อย่าเปิด WP_DEBUG_DISPLAY บน production — แสดง errors ให้ users เห็น ปิดหลังจาก debug เสร็จ — log file จะโตเรื่อยๆ

Q: WooCommerce checkout ล่มบ่อย แก้ยังไง?

A: สาเหตุส่วนใหญ่: Plugin conflict: ปิด plugins ทีละตัว → หา conflict JavaScript errors: เปิด browser console ดู errors Payment gateway: ตรวจ API keys, SSL, webhook URLs Session issues: เพิ่ม session timeout, ใช้ Redis สำหรับ sessions Caching: exclude checkout/cart pages จาก cache ทุกครั้ง ป้องกัน: มี backup payment gateway, monitoring checkout success rate

Q: Database optimization ทำบ่อยแค่ไหน?

A: อย่างน้อยสัปดาห์ละครั้ง: ลบ transients, revisions, auto-drafts, spam comments OPTIMIZE TABLE สำหรับ fragmented tables ใช้ WP-Optimize plugin ตั้ง schedule อัตโนมัติ สำหรับ high-traffic stores: พิจารณา separate database server + read replicas wp_postmeta table มักเป็น bottleneck — ใช้ custom tables สำหรับ WooCommerce orders (HPOS)

📖 บทความที่เกี่ยวข้อง

Mintlify Docs Post-mortem Analysisอ่านบทความ → Apache Kafka Streams Post-mortem Analysisอ่านบทความ → Strapi CMS Post-mortem Analysisอ่านบทความ → LLM Inference vLLM Post-mortem Analysisอ่านบทความ → HashiCorp Vault Secrets Post-mortem Analysisอ่านบทความ →

📚 ดูบทความทั้งหมด →