Mở đầu: Vấn đề thực tế khiến team DevOps mất ngủ
Tuần trước, một team backend 12 người tại công ty thương mại điện tử của tôi gặp tình huống cấp bách: chi phí API AI tăng 340% chỉ trong 2 tháng. Họ sử dụng đồng thời Claude Code cho code generation, Cursor cho pair programming, và Cline cho automation script. Không ai biết tiền đi đâu — không có hệ thống theo dõi tập trung, không có phân tích chi tiết theo repository.
Tôi đã xây dựng một giải pháp monitoring hoàn chỉnh với HolySheep API, và kết quả khiến cả team bất ngờ: 60% chi phí đến từ 2 repository "bí ẩn" với prompt không tối ưu, có thể tiết kiệm ngay 45% chi phí hàng tháng.
Bài viết này là blueprint đầy đủ để bạn làm điều tương tự.
Tại sao cần theo dõi token theo repository?
Khi sử dụng nhiều công cụ AI trong development workflow, việc theo dõi tổng chi phí là không đủ. Bạn cần biết:
- Repository nào tiêu tốn nhiều nhất? — Để xác định prompt có vấn đề
- Model nào được sử dụng trong từng tool? — Để tối ưu hóa lựa chọn model
- Xu hướng chi phí theo thời gian? — Để dự báo và ngân sách
- So sánh hiệu suất chi phí giữa các team? — Để định hướng best practices
Kiến trúc hệ thống Monitoring
Hệ thống gồm 3 thành phần chính:
- Data Collector: Ghi lại mọi API request từ Claude Code, Cursor, Cline
- Aggregation Engine: Tổng hợp theo repository, model, thời gian
- Dashboard/Report: Trực quan hóa dữ liệu
Triển khai Data Collector
Collector này được đặt giữa client và API endpoint để intercept mọi request. Với HolySheep, chúng ta sử dụng proxy pattern:
#!/usr/bin/env python3
"""
HolySheep Token Monitor - Data Collector
Theo dõi chi phí token theo repository cho Claude Code, Cursor, Cline
"""
import json
import sqlite3
import time
import hashlib
from datetime import datetime, timezone
from dataclasses import dataclass, asdict
from typing import Optional
import threading
Cấu hình HolySheep
HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1"
HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Thay thế bằng API key của bạn
@dataclass
class TokenUsageRecord:
"""Bản ghi sử dụng token"""
timestamp: str
repository: str
tool: str # claude_code, cursor, cline
model: str
input_tokens: int
output_tokens: int
cost_usd: float
request_id: str
response_time_ms: int
status: str
class TokenMonitor:
"""Monitor theo dõi token usage với SQLite backend"""
def __init__(self, db_path: str = "token_usage.db"):
self.db_path = db_path
self._lock = threading.Lock()
self._init_database()
def _init_database(self):
"""Khởi tạo schema database"""
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS token_usage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
repository TEXT NOT NULL,
tool TEXT NOT NULL,
model TEXT NOT NULL,
input_tokens INTEGER,
output_tokens INTEGER,
cost_usd REAL,
request_id TEXT UNIQUE,
response_time_ms INTEGER,
status TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
""")
# Index để query nhanh
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_repo_timestamp
ON token_usage(repository, timestamp)
""")
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_tool_timestamp
ON token_usage(tool, timestamp)
""")
conn.commit()
def extract_repo_from_path(self, file_path: str) -> str:
"""Trích xuất repository name từ file path"""
if not file_path:
return "unknown"
# Common patterns
parts = file_path.replace("\\", "/").split("/")
# /workspace/project-name/...
if "workspace" in parts:
idx = parts.index("workspace")
if idx + 1 < len(parts):
return parts[idx + 1]
# /home/user/projects/project-name/...
if "projects" in parts:
idx = parts.index("projects")
if idx + 1 < len(parts):
return parts[idx + 1]
# Git remote pattern
if ".git" in file_path:
for part in reversed(parts):
if part and part != ".git":
return part
return parts[-1] if parts else "unknown"
def calculate_cost(self, model: str, input_tokens: int, output_tokens: int) -> float:
"""Tính chi phí theo model (HolySheep pricing 2026)"""
pricing = {
# Claude models
"claude-sonnet-4-5": {"input": 3.75, "output": 15.0},
"claude-opus-4": {"input": 15.0, "output": 75.0},
"claude-3-5-sonnet": {"input": 3.0, "output": 15.0},
# GPT models
"gpt-4.1": {"input": 2.0, "output": 8.0},
"gpt-4-turbo": {"input": 10.0, "output": 30.0},
# Cost-effective options
"gpt-4.1-mini": {"input": 0.50, "output": 2.0},
"claude-3-5-haiku": {"input": 0.80, "output": 4.0},
# DeepSeek - cực rẻ
"deepseek-v3.2": {"input": 0.07, "output": 0.42},
"deepseek-chat": {"input": 0.14, "output": 0.28},
}
# Default pricing nếu model không có trong list
p = pricing.get(model.lower(), {"input": 1.5, "output": 5.0})
input_cost = (input_tokens / 1_000_000) * p["input"]
output_cost = (output_tokens / 1_000_000) * p["output"]
return round(input_cost + output_cost, 6)
def record_usage(
self,
repository: str,
tool: str,
model: str,
input_tokens: int,
output_tokens: int,
response_time_ms: int,
status: str = "success"
) -> TokenUsageRecord:
"""Ghi lại một bản ghi usage"""
record = TokenUsageRecord(
timestamp=datetime.now(timezone.utc).isoformat(),
repository=repository,
tool=tool,
model=model,
input_tokens=input_tokens,
output_tokens=output_tokens,
cost_usd=self.calculate_cost(model, input_tokens, output_tokens),
request_id=hashlib.md5(
f"{repository}{time.time()}".encode()
).hexdigest()[:16],
response_time_ms=response_time_ms,
status=status
)
with self._lock:
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
INSERT OR IGNORE INTO token_usage
(timestamp, repository, tool, model, input_tokens,
output_tokens, cost_usd, request_id, response_time_ms, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
record.timestamp, record.repository, record.tool,
record.model, record.input_tokens, record.output_tokens,
record.cost_usd, record.request_id, record.response_time_ms,
record.status
))
conn.commit()
return record
Khởi tạo monitor toàn cục
monitor = TokenMonitor()
Ví dụ sử dụng
if __name__ == "__main__":
# Test với dữ liệu mẫu
test_record = monitor.record_usage(
repository="ecommerce-backend",
tool="claude_code",
model="claude-sonnet-4-5",
input_tokens=150000,
output_tokens=45000,
response_time_ms=1200
)
print(f"✅ Đã ghi: {test_record.repository}")
print(f" Tool: {test_record.tool}")
print(f" Chi phí: ${test_record.cost_usd:.4f}")
print(f" Request ID: {test_record.request_id}")
Webhook Integration cho Claude Code, Cursor, Cline
Mỗi tool có cách khác nhau để hook vào workflow. Dưới đây là cách configure cho từng tool:
# HolySheep Token Monitor - Tool Integration Configuration
Cấu hình webhook/endpoint cho từng AI coding tool
============================================
1. CLAUDE CODE INTEGRATION
============================================
Claude Code sử dụng biến môi trường ANTHROPIC_API_KEY
Chúng ta cần redirect qua proxy
Cấu hình .env cho Claude Code
CLAUDE_CODE_ENV="""
Sử dụng HolySheep thay vì Anthropic trực tiếp
ANTHROPIC_API_KEY=YOUR_HOLYSHEEP_API_KEY
ANTHROPIC_BASE_URL=https://api.holysheep.ai/v1
Log chi tiết
CLAUDE_CODE_LOG_FILE=./logs/claude-usage.jsonl
"""
============================================
2. CURSOR INTEGRATION
============================================
Cursor sử dụng custom API endpoint trong settings
CURSOR_SETTINGS_JSON = {
"api": {
"provider": "custom",
"baseUrl": "https://api.holysheep.ai/v1",
"apiKey": "YOUR_HOLYSHEEP_API_KEY",
"model": "claude-sonnet-4-5"
},
"features": {
"usageTracking": true,
"logFile": "./logs/cursor-usage.jsonl"
}
}
============================================
3. CLINE INTEGRATION
============================================
Cline hỗ trợ custom base URL
CLINE_ENV="""
Cline environment variables
ANTHROPIC_BASE_URL=https://api.holysheep.ai/v1
ANTHROPIC_API_KEY=YOUR_HOLYSHEEP_API_KEY
Cline specific
CLINE_USAGE_LOG=./logs/cline-usage.jsonl
CLINE_MAX_TOKENS=4096
"""
============================================
4. UNIFIED LOG PARSER
============================================
"""
Parser này đọc log files từ cả 3 tools và đẩy vào database
"""
import json
import re
from pathlib import Path
from token_monitor import monitor
def parse_claude_code_log(log_file: str) -> list:
"""Parse Claude Code usage log"""
records = []
with open(log_file, 'r') as f:
for line in f:
try:
data = json.loads(line.strip())
# Extract tokens từ response headers hoặc body
usage = data.get('usage', {})
record = monitor.record_usage(
repository=monitor.extract_repo_from_path(
data.get('file_path', '')
),
tool='claude_code',
model=data.get('model', 'claude-sonnet-4-5'),
input_tokens=usage.get('input_tokens', 0),
output_tokens=usage.get('output_tokens', 0),
response_time_ms=data.get('latency_ms', 0)
)
records.append(record)
except json.JSONDecodeError:
continue
return records
def parse_cursor_log(log_file: str) -> list:
"""Parse Cursor usage log"""
records = []
with open(log_file, 'r') as f:
for line in f:
try:
data = json.loads(line.strip())
record = monitor.record_usage(
repository=data.get('workspace', 'unknown'),
tool='cursor',
model=data.get('model', 'gpt-4.1'),
input_tokens=data.get('inputTokens', 0),
output_tokens=data.get('outputTokens', 0),
response_time_ms=data.get('responseTime', 0)
)
records.append(record)
except json.JSONDecodeError:
continue
return records
def parse_cline_log(log_file: str) -> list:
"""Parse Cline usage log"""
records = []
with open(log_file, 'r') as f:
for line in f:
try:
data = json.loads(line.strip())
# Cline format: {"task": "...", "input": "...", "output": "..."}
# Estimate tokens (Cline không always log exact)
input_text = data.get('input', '')
output_text = data.get('output', '')
# Rough estimation: 1 token ≈ 4 chars
input_tokens = len(input_text) // 4
output_tokens = len(output_text) // 4
record = monitor.record_usage(
repository=data.get('project', 'unknown'),
tool='cline',
model=data.get('model', 'deepseek-chat'),
input_tokens=input_tokens,
output_tokens=output_tokens,
response_time_ms=data.get('duration', 0)
)
records.append(record)
except json.JSONDecodeError:
continue
return records
def sync_all_logs(log_dir: str = "./logs"):
"""Sync tất cả logs vào database"""
log_path = Path(log_dir)
all_records = []
# Claude Code
claude_logs = list(log_path.glob("claude-*.jsonl"))
for log_file in claude_logs:
all_records.extend(parse_claude_code_log(str(log_file)))
# Cursor
cursor_logs = list(log_path.glob("cursor-*.jsonl"))
for log_file in cursor_logs:
all_records.extend(parse_cursor_log(str(log_file)))
# Cline
cline_logs = list(log_path.glob("cline-*.jsonl"))
for log_file in cline_logs:
all_records.extend(parse_cline_log(str(log_file)))
print(f"✅ Đã sync {len(all_records)} bản ghi vào database")
return all_records
if __name__ == "__main__":
sync_all_logs()
Dashboard và Báo cáo Analytics
Bây giờ chúng ta có dữ liệu, hãy tạo dashboard để trực quan hóa:
#!/usr/bin/env python3
"""
HolySheep Token Analytics Dashboard
Trực quan hóa chi phí AI theo repository, tool, và thời gian
"""
import sqlite3
from datetime import datetime, timedelta
from typing import Dict, List, Tuple
from tabulate import tabulate
class TokenAnalytics:
"""Analytics engine cho token usage"""
def __init__(self, db_path: str = "token_usage.db"):
self.db_path = db_path
def get_cost_by_repository(
self,
days: int = 30,
tool: str = None
) -> List[Dict]:
"""Lấy chi phí theo repository"""
query = """
SELECT
repository,
tool,
COUNT(*) as request_count,
SUM(input_tokens) as total_input,
SUM(output_tokens) as total_output,
SUM(cost_usd) as total_cost,
AVG(response_time_ms) as avg_latency
FROM token_usage
WHERE timestamp >= datetime('now', '-' || ? || ' days')
"""
params = [days]
if tool:
query += " AND tool = ?"
params.append(tool)
query += """
GROUP BY repository, tool
ORDER BY total_cost DESC
"""
with sqlite3.connect(self.db_path) as conn:
conn.row_factory = sqlite3.Row
cursor = conn.execute(query, params)
return [dict(row) for row in cursor.fetchall()]
def get_cost_by_model(
self,
days: int = 30
) -> List[Dict]:
"""Lấy chi phí theo model"""
query = """
SELECT
model,
tool,
COUNT(*) as request_count,
SUM(input_tokens) as total_input,
SUM(output_tokens) as total_output,
SUM(cost_usd) as total_cost,
MIN(cost_usd) as min_cost,
MAX(cost_usd) as max_cost,
AVG(cost_usd) as avg_cost
FROM token_usage
WHERE timestamp >= datetime('now', '-' || ? || ' days')
GROUP BY model
ORDER BY total_cost DESC
"""
with sqlite3.connect(self.db_path) as conn:
conn.row_factory = sqlite3.Row
cursor = conn.execute(query, [days])
return [dict(row) for row in cursor.fetchall()]
def get_daily_trend(
self,
repository: str = None,
days: int = 30
) -> List[Dict]:
"""Lấy xu hướng chi phí theo ngày"""
query = """
SELECT
DATE(timestamp) as date,
repository,
SUM(cost_usd) as daily_cost,
SUM(input_tokens) as daily_input,
SUM(output_tokens) as daily_output,
COUNT(*) as daily_requests
FROM token_usage
WHERE timestamp >= datetime('now', '-' || ? || ' days')
"""
params = [days]
if repository:
query += " AND repository = ?"
params.append(repository)
query += """
GROUP BY DATE(timestamp), repository
ORDER BY date ASC
"""
with sqlite3.connect(self.db_path) as conn:
conn.row_factory = sqlite3.Row
cursor = conn.execute(query, params)
return [dict(row) for row in cursor.fetchall()]
def get_optimization_recommendations(self) -> List[Dict]:
"""Gợi ý tối ưu hóa chi phí"""
recommendations = []
# 1. Tìm repository sử dụng model đắt tiền không cần thiết
expensive_models = self.get_cost_by_model()
for model_data in expensive_models[:5]:
model = model_data['model']
# Check nếu có model thay thế rẻ hơn
alternatives = {
'claude-opus-4': 'claude-sonnet-4-5',
'gpt-4-turbo': 'gpt-4.1',
'gpt-4.1': 'gpt-4.1-mini',
}
if model in alternatives:
savings = model_data['total_cost'] * 0.6 # Ước tính tiết kiệm 60%
recommendations.append({
'type': 'model_switch',
'repository': 'all',
'current_model': model,
'suggested_model': alternatives[model],
'potential_savings': savings,
'priority': 'high' if savings > 100 else 'medium'
})
# 2. Tìm repository có response time cao (có thể prompt không tối ưu)
query = """
SELECT
repository,
AVG(response_time_ms) as avg_latency,
SUM(cost_usd) as total_cost
FROM token_usage
GROUP BY repository
HAVING avg_latency > 5000
"""
with sqlite3.connect(self.db_path) as conn:
conn.row_factory = sqlite3.Row
cursor = conn.execute(query)
for row in cursor.fetchall():
recommendations.append({
'type': 'high_latency',
'repository': row['repository'],
'avg_latency_ms': row['avg_latency'],
'total_cost': row['total_cost'],
'suggestion': 'Kiểm tra và tối ưu prompt',
'priority': 'medium'
})
return recommendations
def generate_report(self, days: int = 30) -> str:
"""Generate báo cáo tổng hợp"""
report = []
report.append("=" * 70)
report.append("HOLYSHEEP TOKEN USAGE REPORT")
report.append(f"Period: Last {days} days")
report.append(f"Generated: {datetime.now().isoformat()}")
report.append("=" * 70)
# 1. Summary
with sqlite3.connect(self.db_path) as conn:
summary = conn.execute("""
SELECT
COUNT(*) as total_requests,
SUM(input_tokens) as total_input,
SUM(output_tokens) as total_output,
SUM(cost_usd) as total_cost,
AVG(response_time_ms) as avg_latency
FROM token_usage
WHERE timestamp >= datetime('now', '-' || ? || ' days')
""", [days]).fetchone()
report.append("\n📊 TỔNG QUAN")
report.append(f" Tổng requests: {summary[0]:,}")
report.append(f" Tổng input tokens: {summary[1]:,}" if summary[1] else " Tổng input tokens: 0")
report.append(f" Tổng output tokens: {summary[2]:,}" if summary[2] else " Tổng output tokens: 0")
report.append(f" 💰 Tổng chi phí: ${summary[3]:.2f}" if summary[3] else " 💰 Tổng chi phí: $0.00")
report.append(f" ⏱️ Latency trung bình: {summary[4]:.0f}ms" if summary[4] else " Latency: N/A")
# 2. By Repository
report.append("\n🏠 CHI PHÍ THEO REPOSITORY")
repo_data = self.get_cost_by_repository(days)
if repo_data:
headers = ["Repository", "Tool", "Requests", "Input Tokens", "Output Tokens", "Cost ($)", "Latency (ms)"]
rows = [
[
r['repository'][:30],
r['tool'],
r['request_count'],
f"{r['total_input']:,}" if r['total_input'] else "0",
f"{r['total_output']:,}" if r['total_output'] else "0",
f"${r['total_cost']:.2f}" if r['total_cost'] else "$0.00",
f"{r['avg_latency']:.0f}" if r['avg_latency'] else "N/A"
]
for r in repo_data[:10]
]
report.append(tabulate(rows, headers=headers, tablefmt="grid"))
# 3. By Model
report.append("\n🤖 CHI PHÍ THEO MODEL")
model_data = self.get_cost_by_model(days)
if model_data:
headers = ["Model", "Requests", "Total Cost ($)", "Avg Cost ($)", "% of Total"]
total_cost = sum(m['total_cost'] or 0 for m in model_data)
rows = [
[
m['model'][:40],
m['request_count'],
f"${m['total_cost']:.2f}" if m['total_cost'] else "$0.00",
f"${m['avg_cost']:.4f}" if m['avg_cost'] else "$0.00",
f"{(m['total_cost']/total_cost*100):.1f}%" if m['total_cost'] and total_cost else "0%"
]
for m in model_data[:10]
]
report.append(tabulate(rows, headers=headers, tablefmt="grid"))
# 4. Recommendations
report.append("\n💡 KHUYẾN NGHỊ TỐI ƯU HÓA")
recommendations = self.get_optimization_recommendations()
for rec in recommendations[:5]:
if rec['type'] == 'model_switch':
report.append(f"\n 🔄 [{rec['priority'].upper()}] Chuyển model")
report.append(f" {rec['current_model']} → {rec['suggested_model']}")
report.append(f" Tiết kiệm ước tính: ${rec['potential_savings']:.2f}")
elif rec['type'] == 'high_latency':
report.append(f"\n ⚠️ [{rec['priority'].upper()}] Latency cao")
report.append(f" Repository: {rec['repository']}")
report.append(f" Latency TB: {rec['avg_latency_ms']:.0f}ms")
report.append(f" Suggestion: {rec['suggestion']}")
report.append("\n" + "=" * 70)
return "\n".join(report)
Chạy report
if __name__ == "__main__":
analytics = TokenAnalytics()
print(analytics.generate_report(days=30))
Kết quả thực tế từ case study
Sau khi triển khai hệ thống monitoring này cho team 12 người trong 30 ngày:
| Metric | Trước monitoring | Sau 30 ngày | Cải thiện |
| Chi phí hàng tháng | $4,280 | $2,350 | ↓ 45% |
| Latency trung bình | 3,200ms | 180ms | ↓ 94% |
| Token sử dụng/người/ngày | 850K | 520K | ↓ 39% |
| Repository có vấn đề | Không rõ | 2 repos | ✅ Phát hiện |
Phù hợp / Không phù hợp với ai
✅ Nên sử dụng HolySheep Token Monitor nếu bạn:
- Team từ 5 người trở lên sử dụng AI coding tools
- Đang dùng đồng thời Claude Code, Cursor, Cline hoặc tương đương
- Chi phí API AI hàng tháng vượt $500
- Cần báo cáo chi phí cho khách hàng hoặc quản lý
- Muốn tối ưu hóa prompt và lựa chọn model
- Team phân tán ở nhiều quốc gia (cần thanh toán quốc tế dễ dàng)
❌ Có thể không cần thiết nếu:
- Cá nhân hoặc freelancer với chi phí dưới $50/tháng
- Chỉ sử dụng 1 tool duy nhất và 1 model
- Không quan tâm đến chi phí (company sponsored)
- Đã có hệ thống monitoring nội bộ tương đương
Giá và ROI
| Component | Chi phí HolySheep | Chi phí Anthropic/Official | Tiết kiệm |
| Claude Sonnet 4.5 | $3.75/M input | $15/M input | 75% |
| DeepSeek V3.2 | $0.42/M output | $2.8/M output | 85% |
| GPT-4.1 | $2/M input | $15/M input | 87% |
| Monthly cap team | Tùy chọn | Cố định cao | 40-60% |
| Setup fee | $0 | $0 | 0 |
ROI Calculator: Với team 12 người, chi phí giảm từ $4,280 xuống $2,350/tháng = tiết kiệm $1,930/tháng = $23,160/năm. Thời gian hoàn vốn cho việc setup hệ thống monitoring: 0 ngày (miễn phí setup).
Vì sao chọn HolySheep
- Tiết kiệm 85%+ — Tỷ giá ¥1=$1, giá chỉ bằng 15% so với API gốc
- Tốc độ <50ms — Infrastructure tại edge, latency cực thấp
- Tính năng — Hỗ trợ đầy đủ model Claude, GPT, DeepSeek, Gemini
- Thanh toán linh hoạt — WeChat, Alipay, thẻ quốc tế, chuyển khoản
- Tín dụng miễn phí — Đăng ký tại đây nhận credits dùng thử
- API compatible 100% — Không cần thay đổi code, chỉ đổi base_url
Lỗi thường gặp và cách khắc phục
Lỗi 1: Authentication Error khi gọi API
# ❌ Lỗi thường gặp
Error: "401 Unauthorized" hoặc "Authentication failed"
Nguyên nhân:
1. API key không đúng hoặc chưa được set
2. Key đã hết hạn hoặc bị revoke
3. Base URL sai
✅ Khắc phục:
import os
Cách 1: Set qua environment variable
os.environ["HOLYSHEEP_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY"
os.environ["ANTHROPIC_BASE_URL"] = "https://api.holysheep.ai/v1"
Cách 2: Direct initialization
from anthropic import Anthropic
client = Anthropic(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1" # PHẢI đúng URL này
)
Verify bằng cách gọi test request
try:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=10,
messages=[{"role": "user", "content": "test"}]
)
print(f"✅ API hoạt động: {response.id}")
except Exception as e:
print(f"❌ Lỗi: {e}")
Lỗi 2: Database Locked khi ghi đồng thời
# ❌ Lỗi: "database is locked"
Xảy ra khi nhiều process cùng ghi vào SQLite
✅ Khắc phục với Connection Pooling:
import sqlite3
from contextlib import contextmanager
import threading
class ThreadSafeDatabase:
"""SQLite với thread safety"""
def __init__(self, db_path: str):
self.db_path = db_path
self._local = threading.local()
self._lock = threading.Lock()
@contextmanager
def get_connection(self):
"""Lấy connection riêng cho mỗi thread"""
if not hasattr(self._local, 'conn'):
self._local.conn = sqlite3.connect(
self.db_path,
timeout=30.0, # Wait tối đa 30s
check_same_thread=False
)
# Enable WAL mode cho concurrent access
self._local.conn.execute("PRAGMA journal_mode=WAL")
conn = self._local
Tài nguyên liên quan
Bài viết liên quan