You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

219 lines
8.5 KiB

# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
import os
import platform
import psycopg2
import psutil
from odoo import api, models
from odoo.exceptions import AccessError
from odoo.tools import config
def get_model_storage(db_name, model_name):
""" Method to get storage usage of a model it returns storage of
specific model passed to this method """
sql_model_name = model_name.replace(".", "_")
db_host = config['db_host']
db_port = config['db_port']
db_user = config['db_user']
db_password = config['db_password']
try:
connection = psycopg2.connect(
dbname=db_name,
user=db_user,
password=db_password,
host=db_host,
port=db_port,
)
cursor = connection.cursor()
cursor.execute(f"""
SELECT sum(pg_column_size(x))
FROM (SELECT * FROM {sql_model_name}) AS x;
""")
total_storage = cursor.fetchone()[0]
cursor.close()
connection.close()
except psycopg2.Error as e:
if 'relation does not exist' in str(e).lower():
# Return zero as storage when the relation doesn't exist
return '0 bytes'
else:
return None
return total_storage
def get_index_data(db_name, model_name):
sql_model_name = model_name.replace(".", "_")
db_host = config['db_host']
db_port = config['db_port']
db_user = config['db_user']
db_password = config['db_password']
try:
connection = psycopg2.connect(
dbname=db_name,
user=db_user,
password=db_password,
host=db_host,
port=db_port,
)
cursor = connection.cursor()
cursor.execute(f"""SELECT
pg_indexes_size('{sql_model_name}');
""")
index_size = cursor.fetchone()[0]
cursor.close()
connection.close()
except psycopg2.Error as e:
if 'relation does not exist' in str(e).lower():
# Return zero as storage when the relation doesn't exist
return '0 bytes'
else:
return None
return index_size
class StorageUsage(models.Model):
""" Model for Compute Storage usage of each models """
_name = 'storage.usage'
_description = "Storage Usage"
@api.model
def get_data(self):
""" Method for get all existing models and return model with its
storage with the help of get_model_storage_method """
user_group_ids = self.env.user.groups_id.ids
accessible_model_ids = self.env['ir.model.access'].search([
('group_id', 'in', user_group_ids)
]).mapped('model_id').ids
model_names = [record.model for record in self.env['ir.model'].browse(
accessible_model_ids)]
model_storage = []
index_data = []
for name in model_names:
index_size = get_index_data(self.env.cr.dbname, name) if get_index_data(self.env.cr.dbname, name) else 0
if index_size > 100000:
index_size = round(index_size / (1024 * 1024), 2)
if index_size != 0:
index_data.append({'model': name, 'index_size': index_size})
size = get_model_storage(self.env.cr.dbname, name) if get_model_storage(self.env.cr.dbname, name) else 0
if size > 100000:
size = round(size / (1024 * 1024), 2)
if size != 0:
model_storage.append({'model': name, 'size': size})
model_storage = sorted(model_storage, key=lambda x: x['size'],
reverse=True)
return {'model_storage': model_storage,
'index_data': index_data}
@api.model
def get_info(self):
"""
Method for get database information and returns it as a dictionary
"""
db_host = config['db_host']
db_port = config['db_port']
db_user = config['db_user']
db_password = config['db_password']
try:
connection = psycopg2.connect(
dbname=self.env.cr.dbname,
user=db_user,
password=db_password,
host=db_host,
port=db_port
)
cursor = connection.cursor()
# Version of DB
cursor.execute("SELECT version();")
db_version = cursor.fetchone()[0]
# Total size of DB
cursor.execute("""
SELECT sum(pg_total_relation_size(schemaname || '.' ||
tablename)) FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema');
""")
db_size = cursor.fetchone()[0] / (1024 * 1024)
# total storage test
cursor.execute(f"""
SELECT sum(pg_column_size(x))
FROM (SELECT * FROM {"ir_model_data"}) AS x;
""")
total_storage_bytes = cursor.fetchone()[0]
total_storage_kb = total_storage_bytes / 1024
# Execute a query to fetch the total relations in DB
cursor.execute("""
SELECT count(*) FROM information_schema.tables WHERE
table_schema='public';
""")
# Fetch the result
db_tables = cursor.fetchone()[0]
cursor.close()
connection.close()
# Getting system monitor datas
system_datas = dict(psutil.virtual_memory()._asdict())
total_memory = system_datas['total'] / (1024 * 1024 * 1024)
used_memory = system_datas['used'] / (1024 * 1024 * 1024)
available_memory = system_datas['available'] / (1024 * 1024 * 1024)
cpu_usage = psutil.cpu_percent(interval=None)
operating_system = platform.system()
os_ver = platform.release()
soft_limit = config.get('limit_memory_soft') / (1024 * 1024 * 1024)
hard_limit = config.get('limit_memory_hard') / (1024 * 1024 * 1024)
transient_age_limit = config.get('transient_age_limit')
limit_time_cpu = config.get('limit_time_cpu')
limit_request = config.get('limit_request')
limit_time_real = config.get('limit_time_real')
http_port = config.get('http_port')
db_user = config.get('db_user')
# Odoo ram usage
process = psutil.Process(os.getpid())
memory_info = process.memory_info()
ram_usage = memory_info.rss / (1024 * 1024)
db_date = self.env['ir.config_parameter'].sudo().get_param(
'database.create_date')
except psycopg2.Error as e:
raise AccessError(
f"Error while fetching database information via query: {e}")
return {
'db_name': self.env.cr.dbname,
'db_version': db_version,
'db_date': db_date,
'db_size': f"{round(db_size, 2)} MB",
'db_tables': db_tables,
'total_storage_kb': total_storage_kb,
'total_memory': f"{round(total_memory, 2)} GB",
'used_memory': f"{round(used_memory, 2)} GB",
'available_memory': f"{round(available_memory, 2)} GB",
'cpu_usage': f"{cpu_usage} %",
'ram_usage': f"{round(ram_usage, 2)} MB",
'os': f"{operating_system +' ' + os_ver}",
'db_user': db_user,
'soft_limit': f"{soft_limit} GB",
'hard_limit': f"{hard_limit} GB",
'transient_age_limit': f"{transient_age_limit} GB",
'limit_time_cpu': f"{limit_time_cpu} s",
'limit_request': limit_request,
'limit_time_real': limit_time_real,
'http_port': http_port,
}