127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Network Log Model - Stores HTTP request logs in the database.
|
|
"""
|
|
|
|
import logging
|
|
from datetime import timedelta
|
|
from urllib.parse import urlparse
|
|
from odoo import api, fields, models
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class NetworkLog(models.Model):
|
|
_name = 'network.log'
|
|
_description = 'Network Traffic Log'
|
|
_order = 'timestamp desc'
|
|
|
|
timestamp = fields.Datetime(
|
|
string='Timestamp',
|
|
default=fields.Datetime.now,
|
|
required=True,
|
|
index=True,
|
|
)
|
|
method = fields.Selection([
|
|
('GET', 'GET'),
|
|
('POST', 'POST'),
|
|
('PUT', 'PUT'),
|
|
('DELETE', 'DELETE'),
|
|
('PATCH', 'PATCH'),
|
|
('HEAD', 'HEAD'),
|
|
('OPTIONS', 'OPTIONS'),
|
|
], string='Method', required=True, index=True)
|
|
|
|
url = fields.Char(string='URL', required=True, index=True)
|
|
domain = fields.Char(string='Domain', compute='_compute_domain', store=True, index=True)
|
|
|
|
is_odoo_call = fields.Boolean(
|
|
string='Odoo External Call',
|
|
default=False,
|
|
index=True,
|
|
help='True if this request was made to an Odoo server',
|
|
)
|
|
|
|
status_code = fields.Integer(string='Status Code')
|
|
status_type = fields.Selection([
|
|
('success', 'Success'),
|
|
('redirect', 'Redirect'),
|
|
('client_error', 'Client Error'),
|
|
('server_error', 'Server Error'),
|
|
('blocked', 'Blocked'),
|
|
('error', 'Error'),
|
|
('pending', 'Pending'),
|
|
], string='Status Type', compute='_compute_status_type', store=True)
|
|
|
|
response_time = fields.Float(string='Response Time (s)', digits=(10, 4))
|
|
error_message = fields.Text(string='Error Message')
|
|
request_headers = fields.Text(string='Request Headers')
|
|
request_body = fields.Text(string='Request Body')
|
|
|
|
@api.depends('url')
|
|
def _compute_domain(self):
|
|
for record in self:
|
|
try:
|
|
parsed = urlparse(record.url or '')
|
|
record.domain = parsed.netloc or 'unknown'
|
|
except Exception:
|
|
record.domain = 'unknown'
|
|
|
|
@api.depends('status_code', 'error_message')
|
|
def _compute_status_type(self):
|
|
for record in self:
|
|
if record.error_message:
|
|
if 'blocked' in (record.error_message or '').lower():
|
|
record.status_type = 'blocked'
|
|
else:
|
|
record.status_type = 'error'
|
|
elif not record.status_code:
|
|
record.status_type = 'pending'
|
|
elif 200 <= record.status_code < 300:
|
|
record.status_type = 'success'
|
|
elif 300 <= record.status_code < 400:
|
|
record.status_type = 'redirect'
|
|
elif 400 <= record.status_code < 500:
|
|
record.status_type = 'client_error'
|
|
elif record.status_code >= 500:
|
|
record.status_type = 'server_error'
|
|
else:
|
|
record.status_type = 'pending'
|
|
|
|
@api.model
|
|
def log_request(self, method, url, is_odoo_call=False, status_code=None,
|
|
response_time=None, error_message=None):
|
|
"""Create a new network log entry."""
|
|
try:
|
|
vals = {
|
|
'method': method.upper(),
|
|
'url': url[:2048] if url else '',
|
|
'is_odoo_call': is_odoo_call,
|
|
'status_code': status_code,
|
|
'response_time': response_time,
|
|
'error_message': error_message[:4096] if error_message else None,
|
|
}
|
|
return self.sudo().create(vals)
|
|
except Exception as e:
|
|
_logger.warning("Failed to log network request: %s", e)
|
|
return self.browse()
|
|
|
|
@api.model
|
|
def clear_old_logs(self, days=7):
|
|
"""Delete logs older than specified days."""
|
|
cutoff = fields.Datetime.now() - timedelta(days=days)
|
|
old_logs = self.search([('timestamp', '<', cutoff)])
|
|
count = len(old_logs)
|
|
old_logs.unlink()
|
|
_logger.info("Cleared %d network logs older than %d days", count, days)
|
|
return count
|
|
|
|
@api.model
|
|
def clear_all_logs(self):
|
|
"""Delete all network logs."""
|
|
count = self.search_count([])
|
|
self.search([]).unlink()
|
|
_logger.info("Cleared all %d network logs", count)
|
|
return count
|
|
|