Moises Lopez - https://www.vauxoo.com/
9 years ago
19 changed files with 1686 additions and 0 deletions
-
86server_monitoring/README.rst
-
21server_monitoring/__init__.py
-
63server_monitoring/__openerp__.py
-
47server_monitoring/data/ir_cron.xml
-
445server_monitoring/i18n/server_monitoring.pot
-
26server_monitoring/models/__init__.py
-
30server_monitoring/models/field_types.py
-
38server_monitoring/models/ir_cron.py
-
213server_monitoring/models/server_monitor_database.py
-
244server_monitoring/models/server_monitor_process.py
-
8server_monitoring/security/ir.model.access.csv
-
64server_monitoring/tests/test_monitor_database.yml
-
28server_monitoring/tests/test_monitor_process.yml
-
11server_monitoring/views/menu.xml
-
92server_monitoring/views/server_monitor_database.xml
-
91server_monitoring/views/server_monitor_database_table_activity.xml
-
43server_monitoring/views/server_monitor_model_row_count.xml
-
44server_monitoring/views/server_monitor_model_table_size.xml
-
92server_monitoring/views/server_monitor_process.xml
@ -0,0 +1,86 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:alt: License: AGPL-3 |
|||
|
|||
================= |
|||
server monitoring |
|||
================= |
|||
|
|||
This module allows in-database logging of some statistics in order to monitor |
|||
the health of an openerp instance. |
|||
|
|||
Database indicators are logged (number of rows, table size, number of reads, |
|||
number of updates...), with a cron running each week by default. This cron |
|||
needs to be activated after the module is installed. |
|||
|
|||
Some process indicators are logged (cpu time, memory) together with information |
|||
about the different XMLRPC calls made to the server (user, model, method). |
|||
|
|||
Two crons are provided to cleanup old logs from the database. |
|||
|
|||
|
|||
Configuration |
|||
============= |
|||
|
|||
To configure this module, you need to: |
|||
|
|||
* Settings -> Scheduled Actions and tune the cron tasks |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
Just install the addon in your instance. You will be able to access the logs |
|||
under Reporting -> Server Monitoring. |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/149/7.0 |
|||
|
|||
For further information, please visit: |
|||
|
|||
* https://www.odoo.com/forum/help-1 |
|||
|
|||
Known issues / Roadmap |
|||
====================== |
|||
|
|||
* Not tested under other platforms than Linux |
|||
|
|||
TODO / WISH list: |
|||
* visualization |
|||
* export |
|||
* check if we can / wish to log session id |
|||
* check if we can log pooler state (whatever that is...) |
|||
* check if we can log HTTP status |
|||
* enhance group by for process logs. |
|||
|
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_. |
|||
In case of trouble, please check there if your issue has already been reported. |
|||
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback |
|||
`here <https://github.com/OCA/server-tools/issues/new?body=module:%20server_monitoring%0Aversion:%207.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
|||
|
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Alexandre Fayolle <alexandre.fayolle@camptocamp.com> |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
OCA, or the Odoo Community Association, is a nonprofit organization whose |
|||
mission is to support the collaborative development of Odoo features and |
|||
promote its widespread use. |
|||
|
|||
To contribute to this module, please visit http://odoo-community.org. |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import models |
@ -0,0 +1,63 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Server Monitoring', |
|||
'version': '0.1', |
|||
'category': 'Tools', |
|||
'depends': ['base', |
|||
], |
|||
'author': 'Camptocamp, Odoo Community Association (OCA)', |
|||
'license': 'AGPL-3', |
|||
'description': """ |
|||
Server Monitoring |
|||
================= |
|||
|
|||
This module allows in-database logging of some statistics in order to monitor |
|||
the health of an openerp instance. |
|||
|
|||
Database indicators are logged (number of rows, table size, number of reads, |
|||
number of updates...), with a cron running each week by default. This cron |
|||
needs to be activated after the module is installed. |
|||
|
|||
Some process indicators are logged (cpu time, memory) together with information |
|||
about the different XMLRPC calls made to the server (user, model, method). |
|||
|
|||
Two crons are provided to cleanup old logs from the database. |
|||
|
|||
The logs are available through the menu Reporting -> Server Monitoring. |
|||
""", |
|||
'data': [ |
|||
'views/menu.xml', |
|||
'views/server_monitor_database_table_activity.xml', |
|||
'views/server_monitor_database.xml', |
|||
'views/server_monitor_model_row_count.xml', |
|||
'views/server_monitor_model_table_size.xml', |
|||
'views/server_monitor_process.xml', |
|||
'data/ir_cron.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'test': [ |
|||
'tests/test_monitor_process.yml', |
|||
'tests/test_monitor_database.yml', |
|||
], |
|||
'installable': True, |
|||
} |
@ -0,0 +1,47 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data noupdate="1"> |
|||
<record forcecreate="True" id="ir_cron_monitoring_action" model="ir.cron"> |
|||
<field name="name">Database monitoring</field> |
|||
<field eval="False" name="active"/> |
|||
<field name="user_id" ref="base.user_root"/> |
|||
<field name="interval_number">7</field> |
|||
<field name="interval_type">days</field> |
|||
<field name="numbercall">-1</field> |
|||
<field eval="False" name="doall"/> |
|||
<field eval="'server.monitor.database'" name="model"/> |
|||
<field eval="'log_measure'" name="function"/> |
|||
<field eval="'()'" name="args"/> |
|||
<field name="priority" eval='100'/> |
|||
</record> |
|||
|
|||
<record forcecreate="True" id="ir_cron_monitoring_process_cleanup_action" model="ir.cron"> |
|||
<field name="name">Process monitoring cleanup</field> |
|||
<field eval="True" name="active"/> |
|||
<field name="user_id" ref="base.user_root"/> |
|||
<field name="interval_number">1</field> |
|||
<field name="interval_type">days</field> |
|||
<field name="numbercall">-1</field> |
|||
<field eval="False" name="doall"/> |
|||
<field eval="'server.monitor.process'" name="model"/> |
|||
<field eval="'cleanup'" name="function"/> |
|||
<field eval="'(30,)'" name="args"/> |
|||
<field name="priority" eval='500'/> |
|||
</record> |
|||
|
|||
<record forcecreate="True" id="ir_cron_monitoring_database_cleanup_action" model="ir.cron"> |
|||
<field name="name">Database monitoring cleanup</field> |
|||
<field eval="True" name="active"/> |
|||
<field name="user_id" ref="base.user_root"/> |
|||
<field name="interval_number">1</field> |
|||
<field name="interval_type">days</field> |
|||
<field name="numbercall">-1</field> |
|||
<field eval="False" name="doall"/> |
|||
<field eval="'server.monitor.database'" name="model"/> |
|||
<field eval="'cleanup'" name="function"/> |
|||
<field eval="'(365,)'" name="args"/> |
|||
<field name="priority" eval='500'/> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,445 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * server_monitoring |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-04-10 10:31+0000\n" |
|||
"PO-Revision-Date: 2014-04-10 12:33+0200\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_cpu_time |
|||
#: field:server.monitor.process,cpu_time:0 |
|||
msgid "CPU time" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_read_cache_reads |
|||
#: field:server.monitor.model.table.activity.read,cache_reads:0 |
|||
msgid "Cache reads" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.process:0 |
|||
msgid "Class count" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_class_count_ids |
|||
#: field:server.monitor.process,class_count_ids:0 |
|||
msgid "Class counts" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_class_instance_count_name |
|||
#: field:server.monitor.class.instance.count,name:0 |
|||
msgid "Class name" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitor_database_table_activity_read_menu |
|||
msgid "DB Reads" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.actions.act_window,name:server_monitoring.server_monitor_database_table_activity_read |
|||
#: model:ir.actions.act_window,name:server_monitoring.server_monitor_database_table_rows |
|||
#: model:ir.actions.act_window,name:server_monitoring.server_monitor_database_table_size |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitor_database_table_activity_update_menu |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitor_database_table_rows_menu |
|||
msgid "DB Rows" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitor_database_table_size_menu |
|||
msgid "DB Table Size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.actions.act_window,name:server_monitoring.server_monitor_database_table_activity_update |
|||
msgid "DB Updates" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.actions.act_window,name:server_monitoring.server_monitor_database_info |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitor_database_menu |
|||
msgid "Database Info" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_num_delete |
|||
#: field:server.monitor.model.table.activity.update,num_delete:0 |
|||
msgid "Deletes" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_read_disk_reads |
|||
#: field:server.monitor.model.table.activity.read,disk_reads:0 |
|||
msgid "Disk reads (heap blocks)" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.row.count:0 |
|||
#: view:server.monitor.model.table.activity.read:0 |
|||
#: view:server.monitor.model.table.activity.update:0 |
|||
#: view:server.monitor.model.table.size:0 |
|||
#: view:server.monitor.process:0 |
|||
msgid "Group By..." |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_idx_scan |
|||
#: field:server.monitor.model.table.activity.update,idx_scan:0 |
|||
msgid "Idx scans" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_database_info |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_info |
|||
#: view:server.monitor.database:0 |
|||
#: field:server.monitor.database,info:0 |
|||
#: view:server.monitor.process:0 |
|||
#: field:server.monitor.process,info:0 |
|||
msgid "Information" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_num_insert |
|||
#: field:server.monitor.model.table.activity.update,num_insert:0 |
|||
msgid "Inserts" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_class_instance_count_count |
|||
#: field:server.monitor.class.instance.count,count:0 |
|||
msgid "Instance count" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_class_instance_count_measure_id |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_row_count_measure_id |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_read_measure_id |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_measure_id |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_size_measure_id |
|||
#: field:server.monitor.class.instance.count,measure_id:0 |
|||
#: field:server.monitor.model.row.count,measure_id:0 |
|||
#: field:server.monitor.model.table.activity.read,measure_id:0 |
|||
#: field:server.monitor.model.table.activity.update,measure_id:0 |
|||
#: field:server.monitor.model.table.size,measure_id:0 |
|||
msgid "Measure" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_memory |
|||
#: field:server.monitor.process,memory:0 |
|||
msgid "Memory" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_method |
|||
#: field:server.monitor.process,method:0 |
|||
msgid "Method" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_model |
|||
#: field:server.monitor.process,model:0 |
|||
msgid "Model" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_database_table_nb_row_ids |
|||
#: field:server.monitor.database,table_nb_row_ids:0 |
|||
msgid "Model row counts" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_database_table_activity_read_ids |
|||
#: field:server.monitor.database,table_activity_read_ids:0 |
|||
msgid "Model table read activity" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_database_table_size_ids |
|||
#: field:server.monitor.database,table_size_ids:0 |
|||
msgid "Model table size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_database_table_activity_update_ids |
|||
#: field:server.monitor.database,table_activity_update_ids:0 |
|||
msgid "Model table update activity" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.database:0 |
|||
msgid "Nb rows" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.process:0 |
|||
msgid "PID" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_pid |
|||
#: field:server.monitor.process,pid:0 |
|||
msgid "Process ID" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.actions.act_window,name:server_monitoring.server_monitor_process_info |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitor_process_menu |
|||
msgid "Process Info" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_status |
|||
#: field:server.monitor.process,status:0 |
|||
msgid "RPC status" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.row.count:0 |
|||
#: view:server.monitor.process:0 |
|||
msgid "Search Server Monitor Process" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.table.activity.read:0 |
|||
#: view:server.monitor.model.table.activity.update:0 |
|||
msgid "Search Server Monitor Table Actitivty" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.table.size:0 |
|||
msgid "Search Server Monitor Table Size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_seq_scan |
|||
#: field:server.monitor.model.table.activity.update,seq_scan:0 |
|||
msgid "Seq scans" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.database:0 |
|||
#: view:server.monitor.process:0 |
|||
msgid "Server Monitor" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.table.activity.read:0 |
|||
#: view:server.monitor.model.table.activity.update:0 |
|||
#: view:server.monitor.model.table.size:0 |
|||
msgid "Server Monitor DB Table size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.row.count:0 |
|||
#: view:server.monitor.process:0 |
|||
msgid "Server Monitor Process" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.ui.menu,name:server_monitoring.server_monitoring |
|||
msgid "Server Monitoring" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_sessionid |
|||
#: field:server.monitor.process,sessionid:0 |
|||
msgid "Session ID" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_size_hsize |
|||
#: field:server.monitor.model.table.size,hsize:0 |
|||
msgid "Size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_size_size |
|||
#: field:server.monitor.model.table.size,size:0 |
|||
msgid "Size (bytes)" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_row_count_name |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_read_name |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_name |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_size_name |
|||
#: field:server.monitor.model.row.count,name:0 |
|||
#: field:server.monitor.model.table.activity.read,name:0 |
|||
#: field:server.monitor.model.table.activity.update,name:0 |
|||
#: field:server.monitor.model.table.size,name:0 |
|||
msgid "Table name" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.database:0 |
|||
msgid "Table reads" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.database:0 |
|||
msgid "Table size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.database:0 |
|||
msgid "Table updates" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_thread |
|||
#: field:server.monitor.process,thread:0 |
|||
msgid "Thread ID" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_database_name |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_name |
|||
#: field:server.monitor.database,name:0 |
|||
#: field:server.monitor.process,name:0 |
|||
msgid "Timestamp" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_lines_read_total |
|||
#: field:server.monitor.model.table.activity.update,lines_read_total:0 |
|||
msgid "Tot lines read" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_read_total_reads |
|||
#: field:server.monitor.model.table.activity.read,total_reads:0 |
|||
msgid "Total reads" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_num_update |
|||
#: field:server.monitor.model.table.activity.update,num_update:0 |
|||
msgid "Updates" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_process_uid |
|||
#: field:server.monitor.process,uid:0 |
|||
msgid "User" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.process:0 |
|||
msgid "call information" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.process:0 |
|||
msgid "date" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_ir_cron |
|||
#, python-format |
|||
msgid "ir.cron" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.process:0 |
|||
msgid "method" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.process:0 |
|||
msgid "model" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: view:server.monitor.model.row.count:0 |
|||
#: view:server.monitor.model.table.activity.read:0 |
|||
#: view:server.monitor.model.table.activity.update:0 |
|||
#: view:server.monitor.model.table.size:0 |
|||
msgid "name" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_row_count_count |
|||
#: field:server.monitor.model.row.count,count:0 |
|||
msgid "row count" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_class_instance_count |
|||
#, python-format |
|||
msgid "server.monitor.class.instance.count" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_database |
|||
#, python-format |
|||
msgid "server.monitor.database" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_model_row_count |
|||
#, python-format |
|||
msgid "server.monitor.model.row.count" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_model_table_activity_read |
|||
#, python-format |
|||
msgid "server.monitor.model.table.activity.read" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_model_table_activity_update |
|||
#, python-format |
|||
msgid "server.monitor.model.table.activity.update" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_model_table_size |
|||
#, python-format |
|||
msgid "server.monitor.model.table.size" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:server_monitoring.model_server_monitor_process |
|||
#, python-format |
|||
msgid "server.monitor.process" |
|||
msgstr "" |
|||
|
|||
#. module: server_monitoring |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_row_count_timestamp |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_read_timestamp |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_activity_update_timestamp |
|||
#: model:ir.model.fields,field_description:server_monitoring.field_server_monitor_model_table_size_timestamp |
|||
#: view:server.monitor.model.row.count:0 |
|||
#: field:server.monitor.model.row.count,timestamp:0 |
|||
#: view:server.monitor.model.table.activity.read:0 |
|||
#: field:server.monitor.model.table.activity.read,timestamp:0 |
|||
#: view:server.monitor.model.table.activity.update:0 |
|||
#: field:server.monitor.model.table.activity.update,timestamp:0 |
|||
#: view:server.monitor.model.table.size:0 |
|||
#: field:server.monitor.model.table.size,timestamp:0 |
|||
msgid "timestamp" |
|||
msgstr "" |
|||
|
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
|
|||
from . import field_types |
|||
from . import ir_cron |
|||
from . import server_monitor_process |
|||
from . import server_monitor_database |
@ -0,0 +1,30 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from openerp.osv import orm, fields |
|||
|
|||
|
|||
class bigint(fields.integer): |
|||
_type = 'int8' |
|||
|
|||
|
|||
fields.bigint = bigint |
|||
orm.FIELDS_TO_PGTYPES[bigint] = 'int8' |
@ -0,0 +1,38 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from openerp.osv import orm |
|||
|
|||
|
|||
class IrCron(orm.Model): |
|||
_inherit = 'ir.cron' |
|||
|
|||
def _callback(self, cr, uid, model_name, method_name, args, job_id): |
|||
super(IrCron, self)._callback(cr, uid, |
|||
model_name, |
|||
method_name, |
|||
args, |
|||
job_id) |
|||
monitor_obj = self.pool['server.monitor.process'] |
|||
context = {} |
|||
monitor_obj.log_measure(cr, uid, |
|||
model_name, method_name, |
|||
'cron job', |
|||
False, False, context) |
@ -0,0 +1,213 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import logging |
|||
import datetime |
|||
|
|||
from openerp.osv import orm, fields |
|||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT |
|||
|
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class ModelRowCount(orm.Model): |
|||
_name = 'server.monitor.model.row.count' |
|||
_columns = { |
|||
'name': fields.text('Table name', readonly=True), |
|||
'count': fields.bigint('row count', readonly=True), |
|||
'measure_id': fields.many2one('server.monitor.database', |
|||
'Measure', |
|||
ondelete='cascade', |
|||
readonly=True), |
|||
'timestamp': fields.related('measure_id', 'name', |
|||
string='timestamp', |
|||
type='datetime', |
|||
store=True), |
|||
} |
|||
_order = 'timestamp DESC, count DESC' |
|||
|
|||
|
|||
class ModelTableSize(orm.Model): |
|||
_name = 'server.monitor.model.table.size' |
|||
_columns = { |
|||
'name': fields.text('Table name', readonly=True), |
|||
'size': fields.bigint('Size (bytes)', readonly=True), |
|||
'hsize': fields.text('Size', readonly=True), |
|||
'measure_id': fields.many2one('server.monitor.database', |
|||
'Measure', |
|||
ondelete='cascade', readonly=True), |
|||
'timestamp': fields.related('measure_id', 'name', |
|||
string='timestamp', |
|||
type='datetime', |
|||
store=True), |
|||
} |
|||
_order = 'timestamp DESC, size DESC' |
|||
|
|||
|
|||
class ModelTableActivityRead(orm.Model): |
|||
_name = 'server.monitor.model.table.activity.read' |
|||
_columns = { |
|||
'name': fields.text('Table name'), |
|||
'disk_reads': fields.bigint('Disk reads (heap blocks)', readonly=True), |
|||
'cache_reads': fields.bigint('Cache reads', readonly=True), |
|||
'total_reads': fields.bigint('Total reads', readonly=True), |
|||
'measure_id': fields.many2one('server.monitor.database', |
|||
'Measure', |
|||
ondelete='cascade', readonly=True), |
|||
'timestamp': fields.related('measure_id', 'name', |
|||
string='timestamp', |
|||
type='datetime', |
|||
store=True), |
|||
} |
|||
_order = 'timestamp DESC, total_reads DESC' |
|||
|
|||
|
|||
class ModelTableActivityUpdate(orm.Model): |
|||
_name = 'server.monitor.model.table.activity.update' |
|||
_columns = { |
|||
'name': fields.text('Table name', readonly=True), |
|||
'seq_scan': fields.bigint('Seq scans', readonly=True), |
|||
'idx_scan': fields.bigint('Idx scans', readonly=True), |
|||
'lines_read_total': fields.bigint('Tot lines read', readonly=True), |
|||
'num_insert': fields.bigint('Inserts', readonly=True), |
|||
'num_update': fields.bigint('Updates', readonly=True), |
|||
'num_delete': fields.bigint('Deletes', readonly=True), |
|||
'measure_id': fields.many2one('server.monitor.database', |
|||
'Measure', |
|||
ondelete='cascade', |
|||
readonly=True), |
|||
'timestamp': fields.related('measure_id', 'name', |
|||
string='timestamp', |
|||
type='datetime', |
|||
store=True), |
|||
} |
|||
_order = 'timestamp DESC, num_update DESC' |
|||
|
|||
|
|||
class ServerMonitorDatabase(orm.Model): |
|||
_name = 'server.monitor.database' |
|||
_columns = { |
|||
'name': fields.datetime('Timestamp', readonly=True), |
|||
'info': fields.text('Information'), |
|||
'table_nb_row_ids': fields.one2many('server.monitor.model.row.count', |
|||
'measure_id', |
|||
'Model row counts', |
|||
readonly=True), |
|||
'table_size_ids': fields.one2many('server.monitor.model.table.size', |
|||
'measure_id', |
|||
'Model table size', |
|||
readonly=True), |
|||
'table_activity_read_ids': fields.one2many( |
|||
'server.monitor.model.table.activity.read', |
|||
'measure_id', |
|||
'Model table read activity', |
|||
readonly=True), |
|||
'table_activity_update_ids': fields.one2many( |
|||
'server.monitor.model.table.activity.update', |
|||
'measure_id', |
|||
'Model table update activity', |
|||
readonly=True), |
|||
} |
|||
_order = 'name DESC' |
|||
|
|||
def _model_row_count(self, cr, uid, context): |
|||
res = [] |
|||
query = ("SELECT schemaname || '.' || relname as name, " |
|||
" n_live_tup as count " |
|||
"FROM pg_stat_user_tables " |
|||
"ORDER BY n_live_tup DESC") |
|||
cr.execute(query) |
|||
for val in cr.dictfetchall(): |
|||
res.append((0, 0, val)) |
|||
return res |
|||
|
|||
def _model_table_size(self, cr, uid, context): |
|||
res = [] |
|||
query = ( |
|||
"SELECT nspname || '.' || relname AS name, " |
|||
" pg_size_pretty(pg_total_relation_size(C.oid)) AS hsize, " |
|||
" pg_total_relation_size(C.oid) AS size " |
|||
"FROM pg_class C LEFT JOIN pg_namespace N " |
|||
" ON (N.oid = C.relnamespace) " |
|||
"WHERE nspname NOT IN ('pg_catalog', 'information_schema') " |
|||
" AND C.relkind <> 'i' " |
|||
" AND nspname !~ '^pg_toast' " |
|||
"ORDER BY pg_total_relation_size(C.oid) DESC" |
|||
) |
|||
cr.execute(query) |
|||
for val in cr.dictfetchall(): |
|||
res.append((0, 0, val)) |
|||
return res |
|||
|
|||
def _model_table_activity_read(self, cr, uid, context): |
|||
res = [] |
|||
query = ("SELECT schemaname || '.' || relname as name, " |
|||
" heap_blks_read as disk_reads, " |
|||
" heap_blks_hit as cache_reads, " |
|||
" heap_blks_read + heap_blks_hit as total_reads " |
|||
"FROM pg_statio_user_tables " |
|||
"ORDER BY heap_blks_read + heap_blks_hit DESC" |
|||
) |
|||
cr.execute(query) |
|||
for val in cr.dictfetchall(): |
|||
res.append((0, 0, val)) |
|||
return res |
|||
|
|||
def _model_table_activity_update(self, cr, uid, context): |
|||
res = [] |
|||
query = ("SELECT schemaname || '.' || relname as name, " |
|||
" seq_scan, " |
|||
" idx_scan, " |
|||
" idx_tup_fetch + seq_tup_read as lines_read_total, " |
|||
" n_tup_ins as num_insert, " |
|||
" n_tup_upd as num_update, " |
|||
" n_tup_del as num_delete " |
|||
"FROM pg_stat_user_tables " |
|||
"ORDER BY n_tup_upd + n_tup_ins + n_tup_del desc") |
|||
cr.execute(query) |
|||
for val in cr.dictfetchall(): |
|||
res.append((0, 0, val)) |
|||
return res |
|||
|
|||
_defaults = { |
|||
'name': fields.datetime.now, |
|||
'table_nb_row_ids': _model_row_count, |
|||
'table_size_ids': _model_table_size, |
|||
'table_activity_read_ids': _model_table_activity_read, |
|||
'table_activity_update_ids': _model_table_activity_update, |
|||
} |
|||
|
|||
def log_measure(self, cr, uid, context=None): |
|||
fields = self._defaults.keys() |
|||
defaults = self.default_get(cr, uid, fields, context=context) |
|||
self.create(cr, uid, defaults, context=context) |
|||
return True |
|||
|
|||
def cleanup(self, cr, uid, age, context=None): |
|||
now = datetime.datetime.now() |
|||
delta = datetime.timedelta(days=age) |
|||
when = (now - delta).strftime(DEFAULT_SERVER_DATETIME_FORMAT) |
|||
ids = self.search(cr, uid, |
|||
[('name', '<', when)], |
|||
context=context) |
|||
_logger.debug('Database monitor cleanup: removing %d records', |
|||
len(ids)) |
|||
self.unlink(cr, uid, ids, context=context) |
@ -0,0 +1,244 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Alexandre Fayolle |
|||
# Copyright 2014 Camptocamp SA |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# 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 Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
""" |
|||
Monitor openerp instance. |
|||
|
|||
The measures are stored in database. |
|||
cleanup cron (2 different for db and process monitoring) |
|||
|
|||
* database monitoring: |
|||
cron for capturing data |
|||
add timestamp |
|||
|
|||
* process monitoring |
|||
|
|||
TODO: log process start / end |
|||
cron log |
|||
RPC request log |
|||
|
|||
""" |
|||
|
|||
import logging |
|||
import gc |
|||
from operator import itemgetter |
|||
import types |
|||
import os |
|||
import threading |
|||
import datetime |
|||
|
|||
# ugly hack to avoid a WARNING message when importing stdlib resource module |
|||
_logger = logging.getLogger('openerp.modules.module') |
|||
_saved_log_level = _logger.getEffectiveLevel() |
|||
_logger.setLevel(logging.ERROR) |
|||
import resource |
|||
_logger.setLevel(_saved_log_level) |
|||
|
|||
|
|||
import psutil |
|||
|
|||
from openerp.osv import orm, fields, osv |
|||
from openerp import pooler |
|||
from openerp import SUPERUSER_ID |
|||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
BLACKLIST = ( |
|||
type, tuple, dict, list, set, frozenset, |
|||
property, |
|||
classmethod, |
|||
staticmethod, |
|||
types.FunctionType, |
|||
types.ClassType, |
|||
types.ModuleType, types.FunctionType, types.MethodType, |
|||
types.MemberDescriptorType, types.GetSetDescriptorType, |
|||
) |
|||
|
|||
|
|||
class ClassInstanceCount(orm.Model): |
|||
_name = 'server.monitor.class.instance.count' |
|||
_columns = { |
|||
'name': fields.text('Class name', readonly=True), |
|||
'count': fields.bigint('Instance count', readonly=True), |
|||
'measure_id': fields.many2one('server.monitor.process', |
|||
'Measure', |
|||
readonly=True, |
|||
ondelete='cascade'), |
|||
} |
|||
|
|||
|
|||
def _monkey_patch_object_proxy_execute(): |
|||
orig_execute_cr = osv.object_proxy.execute_cr |
|||
|
|||
def execute_cr(self, cr, uid, obj, method, *args, **kw): |
|||
result = orig_execute_cr(self, cr, uid, obj, method, *args, **kw) |
|||
monitor_obj = pooler.get_pool(cr.dbname)['server.monitor.process'] |
|||
context = {} |
|||
monitor_obj.log_measure(cr, uid, obj, method, 'rpc call', |
|||
False, False, context) |
|||
return result |
|||
|
|||
osv.object_proxy.execute_cr = execute_cr |
|||
|
|||
|
|||
class ServerMonitorProcess(orm.Model): |
|||
def __init__(self, pool, cr): |
|||
super(ServerMonitorProcess, self).__init__(pool, cr) |
|||
_monkey_patch_object_proxy_execute() |
|||
|
|||
_name = 'server.monitor.process' |
|||
_columns = { |
|||
'name': fields.datetime('Timestamp', readonly=True), |
|||
'pid': fields.integer('Process ID', readonly=True, |
|||
group_operator='count'), |
|||
'thread': fields.text('Thread ID', readonly=True), |
|||
'cpu_time': fields.float( |
|||
'CPU time', readonly=True, |
|||
group_operator='max', |
|||
help='CPU time consumed by the current server process'), |
|||
'memory': fields.float( |
|||
'Memory', readonly=True, |
|||
group_operator='max', |
|||
help='Memory consumed by the current server process'), |
|||
'uid': fields.many2one('res.users', 'User', |
|||
readonly=True, |
|||
select=True), |
|||
'model': fields.many2one('ir.model', 'Model', |
|||
readonly=True, |
|||
select=True), |
|||
'method': fields.text('Method', readonly=True), |
|||
'status': fields.text('RPC status', readonly=True), |
|||
'sessionid': fields.text('Session ID', readonly=True), |
|||
'info': fields.text('Information'), |
|||
'class_count_ids': fields.one2many( |
|||
'server.monitor.class.instance.count', |
|||
'measure_id', |
|||
'Class counts', |
|||
readonly=True), |
|||
} |
|||
_order = 'name DESC' |
|||
|
|||
def _default_pid(self, cr, uid, context): |
|||
return os.getpid() |
|||
|
|||
def _default_cpu_time(self, cr, uid, context): |
|||
r = resource.getrusage(resource.RUSAGE_SELF) |
|||
cpu_time = r.ru_utime + r.ru_stime |
|||
return cpu_time |
|||
|
|||
def _default_memory(self, cr, uid, context): |
|||
try: |
|||
rss, vms = psutil.Process(os.getpid()).get_memory_info() |
|||
except AttributeError: |
|||
# happens on travis |
|||
vms = 0 |
|||
return vms |
|||
|
|||
def _default_uid(self, cr, uid, context): |
|||
return uid |
|||
|
|||
def _default_thread(self, cr, uid, context): |
|||
return threading.current_thread().name |
|||
|
|||
def _class_count(self, cr, uid, context): |
|||
counts = {} |
|||
if context.get('_x_no_class_count'): |
|||
return [] |
|||
if context.get('_x_no_gc_collect'): |
|||
gc.collect() |
|||
gc.collect() |
|||
for obj in gc.get_objects(): |
|||
if isinstance(obj, BLACKLIST): |
|||
continue |
|||
try: |
|||
cls = obj.__class__ |
|||
except: |
|||
if isinstance(obj, types.ClassType): |
|||
cls = types.ClassType |
|||
else: |
|||
_logger.warning('unknown object type for %r (%s)', |
|||
obj, type(obj)) |
|||
continue |
|||
name = '%s.%s' % (cls.__module__, cls.__name__) |
|||
try: |
|||
counts[name] += 1 |
|||
except KeyError: |
|||
counts[name] = 1 |
|||
info = [] |
|||
for name, count in sorted(counts.items(), |
|||
key=itemgetter(1), |
|||
reverse=True): |
|||
if count < 2: |
|||
break |
|||
info.append({'name': name, 'count': count}) |
|||
return [(0, 0, val) for val in info] |
|||
|
|||
_defaults = { |
|||
'name': fields.datetime.now, |
|||
'class_count_ids': _class_count, |
|||
'pid': _default_pid, |
|||
'cpu_time': _default_cpu_time, |
|||
'memory': _default_memory, |
|||
'uid': _default_uid, |
|||
'thread': _default_thread, |
|||
} |
|||
|
|||
def log_measure(self, cr, uid, |
|||
model_name, method_name, info, |
|||
with_class_count=True, |
|||
gc_collect=True, |
|||
context=None): |
|||
if context is None: |
|||
context = {} |
|||
ctx = context.copy() |
|||
ctx.update({ |
|||
'_x_no_class_count': not with_class_count, |
|||
'_x_no_gc_collect': not gc_collect, |
|||
}) |
|||
fields = self._defaults.keys() |
|||
defaults = self.default_get(cr, uid, fields, context=ctx) |
|||
model_obj = self.pool['ir.model'] |
|||
model_id = model_obj.search(cr, uid, |
|||
[('name', '=', model_name)], |
|||
context=context) |
|||
if model_id: |
|||
model_id = model_id[0] |
|||
else: |
|||
model_id = 0 |
|||
values = {'model': model_id, |
|||
'method': method_name, |
|||
'info': info, |
|||
} |
|||
defaults.update(values) |
|||
|
|||
id = self.create(cr, SUPERUSER_ID, defaults, context=context) |
|||
return id |
|||
|
|||
def cleanup(self, cr, uid, age, context=None): |
|||
now = datetime.datetime.now() |
|||
delta = datetime.timedelta(days=age) |
|||
when = (now - delta).strftime(DEFAULT_SERVER_DATETIME_FORMAT) |
|||
ids = self.search(cr, uid, |
|||
[('name', '<', when)], |
|||
context=context) |
|||
_logger.debug('Process monitor cleanup: removing %d records', len(ids)) |
|||
self.unlink(cr, uid, ids, context=context) |
@ -0,0 +1,8 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_server_monitor_class_instance_count,access_server_monitor_class_instance_count,model_server_monitor_class_instance_count,base.group_no_one,1,0,1,0 |
|||
access_server_monitor_process,access_server_monitor_process,model_server_monitor_process,base.group_no_one,1,0,1,0 |
|||
access_server_monitor_model_row_count,access_server_monitor_model_row_count,model_server_monitor_model_row_count,base.group_no_one,1,0,1,0 |
|||
access_server_monitor_model_table_size,access_server_monitor_model_table_size,model_server_monitor_model_table_size,base.group_no_one,1,0,1,0 |
|||
access_server_monitor_model_table_activity_read,access_server_monitor_model_table_activity_read,model_server_monitor_model_table_activity_read,base.group_no_one,1,0,1,0 |
|||
access_server_monitor_model_table_activity_update,access_server_monitor_model_table_activity_update,model_server_monitor_model_table_activity_update,base.group_no_one,1,0,1,0 |
|||
access_server_monitor_database,access_server_monitor_database,model_server_monitor_database,base.group_no_one,1,0,1,0 |
@ -0,0 +1,64 @@ |
|||
- |
|||
I record a process log |
|||
- |
|||
!python {model: server.monitor.database}: | |
|||
id = self.log_measure(cr, uid, context=context) |
|||
- |
|||
there should be some server.monitor.model.row.count in database |
|||
- |
|||
!python {model: server.monitor.model.row.count}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert ids, 'No server.monitor.model.row.count instance count recorded' |
|||
- |
|||
there should be some server.monitor.model.table.size in database |
|||
- |
|||
!python {model: server.monitor.model.table.size}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert ids, 'No server.monitor.model.table.size recorded' |
|||
- |
|||
there should be some server.monitor.model.table.activity.read in database |
|||
- |
|||
!python {model: server.monitor.model.table.activity.read}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert ids, 'No server.monitor.model.table.activity.read recorded' |
|||
- |
|||
there should be some server.monitor.model.table.activity.update in database |
|||
- |
|||
!python {model: server.monitor.model.table.activity.update}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert ids, 'No server.monitor.model.table.activity.update recorded' |
|||
- |
|||
I cleanup the database logs |
|||
- |
|||
!python {model: server.monitor.database}: | |
|||
id = self.cleanup(cr, uid, -1, context=context) |
|||
- |
|||
there should be no server.monitor.model.row.count in database |
|||
- |
|||
!python {model: server.monitor.model.row.count}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'server.monitor.model.row.count still present' |
|||
- |
|||
there should be no server.monitor.model.table.size in database |
|||
- |
|||
!python {model: server.monitor.model.table.size}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'server.monitor.model.table.size still present' |
|||
- |
|||
there should be no server.monitor.model.table.activity.read in database |
|||
- |
|||
!python {model: server.monitor.model.table.activity.read}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'server.monitor.model.table.activity.read still present' |
|||
- |
|||
there should be no server.monitor.model.table.activity.update in database |
|||
- |
|||
!python {model: server.monitor.model.table.activity.update}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'server.monitor.model.table.activity.update still present' |
|||
- |
|||
there should be no server.monitor.database in database |
|||
- |
|||
!python {model: server.monitor.database}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'server.monitor.database still present' |
@ -0,0 +1,28 @@ |
|||
- |
|||
I record a process log |
|||
- |
|||
!python {model: server.monitor.process}: | |
|||
id = self.log_measure(cr, uid, None, None, 'test', context=context) |
|||
- |
|||
there should be some class instance counts in database |
|||
- |
|||
!python {model: server.monitor.class.instance.count}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert ids, 'No class instance count recorded' |
|||
- |
|||
I cleanup the process logs |
|||
- |
|||
!python {model: server.monitor.process}: | |
|||
id = self.cleanup(cr, uid, -1, context=context) |
|||
- |
|||
there should be no class instance count in database |
|||
- |
|||
!python {model: server.monitor.class.instance.count}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'Class instance count still present' |
|||
- |
|||
there should be no monitor process in database |
|||
- |
|||
!python {model: server.monitor.process}: | |
|||
ids = self.search(cr, uid, [], context=context) |
|||
assert not ids, 'server monitor process still present' |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<menuitem groups="base.group_no_one" |
|||
id="server_monitoring" |
|||
name="Server Monitoring" |
|||
parent="base.menu_reporting" |
|||
sequence="100"/> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,92 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_database_tree_view"> |
|||
<field name="name">Server Monitor Database form view</field> |
|||
<field name="model">server.monitor.database</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Server Monitor" version="7.0"> |
|||
<field name='name'/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_database_form_view"> |
|||
<field name="name">Server Monitor Database tree view</field> |
|||
<field name="model">server.monitor.database</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Server Monitor" version="7.0"> |
|||
<sheet> |
|||
<field name="name"/> |
|||
<notebook> |
|||
<page string="Nb rows"> |
|||
<group> |
|||
<field name='table_nb_row_ids' nolabel="1"> |
|||
<tree> |
|||
<field name='name'/> |
|||
<field name='count'/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
<page string="Table size"> |
|||
<group> |
|||
<field name='table_size_ids' nolabel="1"> |
|||
<tree> |
|||
<field name='name'/> |
|||
<field name='hsize'/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
<page string="Table reads"> |
|||
<group> |
|||
<field name='table_activity_read_ids' nolabel="1"> |
|||
<tree> |
|||
<field name='name'/> |
|||
<field name='disk_reads'/> |
|||
<field name='cache_reads'/> |
|||
<field name='total_reads'/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
<page string="Table updates"> |
|||
<group> |
|||
<field name='table_activity_update_ids' nolabel="1"> |
|||
<tree> |
|||
<field name='name'/> |
|||
<field name='seq_scan'/> |
|||
<field name='idx_scan'/> |
|||
<field name='lines_read_total'/> |
|||
<field name='num_insert'/> |
|||
<field name='num_update'/> |
|||
<field name='num_delete'/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
<group> |
|||
<field name='info' string="Information"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="server_monitor_database_info"> |
|||
<field name="name">Database Info</field> |
|||
<field name="res_model">server.monitor.database</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem name="Database Info" |
|||
parent="server_monitoring" |
|||
id="server_monitor_database_menu" |
|||
action="server_monitor_database_info" |
|||
sequence="20"/> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,91 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="server_monitor_model_table_activity_read_search_view"> |
|||
<field name="name">Server Monitor table activity updates search view</field> |
|||
<field name="model">server.monitor.model.table.activity.read</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search Server Monitor Table Activity read" version="7.0"> |
|||
<field name="timestamp"/> |
|||
<field name="name"/> |
|||
<group expand="0" string="Group By..."> |
|||
<filter string="timestamp" domain="[]" context="{'group_by': 'timestamp'}"/> |
|||
<filter string="name" domain="[]" context="{'group_by': 'name'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_model_table_activity_read_tree_view"> |
|||
<field name="name">Server Monitor table activity tree view</field> |
|||
<field name="model">server.monitor.model.table.activity.read</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Server Monitor DB Table activity" version="7.0"> |
|||
<field name='timestamp'/> |
|||
<field name='name'/> |
|||
<field name='disk_reads'/> |
|||
<field name='cache_reads'/> |
|||
<field name='total_reads'/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="server_monitor_database_table_activity_read"> |
|||
<field name="name">DB Reads</field> |
|||
<field name="res_model">server.monitor.model.table.activity.read</field> |
|||
<field name="view_mode">tree</field> |
|||
</record> |
|||
|
|||
<menuitem name="DB Reads" |
|||
parent="server_monitoring" |
|||
id="server_monitor_database_table_activity_read_menu" |
|||
action="server_monitor_database_table_activity_read" |
|||
sequence="50"/> |
|||
|
|||
|
|||
<record model="ir.ui.view" id="server_monitor_model_table_activity_update_search_view"> |
|||
<field name="name">Server Monitor table activity updates search view</field> |
|||
<field name="model">server.monitor.model.table.activity.update</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search Server Monitor Table Activity updates" version="7.0"> |
|||
<field name="timestamp"/> |
|||
<field name="name"/> |
|||
<group expand="0" string="Group By..."> |
|||
<filter string="timestamp" domain="[]" context="{'group_by': 'timestamp'}"/> |
|||
<filter string="name" domain="[]" context="{'group_by': 'name'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_model_table_activity_update_tree_view"> |
|||
<field name="name">Server Monitor table activity updates tree view</field> |
|||
<field name="model">server.monitor.model.table.activity.update</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Server Monitor DB Table size" version="7.0"> |
|||
<field name='timestamp'/> |
|||
<field name='name'/> |
|||
<field name='seq_scan'/> |
|||
<field name='idx_scan'/> |
|||
<field name='lines_read_total'/> |
|||
<field name='num_insert'/> |
|||
<field name='num_update'/> |
|||
<field name='num_delete'/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="server_monitor_database_table_activity_update"> |
|||
<field name="name">DB Updates</field> |
|||
<field name="res_model">server.monitor.model.table.activity.update</field> |
|||
<field name="view_mode">tree</field> |
|||
</record> |
|||
|
|||
<menuitem name="DB Updates" |
|||
parent="server_monitoring" |
|||
id="server_monitor_database_table_activity_update_menu" |
|||
action="server_monitor_database_table_activity_update" |
|||
sequence="60"/> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,43 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="server_monitor_model_row_count_search_view"> |
|||
<field name="name">Server Monitor model row count search view</field> |
|||
<field name="model">server.monitor.model.row.count</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search Server Monitor Process" version="7.0"> |
|||
<field name="timestamp"/> |
|||
<field name="name"/> |
|||
<field name="count"/> |
|||
<group expand="0" string="Group By..."> |
|||
<filter string="timestamp" domain="[]" context="{'group_by': 'timestamp'}"/> |
|||
<filter string="name" domain="[]" context="{'group_by': 'name'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_model_row_count_tree_view"> |
|||
<field name="name">Server Monitor model row count tree view</field> |
|||
<field name="model">server.monitor.model.row.count</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Server Monitor Process" version="7.0"> |
|||
<field name='timestamp'/> |
|||
<field name='name'/> |
|||
<field name='count'/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="server_monitor_database_table_rows"> |
|||
<field name="name">DB Rows</field> |
|||
<field name="res_model">server.monitor.model.row.count</field> |
|||
<field name="view_mode">tree</field> |
|||
</record> |
|||
|
|||
<menuitem name="DB Rows" |
|||
parent="server_monitoring" |
|||
id="server_monitor_database_table_rows_menu" |
|||
action="server_monitor_database_table_rows" sequence="30"/> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,44 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="server_monitor_model_table_size_search_view"> |
|||
<field name="name">Server Monitor model table size search view</field> |
|||
<field name="model">server.monitor.model.table.size</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search Server Monitor Table Row Count" version="7.0"> |
|||
<field name="timestamp"/> |
|||
<field name="name"/> |
|||
<group expand="0" string="Group By..."> |
|||
<filter string="timestamp" domain="[]" context="{'group_by': 'timestamp'}"/> |
|||
<filter string="name" domain="[]" context="{'group_by': 'name'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_model_table_size_tree_view"> |
|||
<field name="name">Server Monitor model table size tree view</field> |
|||
<field name="model">server.monitor.model.table.size</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Server Monitor DB Table Row Count" version="7.0"> |
|||
<field name='timestamp'/> |
|||
<field name='name'/> |
|||
<field name='hsize'/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="server_monitor_database_table_size"> |
|||
<field name="name">DB Table Size</field> |
|||
<field name="res_model">server.monitor.model.table.size</field> |
|||
<field name="view_mode">tree</field> |
|||
</record> |
|||
|
|||
<menuitem name="DB Table Size" |
|||
parent="server_monitoring" |
|||
id="server_monitor_database_table_size_menu" |
|||
action="server_monitor_database_table_size" |
|||
sequence="40"/> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,92 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="server_monitor_process_search_view"> |
|||
<field name="name">Server Monitor Process search view</field> |
|||
<field name="model">server.monitor.process</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search Server Monitor Process" version="7.0"> |
|||
<field name="model"/> |
|||
<field name="method"/> |
|||
<field name="uid"/> |
|||
<group expand="0" string="Group By..."> |
|||
<filter string="date" domain="[]" context="{'group_by': 'name'}"/> |
|||
<filter string="PID" domain="[]" context="{'group_by': 'pid'}"/> |
|||
<filter string="model" domain="[]" context="{'group_by': 'model'}"/> |
|||
<filter string="method" domain="[]" context="{'group_by': 'method'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_process_tree_view"> |
|||
<field name="name">Server Monitor Process tree view</field> |
|||
<field name="model">server.monitor.process</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Server Monitor Process" version="7.0"> |
|||
<field name='name'/> |
|||
<field name='pid'/> |
|||
<field name='cpu_time'/> |
|||
<field name='memory'/> |
|||
<field name='uid'/> |
|||
<field name='model'/> |
|||
<field name='method'/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="server_monitor_process_form_view"> |
|||
<field name="name">Server Monitor Process form view</field> |
|||
<field name="model">server.monitor.process</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Server Monitor" version="7.0"> |
|||
<sheet> |
|||
<field name="name"/> |
|||
<notebook> |
|||
<page string='call information'> |
|||
<group> |
|||
<field name='pid'/> |
|||
<field name='thread'/> |
|||
<field name='cpu_time'/> |
|||
<field name='memory'/> |
|||
<field name='uid'/> |
|||
<field name='model'/> |
|||
<field name='method'/> |
|||
<field name='status'/> |
|||
<field name='sessionid'/> |
|||
</group> |
|||
</page> |
|||
<page string="Class count"> |
|||
<group> |
|||
<field name='class_count_ids' nolabel="1"> |
|||
<tree> |
|||
<field name='name'/> |
|||
<field name='count'/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
<group> |
|||
<field name='info' string="Information"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
|
|||
<record model="ir.actions.act_window" id="server_monitor_process_info"> |
|||
<field name="name">Process Info</field> |
|||
<field name="res_model">server.monitor.process</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem name="Process Info" |
|||
parent="server_monitoring" |
|||
id="server_monitor_process_menu" |
|||
action="server_monitor_process_info" |
|||
sequence="10"/> |
|||
|
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue