ในยุคที่ระบบ AI API กลายเป็นหัวใจสำคัญของแอปพลิเคชันสมัยใหม่ การตรวจสอบบันทึกการเรียกใช้ API และการตรวจจับพฤติกรรมผิดปกติถือเป็นสิ่งจำเป็นอย่างยิ่งสำหรับทีมพัฒนาและ DevOps บทความนี้จะพาคุณสำรวจแนวทางการสร้างระบบ Audit Log ที่ครอบคลุม พร้อมโค้ดตัวอย่างที่พร้อมใช้งานจริง

ทำความเข้าใจ API Log Audit และ Anomaly Detection

การ audit log คือการบันทึกทุกการเรียกใช้ API อย่างเป็นระบบ โดยมีข้อมูลสำคัญดังนี้:

ส่วน Anomaly Detection คือการวิเคราะห์เพื่อหาความผิดปกติ เช่น:

การสร้างระบบ API Logging Middleware

เราจะเริ่มต้นด้วยการสร้าง middleware สำหรับบันทึก log ทุกคำขอ ซึ่งสามารถใช้งานร่วมกับ HolySheep AI ได้อย่างลงตัว

// api-logger-middleware.js
const fs = require('fs');
const path = require('path');

// การตั้งค่า Log Storage
const LOG_DIR = './api-logs';
const LOG_FILE = path.join(LOG_DIR, audit-${new Date().toISOString().split('T')[0]}.jsonl);

// สร้างโฟลเดอร์ถ้ายังไม่มี
if (!fs.existsSync(LOG_DIR)) {
    fs.mkdirSync(LOG_DIR, { recursive: true });
}

class APILogger {
    constructor(options = {}) {
        this.anomalyThresholds = {
            maxLatency: options.maxLatency || 5000, // ms
            maxTokensPerMinute: options.maxTokensPerMinute || 100000,
            maxRequestsPerMinute: options.maxRequestsPerMinute || 100,
            errorRateThreshold: options.errorRateThreshold || 0.1 // 10%
        };
        this.requestCounts = new Map(); // สำหรับ tracking rate
        this.errorCounts = new Map();
        this.latencies = [];
    }

    // บันทึก log ลงไฟล์
    logRequest(data) {
        const logEntry = {
            timestamp: new Date().toISOString(),
            requestId: data.requestId || this.generateRequestId(),
            method: data.method,
            endpoint: data.endpoint,
            statusCode: data.statusCode,
            latencyMs: data.latencyMs,
            tokenUsage: data.tokenUsage,
            clientIP: data.clientIP,
            userAgent: data.userAgent,
            requestBody: this.sanitizeBody(data.requestBody),
            responseBody: this.sanitizeBody(data.responseBody),
            error: data.error || null
        };

        fs.appendFileSync(LOG_FILE, JSON.stringify(logEntry) + '\n');
        return logEntry;
    }

    // ตรวจจับความผิดปกติ
    detectAnomalies(data) {
        const anomalies = [];
        const now = Date.now();
        const userKey = data.clientIP || 'unknown';

        // 1. ตรวจจับ Rate Limit Violation
        this.updateRateCount(userKey, now);
        if (this.requestCounts.get(userKey) > this.anomalyThresholds.maxRequestsPerMinute) {
            anomalies.push({
                type: 'RATE_LIMIT_EXCEEDED',
                severity: 'HIGH',
                message: User ${userKey} exceeded ${this.anomalyThresholds.maxRequestsPerMinute} req/min,
                count: this.requestCounts.get(userKey)
            });
        }

        // 2. ตรวจจับ Latency Spike
        if (data.latencyMs > this.anomalyThresholds.maxLatency) {
            anomalies.push({
                type: 'HIGH_LATENCY',
                severity: 'MEDIUM',
                message: Latency ${data.latencyMs}ms exceeds threshold ${this.anomalyThresholds.maxLatency}ms,
                latencyMs: data.latencyMs
            });
        }

        // 3. ตรวจจับ Error Rate สูง
        this.updateErrorCount(userKey);
        const errorRate = this.getErrorRate(userKey);
        if (errorRate > this.anomalyThresholds.errorRateThreshold) {
            anomalies.push({
                type: 'HIGH_ERROR_RATE',
                severity: 'HIGH',
                message: Error rate ${(errorRate * 100).toFixed(1)}% exceeds threshold,
                errorRate: errorRate
            });
        }

        // 4. ตรวจจับ Token Usage ผิดปกติ
        if (data.tokenUsage && data.tokenUsage.total > 8000) {
            anomalies.push({
                type: 'HIGH_TOKEN_USAGE',
                severity: 'LOW',
                message: Token usage ${data.tokenUsage.total} is unusually high,
                tokenUsage: data.tokenUsage
            });
        }

        return anomalies;
    }

    updateRateCount(userKey, now) {
        const windowMs = 60000; // 1 นาที
        const key = ${userKey}_${Math.floor(now / windowMs)};
        const count = (this.requestCounts.get(key) || 0) + 1;
        this.requestCounts.set(key, count);
        
        // Cleanup เก่า
        const cutoff = now - windowMs * 2;
        for (const [k] of this.requestCounts) {
            if (k.endsWith(Math.floor(cutoff / windowMs).toString())) {
                this.requestCounts.delete(k);
            }
        }
    }

    updateErrorCount(userKey) {
        const key = error_${userKey};
        this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
    }

    getErrorRate(userKey) {
        const rateKey = ${userKey}_${Math.floor(Date.now() / 60000)};
        const requestCount = this.requestCounts.get(rateKey) || 1;
        const errorCount = this.errorCounts.get(error_${userKey}) || 0;
        return errorCount / requestCount;
    }

    generateRequestId() {
        return req_${Date.now()}_${Math.random().toString(36).substr(2, 9)};
    }

    sanitizeBody(body) {
        if (!body) return null;
        const sanitized = { ...body };
        // ซ่อน sensitive fields
        const sensitiveKeys = ['password', 'api_key', 'token', 'secret', 'authorization'];
        for (const key of Object.keys(sanitized)) {
            if (sensitiveKeys.some(sk => key.toLowerCase().includes(sk))) {
                sanitized[key] = '***REDACTED***';
            }
        }
        return sanitized;
    }
}

module.exports = APILogger;

การใช้งานร่วมกับ HolySheep AI API

ด้านล่างคือตัวอย่างการใช้งาน API Logger ร่วมกับ HolySheep AI ซึ่งมีความหน่วงต่ำกว่า 50ms และราคาประหยัดกว่า 85%

// holysheep-api-client.js
const https = require('https');

class HolySheepAIClient {
    constructor(apiKey, logger) {
        this.baseUrl = 'https://api.holysheep.ai/v1';
        this.apiKey = apiKey;
        this.logger = logger;
    }

    async chatCompletion(messages, options = {}) {
        const requestId = hs_${Date.now()}_${Math.random().toString(36).substr(2, 9)};
        const startTime = Date.now();
        let statusCode = 200;
        let error = null;
        let response = null;

        try {
            const payload = {
                model: options.model || 'gpt-4.1',
                messages: messages,
                temperature: options.temperature || 0.7,
                max_tokens: options.maxTokens || 1000
            };

            const result = await this.makeRequest('/chat/completions', payload);
            response = result;

            // คำนวณ token usage จาก response
            const tokenUsage = {
                prompt: result.usage?.prompt_tokens || 0,
                completion: result.usage?.completion_tokens || 0,
                total: result.usage?.total_tokens || 0
            };

            // บันทึก log
            this.logger.logRequest({
                requestId,
                method: 'POST',
                endpoint: '/chat/completions',
                statusCode,
                latencyMs: Date.now() - startTime,
                tokenUsage,
                clientIP: this.getClientIP(),
                requestBody: payload,
                responseBody: response
            });

            // ตรวจจับความผิดปกติ
            const anomalies = this.logger.detectAnomalies({
                requestId,
                latencyMs: Date.now() - startTime,
                tokenUsage,
                statusCode,
                clientIP: this.getClientIP()
            });

            if (anomalies.length > 0) {
                console.warn([ALERT] Anomalies detected for ${requestId}:, anomalies);
            }

            return result;

        } catch (err) {
            error = err;
            statusCode = err.statusCode || 500;

            this.logger.logRequest({
                requestId,
                method: 'POST',
                endpoint: '/chat/completions',
                statusCode,
                latencyMs: Date.now() - startTime,
                clientIP: this.getClientIP(),
                error: {
                    message: err.message,
                    code: err.code
                }
            });

            throw err;
        }
    }

    makeRequest(endpoint, payload) {
        return new Promise((resolve, reject) => {
            const url = new URL(this.baseUrl + endpoint);
            
            const options = {
                hostname: url.hostname,
                port: 443,
                path: url.pathname,
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': Bearer ${this.apiKey}
                }
            };

            const req = https.request(options, (res) => {
                let data = '';
                res.on('data', chunk => data += chunk);
                res.on('end', () => {
                    try {
                        const parsed = JSON.parse(data);
                        if (res.statusCode >= 400) {
                            const error = new Error(parsed.error?.message || 'API Error');
                            error.statusCode = res.statusCode;
                            error.code = parsed.error?.code;
                            reject(error);
                        } else {
                            resolve(parsed);
                        }
                    } catch (e) {
                        reject(new Error('Failed to parse response'));
                    }
                });
            });

            req.on('error', reject);
            req.write(JSON.stringify(payload));
            req.end();
        });
    }

    getClientIP() {
        // ใน production ใช้ request headers จริงๆ
        return process.env.CLIENT_IP || '127.0.0.1';
    }
}

// ตัวอย่างการใช้งาน
const logger = new APILogger({
    maxLatency: 3000,
    maxRequestsPerMinute: 60,
    errorRateThreshold: 0.05
});

const client = new HolySheepAIClient('YOUR_HOLYSHEEP_API_KEY', logger);

async function testAPI() {
    try {
        const response = await client.chatCompletion([
            { role: 'user', content: 'สวัสดีครับ' }
        ], {
            model: 'gpt-4.1',
            maxTokens: 500
        });
        console.log('Response:', response.choices[0].message.content);
    } catch (err) {
        console.error('Error:', err.message);
    }
}

module.exports = { HolySheepAIClient, APILogger };

การวิเคราะห์ Log และรายงาน Anomaly

// anomaly-analyzer.js
const fs = require('fs');
const path = require('path');

class AnomalyAnalyzer {
    constructor(logDir = './api-logs') {
        this.logDir = logDir;
    }

    // วิเคราะห์ log ทั้งหมดในวัน
    async analyzeDay(dateStr = new Date().toISOString().split('T')[0]) {
        const logFile = path.join(this.logDir, audit-${dateStr}.jsonl);
        
        if (!fs.existsSync(logFile)) {
            console.log(Log file not found: ${logFile});
            return null;
        }

        const logs = this.parseLogs(logFile);
        const report = {
            date: dateStr,
            totalRequests: logs.length,
            uniqueClients: new Set(logs.map(l => l.clientIP)).size,
            metrics: this.calculateMetrics(logs),
            anomalies: this.detectAnomalies(logs),
            recommendations: []
        };

        report.recommendations = this.generateRecommendations(report);
        return report;
    }

    parseLogs(filePath) {
        const logs = [];
        const content = fs.readFileSync(filePath, 'utf8');
        const lines = content.split('\n').filter(l => l.trim());

        for (const line of lines) {
            try {
                logs.push(JSON.parse(line));
            } catch (e) {
                console.warn('Failed to parse log line:', line);
            }
        }
        return logs;
    }

    calculateMetrics(logs) {
        const metrics = {
            totalRequests: logs.length,
            successCount: logs.filter(l => l.statusCode >= 200 && l.statusCode < 300).length,
            errorCount: logs.filter(l => l.statusCode >= 400).length,
            avgLatency: 0,
            p95Latency: 0,
            p99Latency: 0,
            totalTokens: 0
        };

        const latencies = logs
            .filter(l => l.latencyMs)
            .map(l => l.latencyMs)
            .sort((a, b) => a - b);

        if (latencies.length > 0) {
            metrics.avgLatency = latencies.reduce((a, b) => a + b, 0) / latencies.length;
            metrics.p95Latency = latencies[Math.floor(latencies.length * 0.95)] || 0;
            metrics.p99Latency = latencies[Math.floor(latencies.length * 0.99)] || 0;
        }

        const tokenLogs = logs.filter(l => l.tokenUsage?.total);
        if (tokenLogs.length > 0) {
            metrics.totalTokens = tokenLogs.reduce((sum, l) => sum + l.tokenUsage.total, 0);
        }

        metrics.successRate = (metrics.successCount / metrics.totalRequests * 100).toFixed(2);
        metrics.errorRate = (metrics.errorCount / metrics.totalRequests * 100).toFixed(2);

        return metrics;
    }

    detectAnomalies(logs) {
        const anomalies = [];

        // 1. Burst Detection - คำขอที่มาพร้อมกันมาก
        const requestsBySecond = {};
        for (const log of logs) {
            const second = log.timestamp.split('.')[0];
            requestsBySecond[second] = (requestsBySecond[second] || 0) + 1;
        }
        for (const [second, count] of Object.entries(requestsBySecond)) {
            if (count > 50) {
                anomalies.push({
                    type: 'BURST_TRAFFIC',
                    severity: 'HIGH',
                    timestamp: second,
                    count,
                    description: ${count} requests at ${second}
                });
            }
        }

        // 2. Error Spike Detection
        const errorsByMinute = {};
        for (const log of logs) {
            if (log.statusCode >= 400) {
                const minute = log.timestamp.substring(0, 16);
                errorsByMinute[minute] = (errorsByMinute[minute] || 0) + 1;
            }
        }
        const avgErrors = logs.filter(l => l.statusCode >= 400).length / (Object.keys(errorsByMinute).length || 1);
        for (const [minute, count] of Object.entries(errorsByMinute)) {
            if (count > avgErrors * 3 && count > 10) {
                anomalies.push({
                    type: 'ERROR_SPIKE',
                    severity: 'CRITICAL',
                    timestamp: minute,
                    errorCount: count,
                    description: Error spike at ${minute}: ${count} errors
                });
            }
        }

        // 3. Latency Anomaly - ใช้ IQR method
        const latencies = logs.filter(l => l.latencyMs).map(l => l.latencyMs).sort((a, b) => a - b);
        if (latencies.length > 10) {
            const q1 = latencies[Math.floor(latencies.length * 0.25)];
            const q3 = latencies[Math.floor(latencies.length * 0.75)];
            const iqr = q3 - q1;
            const upperBound = q3 + 1.5 * iqr;
            
            const highLatencyLogs = logs.filter(l => l.latencyMs > upperBound);
            if (highLatencyLogs.length > 0) {
                anomalies.push({
                    type: 'HIGH_LATENCY',
                    severity: 'MEDIUM',
                    threshold: upperBound.toFixed(0),
                    affectedRequests: highLatencyLogs.length,
                    description: ${highLatencyLogs.length} requests exceeded ${upperBound.toFixed(0)}ms latency
                });
            }
        }

        return anomalies;
    }

    generateRecommendations(report) {
        const recommendations = [];

        if (report.metrics.errorRate > 5) {
            recommendations.push({
                priority: 'HIGH',
                action: 'ตรวจสอบ API errors เร่งด่วน - Error rate สูงกว่า 5%',
                metric: Error rate: ${report.metrics.errorRate}%
            });
        }

        if (report.metrics.p95Latency > 2000) {
            recommendations.push({
                priority: 'MEDIUM',
                action: 'พิจารณาเพิ่ม rate limiting หรือ scaling',
                metric: P95 latency: ${report.metrics.p95Latency.toFixed(0)}ms
            });
        }

        const criticalAnomalies = report.anomalies.filter(a => a.severity === 'CRITICAL');
        if (criticalAnomalies.length > 0) {
            recommendations.push({
                priority: 'CRITICAL',
                action: 'มี anomaly วิกฤติที่ต้องตรวจสอบทันที',
                count: criticalAnomalies.length
            });
        }

        return recommendations;
    }
}

// การใช้งาน
const analyzer = new AnomalyAnalyzer();

analyzer.analyzeDay().then(report => {
    console.log('\n=== API Audit Report ===');
    console.log(วันที่: ${report.date});
    console.log(\nสรุป Metrics:);
    console.log(- คำขอทั้งหมด: ${report.metrics.totalRequests});
    console.log(- Success Rate: ${report.metrics.successRate}%);
    console.log(- Average Latency: ${report.metrics.avgLatency.toFixed(0)}ms);
    console.log(- P95 Latency: ${report.metrics.p95Latency.toFixed(0)}ms);
    console.log(- Token Usage: ${report.metrics.totalTokens.toLocaleString()});

    console.log(\nพบ Anomalies: ${report.anomalies.length});
    report.anomalies.forEach(a => {
        console.log(  [${a.severity}] ${a.type}: ${a.description});
    });

    console.log(\nRecommendations:);
    report.recommendations.forEach(r => {
        console.log(  [${r.priority}] ${r.action});
    });
});

module.exports = AnomalyAnalyzer;

ตารางเปรียบเทียบ API Providers สำหรับ AI Monitoring

Criteria HolySheep AI OpenAI Anthropic
Base URL api.holysheep.ai/v1 api.openai.com/v1 api.anthropic.com
ความหน่วง (Latency) <50ms 100-300ms 150-400ms
ราคา GPT-4.1 / MTok $8 $15-60 N/A
ราคา Claude-4.5 / MTok $15 N/A $18-75
ราคา Gemini 2.5 / MTok $2.50 N/A N/A
ราคา DeepSeek V3.2 / MTok $0.42 N/A N/A
อัตราแลกเปลี่ยน ¥1=$1 (ประหยัด 85%+) USD USD
วิธีชำระเงิน WeChat/Alipay Credit Card Credit Card
เครดิตฟรี ✓ มีเมื่อลงทะเบียน $5 trial Limited
Uptime SLA 99.9% 99.9% 99.9%

เหมาะกับใคร / ไม่เหมาะกับใคร

✓ เหมาะกับ:

✗ ไม่เหมาะกับ:

ราคาและ ROI

จากการทดสอบจริงในสภาพแวดล้อม production ระบบ monitoring ของเราใช้งานร่วมกับ HolySheep AI และพบว่า:

ตัวอย่างการคำนวณ ROI:

ทำไมต้องเลือก HolySheep

  1. ประหยัด 85%+: อัตรา ¥1=$1 ทำให้ค่าใช้จ่ายต่ำกว่าผู้ให้บริการอื่นอย่างมาก
  2. ความหน่วงต่ำ: ต่ำกว่า 50ms เหมาะสำหรับ real-time applications
  3. รองรับหลาย Models: GPT-4.1, Claude 4.5, Gemini 2.5 Flash, DeepSeek V3.2
  4. ชำระเงินง่าย: WeChat และ Alipay รองรับผู้ใช้ในเอเชียโดยเฉพาะ
  5. เครดิตฟรี: ลงทะเบียนวันนี้รับเครดิตทดลองใช้งาน
  6. API Compatible: ใช้ OpenAI-compatible format ทำให้ย้ายระบบง่าย

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

กรณีที่ 1: Error 401 Unauthorized - Invalid API Key

สาเหตุ: API key ไม่ถูกต้องหรือหมดอายุ

// ❌ วิธีผิด - hardcode API key ในโค้ด
const client = new HolySheepAIClient('sk-xxxxx-xxx', logger);

// ✅ วิธีถูก - ใช้ Environment Variable
const apiKey = process.env.HOLYSHEEP_API_KEY;
if (!apiKey) {
    throw new Error('HOLYSHEEP_API_KEY environment variable is required');
}
const client = new HolySheepAIClient(apiKey, logger);

// ตรวจสอบ format ของ API key
// HolySheep API key ควรขึ้นต้นด้วย 'hs_' หรือ 'sk-hs-'
if (!apiKey.startsWith('hs_') && !apiKey.startsWith('sk-hs-')) {
    console.warn('API key format may be incorrect. Expected: hs_xxx or sk-hs-xxx');
}

แหล่งข้อมูลที่เกี่ยวข้อง

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