Index: main/plugin-web/scripts/derby/jdbc_cache_mon.sql =================================================================== --- main/plugin-web/scripts/derby/jdbc_cache_mon.sql (revision 0) +++ main/plugin-web/scripts/derby/jdbc_cache_mon.sql (revision 0) @@ -0,0 +1,106 @@ +-- +-- Copyright 2013 Anyware Services +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +CREATE TABLE Cache_RA_HTTPServer ( + Unique_Id VARCHAR(31) NOT NULL, + Site VARCHAR(255) NOT NULL, + Request_Date TIMESTAMP NOT NULL, + Method VARCHAR(15) NOT NULL, + Path VARCHAR(255) NOT NULL, + Query_String VARCHAR(255) NOT NULL, + Ori_Status_Code CHAR(3) NOT NULL, + Ret_Status_Code CHAR(3) NOT NULL, + Cache_Hit SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed SMALLINT NOT NULL DEFAULT 0, + PRIMARY KEY (Unique_Id) +); + +CREATE TABLE Cache_RA_Front ( + Unique_Id VARCHAR(31) NOT NULL, + Internal_Uuid VARCHAR(63) NOT NULL, + Site VARCHAR(255) NOT NULL, + Ametys_Path VARCHAR(255) NOT NULL, + Cacheable SMALLINT NOT NULL, + Cache_Hit_1 SMALLINT NOT NULL, + Cache_Hit_2 SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed SMALLINT NOT NULL DEFAULT 0 +); + +CREATE TABLE Cache_RA_Back ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed SMALLINT NOT NULL DEFAULT 0 +); + +CREATE TABLE Cache_RA_Back_Page_Element ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Element_Type VARCHAR(31) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Cache_Hit SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed SMALLINT NOT NULL DEFAULT 0 +); + +CREATE TABLE Cache_Stats_Front ( + Server_Site VARCHAR(255) NOT NULL DEFAULT '-', + Server_Path VARCHAR(255) NOT NULL DEFAULT '-', + Server_Hits INT NOT NULL DEFAULT 0, + Server_Cache_Hits INT NOT NULL DEFAULT 0, + Front_Site VARCHAR(255) NOT NULL DEFAULT '-', + Front_Path VARCHAR(255) NOT NULL DEFAULT '-', + Front_Cacheable SMALLINT NOT NULL DEFAULT 0, + Front_Hits INT NOT NULL DEFAULT 0, + Front_Cache_Hits_1 INT NOT NULL DEFAULT 0, + Front_Cache_Hits_2 INT NOT NULL DEFAULT 0, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + UNIQUE (Server_Site, Server_Path, Front_Site, Front_Path) +); + +CREATE TABLE Cache_Stats_Back ( + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + PRIMARY KEY (Page_Id, Rendering_Context, Workspace_JCR) +); + +CREATE TABLE Cache_Stats_Back_Page_Element ( + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Hits INT NOT NULL, + Cache_Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + PRIMARY KEY (Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR) +); Index: main/plugin-web/scripts/oracle/jdbc_cache_mon.sql =================================================================== --- main/plugin-web/scripts/oracle/jdbc_cache_mon.sql (revision 0) +++ main/plugin-web/scripts/oracle/jdbc_cache_mon.sql (revision 0) @@ -0,0 +1,107 @@ +-- +-- Copyright 2013 Anyware Services +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +CREATE TABLE Cache_RA_HTTPServer ( + Unique_Id VARCHAR(31) NOT NULL, + Site VARCHAR(255) NOT NULL, + Request_Date TIMESTAMP NOT NULL, + Method VARCHAR(15) NOT NULL, + Path VARCHAR(255) NOT NULL, + Query_String VARCHAR(255) NOT NULL, + Ori_Status_Code CHAR(3) NOT NULL, + Ret_Status_Code CHAR(3) NOT NULL, + Cache_Hit NUMBER(1) NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed NUMBER(1) DEFAULT 0 NOT NULL, + PRIMARY KEY (Unique_Id) +); + + +CREATE TABLE Cache_RA_Front ( + Unique_Id VARCHAR(31) NOT NULL, + Internal_Uuid VARCHAR(63) NOT NULL, + Site VARCHAR(255) NOT NULL, + Ametys_Path VARCHAR(255) NOT NULL, + Cacheable NUMBER(1) NOT NULL, + Cache_Hit_1 NUMBER(1) NOT NULL, + Cache_Hit_2 NUMBER(1) NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed NUMBER(1) DEFAULT 0 NOT NULL +); + +CREATE TABLE Cache_RA_Back ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable NUMBER(1) NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed NUMBER(1) DEFAULT 0 NOT NULL +); + +CREATE TABLE Cache_RA_Back_Page_Element ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Element_Type VARCHAR(31) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable NUMBER(1) NOT NULL, + Cache_Hit NUMBER(1) NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed NUMBER(1) DEFAULT 0 NOT NULL +); + +CREATE TABLE Cache_Stats_Front ( + Server_Site VARCHAR(255) DEFAULT '-' NOT NULL, + Server_Path VARCHAR(255) DEFAULT '-' NOT NULL, + Server_Hits INT DEFAULT 0 NOT NULL, + Server_Cache_Hits INT DEFAULT 0 NOT NULL, + Front_Site VARCHAR(255) DEFAULT '-' NOT NULL, + Front_Path VARCHAR(255) DEFAULT '-' NOT NULL, + Front_Cacheable NUMBER(1) DEFAULT 0 NOT NULL, + Front_Hits INT DEFAULT 0 NOT NULL, + Front_Cache_Hits_1 INT DEFAULT 0 NOT NULL, + Front_Cache_Hits_2 INT DEFAULT 0 NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + UNIQUE (Server_Site, Server_Path, Front_Site, Front_Path) +); + +CREATE TABLE Cache_Stats_Back ( + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable NUMBER(1) NOT NULL, + Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + PRIMARY KEY (Page_Id, Rendering_Context, Workspace_JCR) +); + +CREATE TABLE Cache_Stats_Back_Page_Element ( + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable NUMBER(1) NOT NULL, + Hits INT NOT NULL, + Cache_Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + PRIMARY KEY (Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR) +); Index: main/plugin-web/scripts/postgresql/jdbc_cache_mon.sql =================================================================== --- main/plugin-web/scripts/postgresql/jdbc_cache_mon.sql (revision 0) +++ main/plugin-web/scripts/postgresql/jdbc_cache_mon.sql (revision 0) @@ -0,0 +1,119 @@ +-- +-- Copyright 2013 Anyware Services +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +BEGIN; + +drop table if exists Cache_RA_HTTPServer; +CREATE TABLE Cache_RA_HTTPServer ( + Unique_Id VARCHAR(31) NOT NULL, + Site VARCHAR(255) NOT NULL, + Request_Date TIMESTAMP NOT NULL, + Method VARCHAR(15) NOT NULL, + Path VARCHAR(255) NOT NULL, + Query_String VARCHAR(255) NOT NULL, + Ori_Status_Code CHAR(3) NOT NULL, + Ret_Status_Code CHAR(3) NOT NULL, + Cache_Hit SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed SMALLINT NOT NULL DEFAULT 0, + PRIMARY KEY (Unique_Id) +); + + +drop table if exists Cache_RA_Front; +CREATE TABLE Cache_RA_Front ( + Unique_Id VARCHAR(31) NOT NULL, + Internal_Uuid VARCHAR(63) NOT NULL, + Site VARCHAR(255) NOT NULL, + Ametys_Path VARCHAR(255) NOT NULL, + Cacheable SMALLINT NOT NULL, + Cache_Hit_1 SMALLINT NOT NULL, + Cache_Hit_2 SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed SMALLINT NOT NULL DEFAULT 0 +); + +drop table if exists Cache_RA_Back; +CREATE TABLE Cache_RA_Back ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed SMALLINT NOT NULL DEFAULT 0 +); + +drop table if exists Cache_RA_Back_Page_Element; +CREATE TABLE Cache_RA_Back_Page_Element ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Element_Type VARCHAR(31) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Cache_Hit SMALLINT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Processed SMALLINT NOT NULL DEFAULT 0 +); + +drop table if exists Cache_Stats_Front; +CREATE TABLE Cache_Stats_Front ( + Server_Site VARCHAR(255) NOT NULL DEFAULT '-', + Server_Path VARCHAR(255) NOT NULL DEFAULT '-', + Server_Hits INT NOT NULL DEFAULT 0, + Server_Cache_Hits INT NOT NULL DEFAULT 0, + Front_Site VARCHAR(255) NOT NULL DEFAULT '-', + Front_Path VARCHAR(255) NOT NULL DEFAULT '-', + Front_Cacheable SMALLINT NOT NULL DEFAULT 0, + Front_Hits INT NOT NULL DEFAULT 0, + Front_Cache_Hits_1 INT NOT NULL DEFAULT 0, + Front_Cache_Hits_2 INT NOT NULL DEFAULT 0, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + UNIQUE (Server_Site, Server_Path, Front_Site, Front_Path) +); + +drop table if exists Cache_Stats_Back; +CREATE TABLE Cache_Stats_Back ( + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + PRIMARY KEY (Page_Id, Rendering_Context, Workspace_JCR) +); + +drop table if exists Cache_Stats_Back_Page_Element; +CREATE TABLE Cache_Stats_Back_Page_Element ( + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable SMALLINT NOT NULL, + Hits INT NOT NULL, + Cache_Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL, + Updated_At TIMESTAMP NOT NULL, + PRIMARY KEY (Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR) +); + +COMMIT; Index: main/plugin-web/scripts/mysql/jdbc_cache_mon.sql =================================================================== --- main/plugin-web/scripts/mysql/jdbc_cache_mon.sql (revision 0) +++ main/plugin-web/scripts/mysql/jdbc_cache_mon.sql (revision 0) @@ -0,0 +1,114 @@ +-- +-- Copyright 2013 Anyware Services +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +drop table if exists Cache_RA_HTTPServer; +CREATE TABLE Cache_RA_HTTPServer ( + Unique_Id VARCHAR(31) NOT NULL, + Site VARCHAR(255) NOT NULL, + Request_Date TIMESTAMP NOT NULL, + Method VARCHAR(15) NOT NULL, + Path VARCHAR(255) NOT NULL, + Query_String VARCHAR(255) NOT NULL, + Ori_Status_Code CHAR(3) NOT NULL, + Ret_Status_Code CHAR(3) NOT NULL, + Cache_Hit TINYINT(1) NOT NULL, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (Unique_Id) +) ENGINE=InnoDB; + + +drop table if exists Cache_RA_Front; +CREATE TABLE Cache_RA_Front ( + Unique_Id VARCHAR(31) NOT NULL, + Internal_Uuid VARCHAR(63) NOT NULL, + Site VARCHAR(255) NOT NULL, + Ametys_Path VARCHAR(255) NOT NULL, + Cacheable TINYINT(1) NOT NULL, + Cache_Hit_1 TINYINT(1) NOT NULL, + Cache_Hit_2 TINYINT(1) NOT NULL, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed TINYINT(1) NOT NULL DEFAULT 0 +) ENGINE=InnoDB; + +drop table if exists Cache_RA_Back; +CREATE TABLE Cache_RA_Back ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable TINYINT(1) NOT NULL, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed TINYINT(1) NOT NULL DEFAULT 0 +) ENGINE=InnoDB; + +drop table if exists Cache_RA_Back_Page_Element; +CREATE TABLE Cache_RA_Back_Page_Element ( + Internal_Uuid VARCHAR(63) NOT NULL, + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Element_Type VARCHAR(31) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable TINYINT(1) NOT NULL, + Cache_Hit TINYINT(1) NOT NULL, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Processed TINYINT(1) NOT NULL DEFAULT 0 +) ENGINE=InnoDB; + +drop table if exists Cache_Stats_Front; +CREATE TABLE Cache_Stats_Front ( + Server_Site VARCHAR(255) NOT NULL DEFAULT '-', + Server_Path VARCHAR(255) NOT NULL DEFAULT '-', + Server_Hits INT NOT NULL DEFAULT 0, + Server_Cache_Hits INT NOT NULL DEFAULT 0, + Front_Site VARCHAR(255) NOT NULL DEFAULT '-', + Front_Path VARCHAR(255) NOT NULL DEFAULT '-', + Front_Cacheable TINYINT(1) NOT NULL DEFAULT 0, + Front_Hits INT NOT NULL DEFAULT 0, + Front_Cache_Hits_1 INT NOT NULL DEFAULT 0, + Front_Cache_Hits_2 INT NOT NULL DEFAULT 0, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Updated_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + UNIQUE KEY (Server_Site, Server_Path, Front_Site, Front_Path) +) ENGINE=InnoDB; + +drop table if exists Cache_Stats_Back; +CREATE TABLE Cache_Stats_Back ( + Page_Id VARCHAR(63) NOT NULL, + Page_Path VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable TINYINT(1) NOT NULL, + Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Updated_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + PRIMARY KEY (Page_Id, Rendering_Context, Workspace_JCR) +) ENGINE=InnoDB; + +drop table if exists Cache_Stats_Back_Page_Element; +CREATE TABLE Cache_Stats_Back_Page_Element ( + Page_Element_Id VARCHAR(63) NOT NULL, + Page_Id VARCHAR(63) NOT NULL, + Rendering_Context VARCHAR(15) NOT NULL, + Workspace_JCR VARCHAR(15) NOT NULL, + Cacheable TINYINT(1) NOT NULL, + Hits INT NOT NULL, + Cache_Hits INT NOT NULL, + Created_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + Updated_At TIMESTAMP NOT NULL DEFAULT 0, -- The DEFAULT clause prevents weird auto update (See Mysql doc) + PRIMARY KEY (Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR) +) ENGINE=InnoDB; Index: main/plugin-web/i18n/messages_en.xml =================================================================== --- main/plugin-web/i18n/messages_en.xml (revision 20673) +++ main/plugin-web/i18n/messages_en.xml (working copy) @@ -290,6 +290,20 @@ <message key="PLUGINS_WEB_FO_LOGIN_NO_ACCOUNT">You don't have an account?</message> <!-- + + | CACHE MONITORING + + --> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY">Cache Monitoring</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_GROUP">Monitoring database connection</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_DRIVER_LABEL">Driver</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_DRIVER_DESCRIPTION">JDBC Driver fully qualified class name</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_URL_LABEL">Url</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_URL_DESCRIPTION">JDBC URL for connecting to the database</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_USER_LABEL">User</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_USER_DESCRIPTION">User name for connecting to the database</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_PASSWORD_LABEL">Password</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_PASSWORD_DESCRIPTION">Password associated with the user name for connecting to the database</message> + + <!-- + | SITES CONFIGURATION + --> <message key="PLUGINS_WEB_SITE_INFORMATION_CATEGORY">General information</message> @@ -326,6 +340,8 @@ <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CONFIG">Configure</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_STATISTICS">Site statistics</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_GLOBAL_STATISTICS">Global statistics</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CACHE_BACK_STATISTICS">Cache back statistics</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CACHE_SERVERS_STATISTICS">Cache front statistics</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_DELETE">Delete</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_OPEN">Open website as a contributor</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_NEW">New site</message> @@ -449,7 +465,47 @@ <message key="PLUGINS_WEB_ADMINISTRATOR_GLOBAL_STATISTICS_VALUE_CONTENTS_SITECONTENTS">Content count in all the sites</message> <message key="PLUGINS_WEB_ADMINISTRATOR_GLOBAL_STATISTICS_RESOURCES">Resource explorer</message> <message key="PLUGINS_WEB_ADMINISTRATOR_GLOBAL_STATISTICS_PAGES">Pages</message> - + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_LOAD_MESSAGE">Loading statistics, please wait...</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE">Actions</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_REINITIALIZE">Reinitialize the statistics</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_QUIT">Quit</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HELP">Help</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_TITLE">Statistics of the caches for the site {name} (back)</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_RELOAD_BTN_LABEL">Reload</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_HELP_TEXT">This screen displays some statistics about pages and page elements on the back-office.<br/><br/> \ + Statistics can be filtered by context (couple rendering context - workspace JCR).<br/>Thus, it is possible to select or deselect contexts and then reload the table by clicking on the 'reload' bouton.<br/><br/> \ + Statistics columns are grouped by category ('page' or 'page element').<br/>The 'cacheable' column represent the rate of page elements that are cacheable, weighted by element hits.<br/>This way, the rates 'cacheable' and 'efficiency' can be directly compared.</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_FIRST_ROWHD_PAGE">Pages</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_FIRST_ROWHD_PAGE_ELEMENT">Page elements</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_FIRST">Title</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_PAGE_HITS">Hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_CACHEABLE">Cacheable</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_EFFICIENCY">Efficiency</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_HITS">Hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_CACHE_HITS">Cache hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_TITLE">Statistics of the caches for the site {name} (front)</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_HELP_TEXT">This screen displays statistics of the caches use on the front-office.<br/><br/> \ + It is possible to get more information by clicking on the appropriate button in the action menu.<br/>You will get the detailed statistics for Apache and the front-offiche.<br/><br/> \ + As it is for the back-office statistics, the 'cacheable' rate is weighted by the number of hits.</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_HANDLE_DISPLAY_HIDE">Display/Hide details</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_FIRST">Main</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_EFFICIENCY">Efficiency</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_HITS">Hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_CACHE_HITS">Cache hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_BACK">Back</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_FIRST">Titre</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHEABLE">Cacheable</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_TOTAL">Total</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_APACHE">Apache</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_FRONT">Front</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_TOTAL">Total</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_APACHE">Apache</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_FRONT">Front</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_TOTAL">Total</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_APACHE">Apache</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_FRONT">Front</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_BACK">Hits</message> + <!-- + | SKIN ADMINISTRATION + --> @@ -457,6 +513,7 @@ <message key="PLUGINS_WEB_ADMINISTRATOR_SKINS_DESCRIPTION">Skins management</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SKINS_TITLE">Skins management</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SKINS_HANDLE">Actions</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_SKINS_HANDLE_IMPORT_ZIP">Import a Ametys skin</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SKINS_HANDLE_IMPORT_ZIP_DESC">Import a Ametys skin from a ZIP file</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SKINS_HANDLE_EXPORT_ZIP">Export to ZIP format</message> Index: main/plugin-web/i18n/messages_fr.xml =================================================================== --- main/plugin-web/i18n/messages_fr.xml (revision 20673) +++ main/plugin-web/i18n/messages_fr.xml (working copy) @@ -290,6 +290,20 @@ <message key="PLUGINS_WEB_FO_LOGIN_NO_ACCOUNT">Vous n'avez pas de compte ?</message> <!-- + + | CACHE MONITORING + + --> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY">Monitoring Cache</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_GROUP">Connexion à la base de données de monitoring</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_DRIVER_LABEL">Pilote</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_DRIVER_DESCRIPTION">Nom complet de la classe driver JDBC à charger</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_URL_LABEL">Url</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_URL_DESCRIPTION">Url JDBC de connexion au serveur de base de données</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_USER_LABEL">Utilisateur</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_USER_DESCRIPTION">Nom d'utilisateur à utiliser lors de la connexion au serveur de base de données</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_PASSWORD_LABEL">Mot de passe</message> + <message key="PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_PASSWORD_DESCRIPTION">Mot de passe associé au nom d'utilisateur à utiliser lors de la connexion au serveur de base de données</message> + + <!-- + | SITES CONFIGURATION + --> <message key="PLUGINS_WEB_SITE_INFORMATION_CATEGORY">Informations générales</message> @@ -326,6 +340,8 @@ <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CONFIG">Configurer</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_STATISTICS">Statistiques du site</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_GLOBAL_STATISTICS">Statistiques globales</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CACHE_BACK_STATISTICS">Statistiques du cache (back)</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CACHE_SERVERS_STATISTICS">Statistiques du cache (front)</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_DELETE">Supprimer</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_OPEN">Ouvrir dans le CMS</message> <message key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_NEW">Nouveau site</message> @@ -449,6 +465,46 @@ <message key="PLUGINS_WEB_ADMINISTRATOR_GLOBAL_STATISTICS_VALUE_CONTENTS_SITECONTENTS">Nombre de contenus dans l'ensemble des sites</message> <message key="PLUGINS_WEB_ADMINISTRATOR_GLOBAL_STATISTICS_RESOURCES">Explorateur de ressources</message> <message key="PLUGINS_WEB_ADMINISTRATOR_GLOBAL_STATISTICS_PAGES">Pages</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_LOAD_MESSAGE">Chargement des statistiques, veuillez patienter...</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE">Actions</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_REINITIALIZE">Réinitialiser les stats</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_QUIT">Quitter</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HELP">Aide</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_TITLE">Statistiques des caches pour le site {name} (back)</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_RELOAD_BTN_LABEL">Recharger</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_HELP_TEXT">Ce tableau centralise les statistiques d'accès aux pages et éléments des pages sur le back-office.<br/><br/> \ + Les statistiques peuvent être filtrées par contexte (couple contexte de rendu - workspace JCR).<br/>Ainsi il est possible de sélectionner ou désélectionner des contextes puis de recharger le tableau à l'aide du bouton 'recharger'.<br/><br/> \ + Les statistiques sont regroupées selon qu'elles se rapportent aux pages ou aux éléments des pages.<br/>La colonne 'cacheable' représente le taux d'éléments des pages qui sont cacheables, pondéré par le nombre de hits par élément.<br/>En conséquence, les taux 'cacheable' et 'efficacité' peuvent être comparés directement.</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_FIRST_ROWHD_PAGE">Pages</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_FIRST_ROWHD_PAGE_ELEMENT">Eléments des pages</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_FIRST">Titre</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_PAGE_HITS">Hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_CACHEABLE">Cacheable</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_EFFICIENCY">Efficacité</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_HITS">Hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_CACHE_HITS">Cache hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_TITLE">Statistiques des caches pour le site {name} (front)</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_HELP_TEXT">Ce tableau centralise les statistiques d'utilisation des caches côté front-office.<br/><br/> \ + Il est possible d'afficher plus d'informations en cliquant sur le bouton approprié dans le menu des actions.<br/>Vous obtiendrez le détails des statistiques pour Apache et le front-office.<br/><br/> \ + Comme pour les statistique côté back-office, le taux 'cacheable' est pondéré par le nombre de hits.</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_HANDLE_DISPLAY_HIDE">Afficher/Masquer détails</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_FIRST">Général</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_EFFICIENCY">Efficacité</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_HITS">Hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_CACHE_HITS">Cache hits</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_BACK">Back</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_FIRST">Titre</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHEABLE">Cacheable</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_TOTAL">Total</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_APACHE">Apache</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_FRONT">Front</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_TOTAL">Total</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_APACHE">Apache</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_FRONT">Front</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_TOTAL">Total</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_APACHE">Apache</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_FRONT">Front</message> + <message key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_BACK">Hits</message> <!-- + | SKIN ADMINISTRATION Index: main/plugin-web/resources/js/org/ametys/web/administration/CacheStatisticsBack.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/administration/CacheStatisticsBack.i18n.js (revision 0) +++ main/plugin-web/resources/js/org/ametys/web/administration/CacheStatisticsBack.i18n.js (revision 0) @@ -0,0 +1,226 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.namespace('org.ametys.web.administration'); + +org.ametys.web.administration.CacheStatisticsBack = function () {} + +org.ametys.web.administration.CacheStatisticsBack.init = function (pluginName, siteName, sitePath) +{ + this.pluginName = pluginName; + this.siteName = siteName; + this.sitePath = sitePath; + + // Contexts (that can be filtered) + this._contexts = [ + 'back-default', + 'front-live', + 'preview-default', + 'preview-live' + ]; + + // init tb + var toolbar = this._initToolbar(); + + // init loader + this._loader = new Ext.ux.tree.XmlTreeLoader({ + dataUrl: getPluginDirectUrl(this.pluginName) + '/administrator/sites/' + siteName + '/cache-statistics-back-tree.xml', + baseParams: { + contexts : this._contexts.join('#') + } + }); + + // loader listeners + this._loader.on('beforeload', this._beforeLoadStats, this); + this._loader.on('load', this._loadStats, this); + + + this._grid = new org.ametys.web.administration.cacheStatistics.DoubleHeaderTreeGrid({ + /* width: 610,*/ + region: 'center', + enableDD: false, + enableHdMenu: false, + enableSort: false, + border: false, + firstRowHd:[ + {colspan: 1, align: 'center'}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_FIRST_ROWHD_PAGE"/>", colspan: 1, align: 'center'}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_FIRST_ROWHD_PAGE_ELEMENT"/>", colspan: 4, align: 'center'} + ], + columns:[ + // total width must be 590 + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_FIRST"/>", dataIndex: 'label', width: 280}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_PAGE_HITS"/>", dataIndex: 'pageHits', align: 'center', width: 50}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_CACHEABLE"/>", dataIndex: 'cacheable', align: 'center', width: 70}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_EFFICIENCY"/>", dataIndex: 'eff', align: 'center', width: 70}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_HITS"/>", dataIndex: 'hits', align: 'center', width: 50}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_COL_CACHE_HITS"/>", dataIndex: 'cacheHits', align: 'center', width: 70} + ], + loader: this._loader, + tbar: toolbar + }); + + this._centerPanel = new Ext.Panel({ + region:'center', + layout: 'border', + baseCls: 'transparent-panel', + border: false, + autoScroll : true, + height: 'auto', + items: [this._grid] + }); + + // Handle box + this._handle = new org.ametys.ActionsPanel({title: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE"/>"}); + // Not available currenlty. +// this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_REINITIALIZE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/cachestats/reinitialize.png", org.ametys.web.administration.cacheStatistics._reinitializeStats); + // Quit action + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_QUIT"/>", getPluginResourcesUrl('core') + '/img/administrator/config/quit.png', org.ametys.web.administration.cacheStatistics._goBack.createDelegate(this)); + + // Help box + var help = new org.ametys.TextPanel({title: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HELP"/>"}); + help.addText("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_HELP_TEXT"/>"); + + this._rightPanel = new org.ametys.HtmlContainer({ + region:'east', + border: false, + cls: 'admin-right-panel', + width: 277, + items: [this._handle, help] + }); +} + +org.ametys.web.administration.CacheStatisticsBack._initToolbar = function() +{ + var self = this; + + // Toolbar btn abstraction + var ContextItem = function(context, pressed) { + var res = context.split('-'), + renderingCtx = res[0], + workspace= res[1]; + + return new Ext.Button({ + text: renderingCtx + '/' + workspace, + enableToggle: true, + toggleHandler: self._onContextItemToggle, + scope: self, + 'context': context, + 'renderingCtx': renderingCtx, + 'workspace': workspace, + 'pressed': pressed + }); + } + + // Construct toolbar btn depending on contexts. + var items = []; + for (var c in this._contexts) { + if (Object.prototype.hasOwnProperty.call(this._contexts, c)) { + if (c > 0) items.push(' '); // toolbar spacer + items.push(ContextItem(this._contexts[c], true)); + } + } + + // Reload stats btn + items.push('-'); + items.push(new Ext.Button({ + text: '<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_RELOAD_BTN_LABEL"/>', + handler: this._reload, + scope: this + })); + + return new Ext.Toolbar({ + items: items + }); +} + +org.ametys.web.administration.CacheStatisticsBack._onContextItemToggle = function(item, pressed) +{ + // add/remove context in the contexts array + if (pressed) { + if (this._contexts.indexOf(item.context) === -1) { + this._contexts.push(item.context); + } + } + else { + // Array.remove shim + var index = this._contexts.indexOf(item.context); + if (index !== -1) { + this._contexts.splice(index, 1); + } + } +} + +org.ametys.web.administration.CacheStatisticsBack._reload = function(button, event) +{ + this._loader.load(this._grid.getRootNode()); +} + +org.ametys.web.administration.CacheStatisticsBack._beforeLoadStats = function(loader, node) +{ + this._statsMask = new org.ametys.msg.Mask(Ext.get('admin-panel'), "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_LOAD_MESSAGE"/>"); + + // remember selected node to be able to re-expand it. + this._selectedNodeId = (this._grid.getSelectionModel().getSelectedNode() || {}).id + + // contexts param passed to the server. + this._loader.baseParams.contexts = this._contexts.join('#'); +}; + +org.ametys.web.administration.CacheStatisticsBack._loadStats = function(loader, node) +{ + if (this._statsMask) + { + this._statsMask.hide(); + } + + // Recursive expand for node that are marked as recursive in the loaded XML. + if (node.isRoot) + { + org.ametys.web.administration.cacheStatistics._recursiveExpand(node); + } + + // Recursive expand to the node that was selected before a reload (if still existing). + // This node is also selected again. + if (this._selectedNodeId) + { + var selectedNode = this._grid.getNodeById(this._selectedNodeId); + var selectedParentNode = (selectedNode || {}).parentNode; + + if (selectedParentNode) + { + this._recursiveExpandToSelected(selectedParentNode); + } + + if (selectedNode) + { + this._grid.getSelectionModel().select(selectedNode); + } + } +}; + +org.ametys.web.administration.CacheStatisticsBack._recursiveExpandToSelected = function(node) +{ + if (node !== null && node !== undefined) + { + this._recursiveExpandToSelected(node.parentNode); + + if (!node.isExpanded() && node !== this._grid.getRootNode()) + { + node.expand(false, true); + } + } +}; Index: main/plugin-web/resources/js/org/ametys/web/administration/CacheStatisticsServers.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/administration/CacheStatisticsServers.i18n.js (revision 0) +++ main/plugin-web/resources/js/org/ametys/web/administration/CacheStatisticsServers.i18n.js (revision 0) @@ -0,0 +1,164 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.namespace('org.ametys.web.administration'); + +org.ametys.web.administration.CacheStatisticsServers = function () {} + +org.ametys.web.administration.CacheStatisticsServers.init = function (pluginName, siteName, sitePath) +{ + this.pluginName = pluginName; + this.siteName = siteName; + this.sitePath = sitePath; + + // init loader + this._loader = new Ext.ux.tree.XmlTreeLoader({ + dataUrl: getPluginDirectUrl(this.pluginName) + '/administrator/sites/' + siteName + '/cache-statistics-servers-tree.xml' + }); + + // loader listeners + this._loader.on('beforeload', this._beforeLoadStats, this); + this._loader.on('load', this._loadStats, this); + + var columns = [ + // total width must be 590 + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_FIRST"/>", dataIndex: 'label', width: 260}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHEABLE"/>", dataIndex: 'cacheable', align: 'center', width: 70}, + + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_TOTAL"/>", dataIndex: 'eff', align: 'center', width: 70}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_APACHE"/>", dataIndex: 'effA', align: 'center', width: 50, hidden: true}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_EFFICIENCY_FRONT"/>", dataIndex: 'effF', align: 'center', width: 50, hidden: true}, + + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_TOTAL"/>", dataIndex: 'hits', align: 'center', width: 70}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_APACHE"/>", dataIndex: 'hitsA', align: 'center', width: 50, hidden: true}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_FRONT"/>", dataIndex: 'hitsF', align: 'center', width: 50, hidden: true}, + + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_TOTAL"/>", dataIndex: 'cacheHits', align: 'center', width: 70}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_APACHE"/>", dataIndex: 'cacheHitsA', align: 'center', width: 50, hidden: true}, + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_CACHE_HITS_FRONT"/>", dataIndex: 'cacheHitsF', align: 'center', width: 50, hidden: true}, + + { header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_COL_HITS_BACK"/>", dataIndex: 'hitsB', align: 'center', width: 50} + ]; + + this._detailsColsIndex = []; + this._detailsVisible = false; // Indicates whether the 'details' columns are visible. + + // Populate the _detailsColsIndex with the index of the hidden columns. + // This means that these column are 'details' column. A special action + // button will be created to be able to display/hide details columns. + Ext.each(columns, function(item, index) { + if (item.hidden === true) this._detailsColsIndex.push(index); + }, this); + + // maps colspan attributes of the td of the firstrow given the boolean this._detailsVisible. + /* + this._firstRowColspans = { + 'false': [2, 1, 1, 1, 1], + 'true': [2, 3, 3, 3, 1] + } + */ + + this._grid = new org.ametys.web.administration.cacheStatistics.DoubleHeaderTreeGrid({ + /* width: 610,*/ + region: 'center', + enableDD: false, + enableHdMenu: false, + enableSort: false, + border: false, + firstRowHd:[ + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_FIRST"/>", colspan: 2, align: 'center'}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_EFFICIENCY"/>", colspan: 3, align: 'center'}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_HITS"/>", colspan: 3, align: 'center'}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_CACHE_HITS"/>", colspan: 3, align: 'center'}, + {header: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_FIRST_ROWHD_BACK"/>", colspan: 1, align: 'center'} + ], + columns: columns, + loader: this._loader + }); + + this._centerPanel = new Ext.Panel({ + region:'center', + layout: 'border', + baseCls: 'transparent-panel', + border: false, + autoScroll : true, + height: 'auto', + items: [this._grid] + }); + + // Handle box + this._handle = new org.ametys.ActionsPanel({title: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE"/>"}); + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_HANDLE_DISPLAY_HIDE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/cachestats/displayhide.png", org.ametys.web.administration.CacheStatisticsServers._displayHideDetails.createDelegate(this)); + // Not available currenlty. +// this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_REINITIALIZE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/cachestats/reinitialize.png", org.ametys.web.administration.cacheStatistics._reinitializeStats); + // Quit action + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HANDLE_QUIT"/>", getPluginResourcesUrl('core') + '/img/administrator/config/quit.png', org.ametys.web.administration.cacheStatistics._goBack.createDelegate(this)); + + // Help box + var help = new org.ametys.TextPanel({title: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_HELP"/>"}); + help.addText("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_HELP_TEXT"/>"); + + this._rightPanel = new org.ametys.HtmlContainer({ + region:'east', + border: false, + cls: 'admin-right-panel', + width: 277, + items: [this._handle, help] + }); +} + +org.ametys.web.administration.CacheStatisticsServers._reload = function(button, event) +{ + this._loader.load(this._grid.getRootNode()); +} + +org.ametys.web.administration.CacheStatisticsServers._beforeLoadStats = function(loader, node) +{ + this._statsMask = new org.ametys.msg.Mask(Ext.get('admin-panel'), "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_STATISTICS_LOAD_MESSAGE"/>"); +}; + +org.ametys.web.administration.CacheStatisticsServers._loadStats = function(loader, node) +{ + if (this._statsMask) + { + this._statsMask.hide(); + } + + // Recursive expand for node that are marked as recursive in the loaded XML. + if (node.isRoot) + { + org.ametys.web.administration.cacheStatistics._recursiveExpand(node); + } +}; + +/**-----------------------------------------------------------*/ + +org.ametys.web.administration.CacheStatisticsServers._displayHideDetails = function() +{ + this._detailsVisible = !this._detailsVisible; + + Ext.each(this._detailsColsIndex, function(detailsColIndex) { + this._grid.setColumnVisible(detailsColIndex, this._detailsVisible); + }, this); + + // updating colspans of the first hd row + /* + var colspanMapping = this._firstRowColspans['' + this._detailsVisible]; + Ext.each(this._grid.body.query('.custom-hd-row'), function(td, index) { + td.setAttribute('colspan', colspanMapping[index]); + }); + */ +} Index: main/plugin-web/resources/js/org/ametys/web/administration/CacheStatistics.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/administration/CacheStatistics.i18n.js (revision 0) +++ main/plugin-web/resources/js/org/ametys/web/administration/CacheStatistics.i18n.js (revision 0) @@ -0,0 +1,164 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.namespace('org.ametys.web.administration.cacheStatistics'); + +org.ametys.web.administration.cacheStatistics._recursiveExpand = function(node) +{ + var cs = node.childNodes, + i, + len = cs.length; + + for (i = 0; i < len; i++) + { + if (cs[i].attributes.expanded == 'true') + { + cs[i].expand(false, true, org.ametys.web.administration.cacheStatistics._recursiveExpand); + } + } +}; + +org.ametys.web.administration.cacheStatistics._reinitializeStats = function() +{ + Ext.Msg.show({ + title: "Not available", + msg: "This feature is not implemented yet.", + buttons: Ext.Msg.OK, + icon: Ext.Msg.WARNING + }); +} + +org.ametys.web.administration.cacheStatistics._goBack = function() +{ + document.location.href = getPluginWrappedUrl('web') + '/administrator/sites/view.html' + (this.sitePath ? '?path=' + this.sitePath : ''); +} + +org.ametys.web.administration.cacheStatistics.DoubleHeaderTreeGrid = Ext.extend(Ext.ux.tree.TreeGrid, { + firstRowHd : [], + + initComponent : function() { + this.internalTpl = new Ext.XTemplate( + '<div class="x-grid3-header">', + '<div class="x-treegrid-header-inner">', + '<div class="x-grid3-header-offset">', + '<table style="table-layout: fixed;" cellspacing="0" cellpadding="0" border="0"><colgroup><tpl for="columns"><col /></tpl></colgroup>', + '<thead><tr class="x-grid3-hd-row">', + + // Template modification, adding a new header row, that will be filled with the 'firstRowHd' array. + '<tpl for="firstRowHd">', + '<td class="custom-hd-row" style="text-align: {align};" colspan="{colspan}" >', + '<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">', + '{header}', + '</div>', + '</td></tpl>', + '</tr>', + + '<tr class="x-grid3-hd-row">', + '<tpl for="columns">', + // adding the 'standard-hd-row' class (used in the overridden method updateColumnWidths, see below) + '<td class="standard-hd-row x-grid3-hd x-grid3-cell x-treegrid-hd" style="text-align: {align};" id="', this.id, '-xlhd-{#}">', + '<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">', + this.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '', + '{header}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />', + '</div>', + '</td></tpl>', + '</tr></thead>', + '</table>', + '</div></div>', + '</div>', + '<div class="x-treegrid-root-node">', + '<table class="x-treegrid-root-table" cellpadding="0" cellspacing="0" style="table-layout: fixed;"></table>', + '</div>' + ); + + org.ametys.web.administration.cacheStatistics.DoubleHeaderTreeGrid.superclass.initComponent.call(this); + }, + + onRender : function() { + Ext.tree.TreePanel.superclass.onRender.apply(this, arguments); + + this.el.addClass('x-treegrid'); + + this.outerCt = this.body.createChild({ + cls:'x-tree-root-ct x-treegrid-ct ' + (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines') + }); + + // Adding firstRowHd to the template + this.internalTpl.overwrite(this.outerCt, {columns: this.columns, firstRowHd: this.firstRowHd}); + + this.mainHd = Ext.get(this.outerCt.dom.firstChild); + this.innerHd = Ext.get(this.mainHd.dom.firstChild); + this.innerBody = Ext.get(this.outerCt.dom.lastChild); + this.innerCt = Ext.get(this.innerBody.dom.firstChild); + + this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns}); + + if(this.hideHeaders){ + this.el.child('.x-grid3-header').setDisplayed('none'); + } + else if(this.enableHdMenu !== false){ + this.hmenu = new Ext.menu.Menu({id: this.id + '-hctx'}); + if(this.enableColumnHide !== false){ + this.colMenu = new Ext.menu.Menu({id: this.id + '-hcols-menu'}); + this.colMenu.on({ + scope: this, + beforeshow: this.beforeColMenuShow, + itemclick: this.handleHdMenuClick + }); + this.hmenu.add({ + itemId:'columns', + hideOnClick: false, + text: this.columnsText, + menu: this.colMenu, + iconCls: 'x-cols-icon' + }); + } + this.hmenu.on('itemclick', this.handleHdMenuClick, this); + } + }, + + updateColumnWidths : function() { + var cols = this.columns, + colCount = cols.length, + groups = this.outerCt.query('colgroup'), + groupCount = groups.length, + c, g, i, j; + + for(i = 0; i < colCount; i++) { + c = cols[i]; + for(j = 0; j < groupCount; j++) { + g = groups[j]; + g.childNodes[i].style.width = (c.hidden ? 0 : c.width) + 'px'; + } + } + + // Adding the class standard-hd-row in the query, to avoid issue when hidding standard column. + for(i = 0, groups = this.innerHd.query('td.standard-hd-row'), len = groups.length; i < len; i++) { + c = Ext.fly(groups[i]); + if(cols[i] && cols[i].hidden) { + c.addClass('x-treegrid-hd-hidden'); + } + else { + c.removeClass('x-treegrid-hd-hidden'); + } + } + + var tcw = this.getTotalColumnWidth(); + Ext.fly(this.innerHd.dom.firstChild).setWidth(tcw + (this.scrollOffset || 0)); + this.outerCt.select('table').setWidth(tcw); + this.syncHeaderScroll(); + } +}); Index: main/plugin-web/resources/js/org/ametys/web/administration/Sites.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/administration/Sites.i18n.js (revision 20673) +++ main/plugin-web/resources/js/org/ametys/web/administration/Sites.i18n.js (working copy) @@ -35,15 +35,17 @@ this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_OPEN"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/open_site.png", org.ametys.web.administration.site.Open);// 1 this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CONFIG"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/config_site.png", org.ametys.web.administration.site.Config);// 2 this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_STATISTICS"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/stats_site.png", org.ametys.web.administration.site.OpenStats);// 3 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_GLOBAL_STATISTICS"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/stats_global.png", org.ametys.web.administration.site.OpenGlobalStats);// 4 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_SUPERUSER"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/super_user.png", org.ametys.web.administration.site.SuperAdministrator);// 5 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_BUILDPREVIEW"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/build_preview.png", org.ametys.web.administration.site.BuildPreview);// 6 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_BUILDALL_LABEL"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/build_preview_all.png", org.ametys.web.administration.site.BuildAll);// 7 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CLEARCACHE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/clear_cache.png", org.ametys.web.administration.site.ClearCache);// 8 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CLEARCACHEALL_LABEL"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/clear_cache_all.png", org.ametys.web.administration.site.ClearCacheAll);// 9 - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_DELETE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/delete.png", org.ametys.web.administration.site.Delete);// 10 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_GLOBAL_STATISTICS"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/stats_global.png", org.ametys.web.administration.site.OpenGlobalStats);// 4 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CACHE_BACK_STATISTICS"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/stats_global.png", org.ametys.web.administration.site.OpenCacheBackStats);// 5 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CACHE_SERVERS_STATISTICS"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/stats_global.png", org.ametys.web.administration.site.OpenCacheServersStats);// 6 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_SUPERUSER"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/super_user.png", org.ametys.web.administration.site.SuperAdministrator);// 7 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_BUILDPREVIEW"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/build_preview.png", org.ametys.web.administration.site.BuildPreview);// 8 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_BUILDALL_LABEL"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/build_preview_all.png", org.ametys.web.administration.site.BuildAll);// 9 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CLEARCACHE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/clear_cache.png", org.ametys.web.administration.site.ClearCache);// 10 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_CLEARCACHEALL_LABEL"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/clear_cache_all.png", org.ametys.web.administration.site.ClearCacheAll);// 11 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_DELETE"/>", getPluginResourcesUrl(this.pluginName) + "/img/administrator/sites/delete.png", org.ametys.web.administration.site.Delete);// 12 // Quit action - this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_QUIT"/>", getPluginResourcesUrl('core') + '/img/administrator/config/quit.png', org.ametys.web.administration.site.goBack);// 9 + this._handle.addAction("<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HANDLE_QUIT"/>", getPluginResourcesUrl('core') + '/img/administrator/config/quit.png', org.ametys.web.administration.site.goBack);// 13 // Help box var help = new org.ametys.TextPanel({title: "<i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_SITES_HELP"/>"}); @@ -54,8 +56,10 @@ this._handle.hideElt(3); this._handle.hideElt(5); this._handle.hideElt(6); + this._handle.hideElt(7); this._handle.hideElt(8); this._handle.hideElt(10); + this._handle.hideElt(12); this._rightPanel = new org.ametys.HtmlContainer({ region:'east', @@ -152,8 +156,10 @@ this._handle.hideElt(3); this._handle.hideElt(5); this._handle.hideElt(6); + this._handle.hideElt(7); this._handle.hideElt(8); this._handle.hideElt(10); + this._handle.hideElt(12); } else { @@ -162,8 +168,10 @@ this._handle.showElt(3); this._handle.showElt(5); this._handle.showElt(6); + this._handle.showElt(7); this._handle.showElt(8); this._handle.showElt(10); + this._handle.showElt(12); } } @@ -241,6 +249,18 @@ window.location.href = getPluginWrappedUrl('web') + '/administrator/sites/global-statistics.html'; } /**-----------------------------------------------------------*/ +org.ametys.web.administration.site.OpenCacheBackStats = function() +{ + var node = org.ametys.web.administration.Site._sites.getSelectionModel().getSelectedNode(); + window.location.href = getPluginWrappedUrl('web') + '/administrator/sites/' + node.attributes.name + '/cache-statistics-back.html'; +} +/**-----------------------------------------------------------*/ +org.ametys.web.administration.site.OpenCacheServersStats = function() +{ + var node = org.ametys.web.administration.Site._sites.getSelectionModel().getSelectedNode(); + window.location.href = getPluginWrappedUrl('web') + '/administrator/sites/' + node.attributes.name + '/cache-statistics-servers.html'; +} +/**-----------------------------------------------------------*/ org.ametys.web.administration.site.Open = function () { var node = org.ametys.web.administration.Site._sites.getSelectionModel().getSelectedNode(); Index: main/plugin-web/plugin.xml =================================================================== --- main/plugin-web/plugin.xml (revision 20673) +++ main/plugin-web/plugin.xml (working copy) @@ -8634,4 +8634,91 @@ </param> </config> </feature> + + <!-- + + | CACHE MONITORING + + --> + <feature name="cache.monitoring.datasource"> + <!-- Monitoring Datasource --> + <config> + <param id="cache.monitoring.datasource.jdbc.driver" type="string"> + <label i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_DRIVER_LABEL</label> + <description i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_DRIVER_DESCRIPTION</description> + <validation> + <mandatory/> + </validation> + <default-value>com.mysql.jdbc.Driver</default-value> + <category i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY</category> + <group i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_GROUP</group> + <order>10</order> + </param> + <param id="cache.monitoring.datasource.jdbc.url" type="string"> + <label i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_URL_LABEL</label> + <description i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_URL_DESCRIPTION</description> + <validation> + <mandatory/> + </validation> + <default-value>jdbc:mysql://servername/basename</default-value> + <category i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY</category> + <group i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_GROUP</group> + <order>20</order> + </param> + <param id="cache.monitoring.datasource.jdbc.user" type="string"> + <label i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_USER_LABEL</label> + <description i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_USER_DESCRIPTION</description> + <default-value>username</default-value> + <category i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY</category> + <group i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_GROUP</group> + <order>30</order> + </param> + <param id="cache.monitoring.datasource.jdbc.passwd" type="password"> + <label i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_PASSWORD_LABEL</label> + <description i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_PASSWORD_DESCRIPTION</description> + <default-value>password</default-value> + <category i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY</category> + <group i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_DATASOURCE_JDBC_GROUP</group> + <order>40</order> + </param> + </config> + + <extensions> + <extension point="org.ametys.runtime.datasource.DataSourceExtensionPoint" + id="cache.monitoring.datasource" + logger="org.ametys.cache.monitoring.datasource"> + <driver runtime-config-parameter="cache.monitoring.datasource.jdbc.driver"/> + <dburl runtime-config-parameter="cache.monitoring.datasource.jdbc.url"/> + <user runtime-config-parameter="cache.monitoring.datasource.jdbc.user"/> + <password runtime-config-parameter="cache.monitoring.datasource.jdbc.passwd"/> + </extension> + </extensions> + </feature> + + <feature name="cache.monitoring.schedulers"> + <config> + <param id="cache.monitoring.schedulers.enable" type="boolean"> + <label i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_HANDLING_ENABLE_LABEL</label> + <description i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_HANDLING_ENABLE_DESCRIPTION</description> + <validation> + <mandatory/> + </validation> + <default-value>false</default-value> + <category i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_CATEGORY</category> + <group i18n="true">PLUGINS_WEB_CONFIG_CACHE_MONITORING_HANDLING_GROUP</group> + </param> + </config> + + <components> + <component role="org.ametys.web.cache.monitoring.process.access.ResourceAccessComponent" + class="org.ametys.web.cache.monitoring.process.access.ResourceAccessComponent" + logger="org.ametys.web.cache.monitoring.process.access.ResourceAccessComponent" /> + + <component role="org.ametys.web.cache.monitoring.process.statistics.ResourceStatisticsComponent" + class="org.ametys.web.cache.monitoring.process.statistics.ResourceStatisticsComponent" + logger="org.ametys.web.cache.monitoring.process.statistics.ResourceStatisticsComponent" /> + + <component role="org.ametys.web.cache.monitoring.process.CacheMonitoringScheduler" + class="org.ametys.web.cache.monitoring.process.CacheMonitoringScheduler" + logger="org.ametys.web.cache.monitoring.process.CacheMonitoringScheduler" /> + </components> + </feature> </plugin> Index: main/plugin-web/src/org/ametys/web/cache/monitoring/ui/PageElementCacheStatsGenerator.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/ui/PageElementCacheStatsGenerator.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/ui/PageElementCacheStatsGenerator.java (working copy) @@ -35,6 +35,7 @@ import org.apache.cocoon.generation.ServiceableGenerator; import org.apache.cocoon.xml.AttributesImpl; import org.apache.cocoon.xml.XMLUtils; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; @@ -120,7 +121,7 @@ List<String> contexts = _getContextsFilter(parameters.getParameter("contexts", null)); - Long start = null; + long start = 0; if (getLogger().isDebugEnabled()) { start = System.currentTimeMillis(); @@ -139,12 +140,9 @@ if (getLogger().isDebugEnabled()) { - if (start != null) - { - long end = System.currentTimeMillis(); - String duration = PeriodFormat.getDefault().print(new Duration(end - start).toPeriod()); - getLogger().debug(String.format("The SAX process of the back-office cache statistics took %s", duration)); - } + long end = System.currentTimeMillis(); + String duration = PeriodFormat.getDefault().print(new Duration(end - start).toPeriod()); + getLogger().debug(String.format("The SAX process of the back-office cache statistics took %s", duration)); } } @@ -186,10 +184,10 @@ { StringBuilder sb = new StringBuilder(); - sb.append(" SELECT p.Page_Id, p.Rendering_Context, p.Workspace_JCR, p.Cacheable AS P_Cacheable, p.Hits AS P_Hits,"); - sb.append(" pe.Page_Element_Id, pe.Cacheable AS PE_Cacheable, pe.Hits AS PE_Hits, pe.Cache_Hits AS PE_Cache_Hits"); - sb.append(" FROM CACHE_BACK_STATS p"); - sb.append(" LEFT OUTER JOIN Cache_Back_Page_Element_Stats pe"); + sb.append(" SELECT p.Page_Id, p.Rendering_Context, p.Workspace_JCR, p.Cacheable AS \"P_Cacheable\", p.Hits AS \"P_Hits\","); + sb.append(" pe.Page_Element_Id, pe.Cacheable AS \"PE_Cacheable\", pe.Hits AS \"PE_Hits\", pe.Cache_Hits AS \"PE_Cache_Hits\""); + sb.append(" FROM ").append(Constants.__SQL_TABLE_NAME_PAGE_STATISTICS).append(" p"); + sb.append(" INNER JOIN ").append(Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS).append(" pe"); sb.append(" ON p.Page_Id = pe.Page_Id AND p.Rendering_Context = pe.Rendering_Context AND p.Workspace_JCR = pe.Workspace_JCR"); return sb.toString(); @@ -202,7 +200,7 @@ for (int i = 0; i < cols.length; i++) { - cols[i] = meta.getColumnLabel(i + 1); + cols[i] = meta.getColumnLabel(i + 1).toUpperCase(); } while (rs.next()) @@ -445,33 +443,62 @@ /** * Object model representing an entry of stats for a Page */ - @SuppressWarnings("javadoc") protected class PageStatsEntry { + /** page id */ protected final String _pageId; + /** rendering context */ protected final String _renderingContext; + /** workspace JCR */ protected final String _workspaceJCR; + /** is cacheable */ protected final boolean _cacheable; + /** hits */ protected final int _hits; /** * Ctor + * @param data map of raw data object. */ protected PageStatsEntry(Map<String, Object> data) { - _pageId = (String) data.get("Page_Id"); - _renderingContext = (String) data.get("Rendering_Context"); - _workspaceJCR = (String) data.get("Workspace_JCR"); - _cacheable = (Boolean) data.get("P_Cacheable"); - _hits = __toInteger(data.get("P_Hits")); + _pageId = (String) data.get("PAGE_ID"); + _renderingContext = (String) data.get("RENDERING_CONTEXT"); + _workspaceJCR = (String) data.get("WORKSPACE_JCR"); + _cacheable = __toBool(data.get("P_CACHEABLE")); + _hits = __toInt(data.get("P_HITS")); } - private Integer __toInteger(Object value) + private boolean __toBool(Object object) { - Long lValue = (Long) value; - return lValue != null ? lValue.intValue() : null; + if (object instanceof Boolean) + { + return BooleanUtils.toBoolean((Boolean) object); + } + else if (object instanceof Number) + { + Number i = (Number) object; + return i != null && i.intValue() != 0; + } + + throw new IllegalArgumentException("Not able to convert object to bool : unexpected object type."); } + private int __toInt(Object object) + { + if (object instanceof Number) + { + Number n = (Number) object; + return n == null ? 0 : n.intValue(); + } + + throw new IllegalArgumentException("Not able to convert object to int : unexpected object type."); + } + + /** + * Returns the formatted context name + * @return context name + */ public String getContext() { return _renderingContext + '-' + _workspaceJCR; @@ -514,33 +541,59 @@ /** * Object model representing an entry of stats for a PageElement */ - @SuppressWarnings("javadoc") protected class PageElementStatsEntry { + /** page element id */ protected final String _pageElementID; + /** rendering context */ protected final String _renderingContext; + /** workspace JCR */ protected final String _workspaceJCR; - protected final Boolean _cacheable; - protected final Integer _hits; - protected final Integer _cacheHits; + /** is cacheable */ + protected final boolean _cacheable; + /** hits */ + protected final int _hits; + /** cache hits */ + protected final int _cacheHits; /** * Ctor + * @param data map of raw data object. */ protected PageElementStatsEntry(Map<String, Object> data) { - _pageElementID = (String) data.get("Page_Element_Id"); - _renderingContext = (String) data.get("Rendering_Context"); - _workspaceJCR = (String) data.get("Workspace_JCR"); - _cacheable = (Boolean) data.get("PE_Cacheable"); - _hits = __toInteger(data.get("PE_Hits")); - _cacheHits = __toInteger(data.get("PE_Cache_Hits")); + _pageElementID = (String) data.get("PAGE_ELEMENT_ID"); + _renderingContext = (String) data.get("RENDERING_CONTEXT"); + _workspaceJCR = (String) data.get("WORKSPACE_JCR"); + _cacheable = __toBool(data.get("PE_CACHEABLE")); + _hits = __toInt(data.get("PE_HITS")); + _cacheHits = __toInt(data.get("PE_CACHE_HITS")); + } + + private boolean __toBool(Object object) + { + if (object instanceof Boolean) + { + return BooleanUtils.toBoolean((Boolean) object); + } + else if (object instanceof Number) + { + Number i = (Number) object; + return i != null && i.intValue() != 0; + } + + throw new IllegalArgumentException("Not able to convert object to bool : unexpected object type."); } - private Integer __toInteger(Object value) + private int __toInt(Object object) { - Long lValue = (Long) value; - return lValue != null ? lValue.intValue() : null; + if (object instanceof Number) + { + Number n = (Number) object; + return n == null ? 0 : n.intValue(); + } + + throw new IllegalArgumentException("Not able to convert object to int : unexpected object type."); } } } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/ui/ServersCacheStatsGenerator.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/ui/ServersCacheStatsGenerator.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/ui/ServersCacheStatsGenerator.java (working copy) @@ -39,6 +39,7 @@ import org.apache.cocoon.generation.ServiceableGenerator; import org.apache.cocoon.xml.AttributesImpl; import org.apache.cocoon.xml.XMLUtils; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.joda.time.Duration; import org.joda.time.format.PeriodFormat; @@ -63,7 +64,7 @@ public class ServersCacheStatsGenerator extends ServiceableGenerator { /** List of paths used to during the sanitize process of the server path */ - protected static final String[] _SPECIAL_PATH_PREFIXS = new String[]{"/skins/", "/plugins/", "/kernel", "/_external/"}; + protected static final String[] _SPECIAL_PATH_PREFIXS = new String[]{"/skins/", "/plugins/", "/kernel/", "/_external/"}; /** * This multimap associates site names to a list of prefix. This is needed @@ -131,7 +132,7 @@ // Populate and organize stats maps. _initializeStats(rawStats); - Long start = null; + long start = 0; if (getLogger().isDebugEnabled()) { start = System.currentTimeMillis(); @@ -154,12 +155,9 @@ if (getLogger().isDebugEnabled()) { - if (start != null) - { - long end = System.currentTimeMillis(); - String duration = PeriodFormat.getDefault().print(new Duration(end - start).toPeriod()); - getLogger().debug(String.format("The SAX process of the Apache and Front-office cache statistics took %s", duration)); - } + long end = System.currentTimeMillis(); + String duration = PeriodFormat.getDefault().print(new Duration(end - start).toPeriod()); + getLogger().debug(String.format("The SAX process of the Apache and Front-office cache statistics took %s", duration)); } } @@ -222,11 +220,10 @@ sb.append(" SELECT F.Server_Site, F.Server_Path, F.Server_Hits, F.Server_Cache_Hits,"); sb.append(" F.Front_Site, F.Front_Path, F.Front_Cacheable, F.Front_Hits, F.Front_Cache_Hits_1, F.Front_Cache_Hits_2,"); sb.append(" B.Page_Id, B.Page_Path, B.Cacheable, B.Hits"); - sb.append(" FROM CACHE_FRONT_STATS F"); - sb.append(" LEFT OUTER JOIN CACHE_BACK_STATS B"); - sb.append(" ON F.Front_Path = B.Page_Path AND F.Front_Path is not NULL AND B.Rendering_Context = 'front'"); - sb.append(" WHERE F.Server_Site = ? OR F.Server_Site = '' OR F.Server_Site is NULL"); - sb.append(" OR F.Front_Site = ? OR F.Front_Site = '' OR F.Front_Site is NULL"); + sb.append(" FROM ").append(Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS).append(" F"); + sb.append(" LEFT OUTER JOIN ").append(Constants.__SQL_TABLE_NAME_PAGE_STATISTICS).append(" B"); + sb.append(" ON F.Front_Path = B.Page_Path AND B.Rendering_Context = 'front'"); + sb.append(" WHERE (F.Server_Site = ? OR F.Server_Site = '-' OR F.Front_Site = ? OR F.Front_Site = '-')"); return sb.toString(); } @@ -238,7 +235,7 @@ for (int i = 0; i < cols.length; i++) { - cols[i] = meta.getColumnLabel(i + 1); + cols[i] = meta.getColumnLabel(i + 1).toUpperCase(); } List<RawStatsEntry> entries = new ArrayList<RawStatsEntry>(); @@ -291,7 +288,6 @@ private void _addToApacheStats(FrontFromApacheStatsEntry apacheEntry) { - // could be null in case of a resource. That's ok, we will handle this case later when SAX'ing. String siteName = apacheEntry._serverSite; Map<String, FrontFromApacheStatsEntry> siteMap = _fromApacheStats.get(siteName); @@ -322,8 +318,7 @@ private void _addToFrontOnlyStats(FrontFromFrontStatsEntry frontEntry) { - // could be null in case of a resource. That's ok, we will handle this case later when SAX'ing. - String siteName = StringUtils.defaultIfEmpty(frontEntry._frontSite, null); + String siteName = frontEntry._frontSite; Map<String, FrontFromFrontStatsEntry> siteMap = _fromFrontOnlyStats.get(siteName); if (siteMap == null) @@ -543,7 +538,7 @@ private void _saxStatsOrphanEntries() throws SAXException { - Multimap<String, String> pathMap = _pathMaps.get(null); + Multimap<String, String> pathMap = _pathMaps.get("-"); if (pathMap == null || pathMap.isEmpty()) { return; @@ -555,13 +550,13 @@ return; } - Map<String, FrontFromApacheStatsEntry> apacheStats = _fromApacheStats.get(null); + Map<String, FrontFromApacheStatsEntry> apacheStats = _fromApacheStats.get("-"); if (apacheStats == null) { apacheStats = Collections.EMPTY_MAP; } - Map<String, FrontFromFrontStatsEntry> frontOnlyStats = _fromFrontOnlyStats.get(null); + Map<String, FrontFromFrontStatsEntry> frontOnlyStats = _fromFrontOnlyStats.get("-"); if (frontOnlyStats == null) { frontOnlyStats = Collections.EMPTY_MAP; @@ -596,27 +591,38 @@ /** * Object model representing a raw entry of stats retrieved through the DB. */ - @SuppressWarnings("javadoc") protected class RawStatsEntry { + /** The map of raw data objects */ protected final Map<String, Object> _data; /** * Ctor + * @param data map of raw data object. */ protected RawStatsEntry(Map<String, Object> data) { _data = data; } + /** + * Indicates if this instance has apache information. + * @return a boolean + */ protected boolean hasApacheInfo() { - return _data.get("Server_Path") != null; + String serverPath = (String) _data.get("SERVER_PATH"); + return serverPath != null && !"-".equals(serverPath); } + /** + * Indicates if this instance has back(-office) information. + * @return a boolean + */ protected boolean hasBackInfo() { - return _data.get("Page_Id") != null; + String pageId = (String) _data.get("PAGE_ID"); + return pageId != null && !"-".equals(pageId); } } @@ -624,28 +630,36 @@ * Object model representing an entry of stats for a front resource, coming * from Apache */ - @SuppressWarnings("javadoc") protected class FrontFromApacheStatsEntry extends FrontFromFrontStatsEntry { - + /** Server site name */ protected final String _serverSite; + /** Server path */ protected final String _serverPath; - protected Integer _serverHits; - protected Integer _serverCacheHits; + /** server hits */ + protected int _serverHits; + /** server cache hits */ + protected int _serverCacheHits; /** * Ctor + * @param data map of raw data object. */ protected FrontFromApacheStatsEntry(Map<String, Object> data) { super(data); - _serverSite = (String) data.get("Server_Site"); - _serverPath = (String) data.get("Server_Path"); - _serverHits = __toInteger(data.get("Server_Hits")); - _serverCacheHits = __toInteger(data.get("Server_Cache_Hits")); + _serverSite = (String) data.get("SERVER_SITE"); + _serverPath = (String) data.get("SERVER_PATH"); + _serverHits = __toInt(data.get("SERVER_HITS")); + _serverCacheHits = __toInt(data.get("SERVER_CACHE_HITS")); } + /** + * Merge this instance of <code>FrontFromApacheStatsEntry</code> with + * another instance of <code>FrontFromApacheStatsEntry</code> + * @param that + */ protected void merge(FrontFromApacheStatsEntry that) { if (that == null) @@ -668,6 +682,11 @@ } } + /** + * Returns a sanitized path given the different path properties of this + * instance. + * @return The sanitized path + */ protected String getSanitizedPath() { if (hasFrontInfo()) @@ -727,9 +746,13 @@ return sanitizedPath; } + /** + * Indicates if this instance has front(-office) information. + * @return a boolean + */ protected boolean hasFrontInfo() { - return _frontPath != null; + return _frontPath != null && !"-".equals(_frontPath); } } @@ -737,33 +760,70 @@ * Object model representing an entry of stats for a front resource, coming * from the Front (direct request to tomcat, bypassing any Apache HTTP server if any). */ - @SuppressWarnings("javadoc") protected class FrontFromFrontStatsEntry { + /** front site name */ protected String _frontSite; + /** front path */ protected String _frontPath; - protected Boolean _frontCacheable; - protected Integer _frontHits; - protected Integer _frontCacheHits1; - protected Integer _frontCacheHits2; + /** is front cacheable */ + protected boolean _frontCacheable; + /** front hits */ + protected int _frontHits; + /** front cache hits 1 */ + protected int _frontCacheHits1; + /** front cache hits 2 */ + protected int _frontCacheHits2; /** * Ctor + * @param data map of raw data object. */ protected FrontFromFrontStatsEntry(Map<String, Object> data) { - _frontSite = (String) data.get("Front_Site"); - _frontPath = (String) data.get("Front_Path"); - _frontCacheable = (Boolean) data.get("Front_Cacheable"); - _frontHits = __toInteger(data.get("Front_Hits")); - _frontCacheHits1 = __toInteger(data.get("Front_Cache_Hits_1")); - _frontCacheHits2 = __toInteger(data.get("Front_Cache_Hits_2")); + _frontSite = (String) data.get("FRONT_SITE"); + _frontPath = (String) data.get("FRONT_PATH"); + _frontCacheable = __toBool(data.get("FRONT_CACHEABLE")); + _frontHits = __toInt(data.get("FRONT_HITS")); + _frontCacheHits1 = __toInt(data.get("FRONT_CACHE_HITS_1")); + _frontCacheHits2 = __toInt(data.get("FRONT_CACHE_HITS_2")); + } + + + /** + * Object to boolean + * @param object + * @return the boolean + */ + protected boolean __toBool(Object object) + { + if (object instanceof Boolean) + { + return BooleanUtils.toBoolean((Boolean) object); + } + else if (object instanceof Number) + { + Number i = (Number) object; + return i != null && i.intValue() != 0; + } + + throw new IllegalArgumentException("Not able to convert object to bool : unexpected object type."); } - protected Integer __toInteger(Object value) + /** + * Object to int + * @param object + * @return the int + */ + protected int __toInt(Object object) { - Long lValue = (Long) value; - return lValue != null ? lValue.intValue() : null; + if (object instanceof Number) + { + Number n = (Number) object; + return n == null ? 0 : n.intValue(); + } + + throw new IllegalArgumentException("Not able to convert object to int : unexpected object type."); } } @@ -771,29 +831,63 @@ * Object model representing an entry of stats for a back resource (ie. a * page). */ - @SuppressWarnings("javadoc") protected class BackStatsEntry { + /** page id */ protected final String _pageId; + /** page path */ protected final String _pagePath; + /** cacheable */ protected final boolean _cacheable; + /** hits */ protected final int _hits; /** * Ctor + * @param data map of raw data object. */ protected BackStatsEntry(Map<String, Object> data) { - _pageId = (String) data.get("Page_Id"); - _pagePath = (String) data.get("Page_Path"); - _cacheable = (Boolean) data.get("Cacheable"); - _hits = __toInteger(data.get("Hits")); + _pageId = (String) data.get("PAGE_ID"); + _pagePath = (String) data.get("PAGE_PATH"); + _cacheable = __toBool(data.get("CACHEABLE")); + _hits = __toInt(data.get("HITS")); + } + + /** + * Object to boolean + * @param object + * @return the boolean + */ + protected boolean __toBool(Object object) + { + if (object instanceof Boolean) + { + return BooleanUtils.toBoolean((Boolean) object); + } + else if (object instanceof Number) + { + Number i = (Number) object; + return i != null && i.intValue() != 0; + } + + throw new IllegalArgumentException("Not able to convert object to bool : unexpected object type."); } - private Integer __toInteger(Object value) + /** + * Object to int + * @param object + * @return the int + */ + protected int __toInt(Object object) { - Long lValue = (Long) value; - return lValue != null ? lValue.intValue() : null; + if (object instanceof Number) + { + Number n = (Number) object; + return n == null ? 0 : n.intValue(); + } + + throw new IllegalArgumentException("Not able to convert object to int : unexpected object type."); } } } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontFromHTTPServerResourceStatistics.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontFromHTTPServerResourceStatistics.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontFromHTTPServerResourceStatistics.java (working copy) @@ -19,6 +19,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Timestamp; + +import org.apache.commons.lang.BooleanUtils; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.statistics.ResourceStatistics; @@ -38,7 +41,7 @@ private final boolean _frontCacheHit1; private final boolean _frontCacheHit2; - private final long _newHits; + private final int _newHits; /** * Creates a statistic @@ -52,7 +55,7 @@ * @param frontCacheHit2 The front cache hit 2 status * @param newHits The hits */ - public FrontFromHTTPServerResourceStatistics(String httpserverSite, String httpserverPath, boolean httpserverCacheHit, String frontSite, String frontPath, boolean frontCacheable, boolean frontCacheHit1, boolean frontCacheHit2, long newHits) + public FrontFromHTTPServerResourceStatistics(String httpserverSite, String httpserverPath, boolean httpserverCacheHit, String frontSite, String frontPath, boolean frontCacheable, boolean frontCacheHit1, boolean frontCacheHit2, int newHits) { _httpserverSite = httpserverSite; _httpserverPath = httpserverPath; @@ -70,7 +73,7 @@ @Override public PreparedStatement getFindStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("SELECT count(1) " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE Server_Site = ? AND Server_Path = ?"); + PreparedStatement stmt = connection.prepareStatement("SELECT count(1) FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE Server_Site = ? AND Server_Path = ?"); stmt.setString(1, _httpserverSite); stmt.setString(2, _httpserverPath); @@ -81,19 +84,23 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " (Server_Site, Server_Path, Server_Hits, Server_Cache_Hits, Front_Site, Front_Path, Front_Cacheable, Front_Hits, Front_Cache_Hits_1, Front_Cache_Hits_2) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " (Server_Site, Server_Path, Server_Hits, Server_Cache_Hits, Front_Site, Front_Path, Front_Cacheable, Front_Hits, Front_Cache_Hits_1, Front_Cache_Hits_2, Created_At, Updated_At) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.setString(1, _httpserverSite); stmt.setString(2, _httpserverPath); - stmt.setLong(3, _newHits); - stmt.setLong(4, _getServerCacheHits()); + stmt.setInt(3, _newHits); + stmt.setInt(4, _getServerCacheHits()); stmt.setString(5, _frontSite); stmt.setString(6, _frontPath); - stmt.setBoolean(7, _frontCacheable); - stmt.setLong(8, _newHits); - stmt.setLong(9, _getFrontCacheHits1()); - stmt.setLong(10, _getFrontCacheHits2()); + stmt.setInt(7, BooleanUtils.toInteger(_frontCacheable)); + stmt.setInt(8, _newHits); + stmt.setInt(9, _getFrontCacheHits1()); + stmt.setInt(10, _getFrontCacheHits2()); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + stmt.setTimestamp(11, now); + stmt.setTimestamp(12, now); return stmt; } @@ -101,40 +108,41 @@ @Override public PreparedStatement getUpdateStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " SET Server_Hits = Server_Hits + ?, Server_Cache_Hits = Server_Cache_Hits + ?, Front_Site = ?, Front_Path = ?, Front_Cacheable = ?, Front_Hits = Front_Hits + ?, Front_Cache_Hits_1 = Front_Cache_Hits_1 + ?, Front_Cache_Hits_2 = Front_Cache_Hits_2 + ? WHERE Server_Site = ? AND Server_Path = ?"); + PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " SET Server_Hits = Server_Hits + ?, Server_Cache_Hits = Server_Cache_Hits + ?, Front_Site = ?, Front_Path = ?, Front_Cacheable = ?, Front_Hits = Front_Hits + ?, Front_Cache_Hits_1 = Front_Cache_Hits_1 + ?, Front_Cache_Hits_2 = Front_Cache_Hits_2 + ?, Updated_At = ? WHERE Server_Site = ? AND Server_Path = ?"); - stmt.setLong(1, _newHits); - stmt.setLong(2, _getServerCacheHits()); + stmt.setInt(1, _newHits); + stmt.setInt(2, _getServerCacheHits()); stmt.setString(3, _frontSite); stmt.setString(4, _frontPath); - stmt.setBoolean(5, _frontCacheable); - stmt.setLong(6, _newHits); - stmt.setLong(7, _getFrontCacheHits1()); - stmt.setLong(8, _getFrontCacheHits2()); + stmt.setInt(5, BooleanUtils.toInteger(_frontCacheable)); + stmt.setInt(6, _newHits); + stmt.setInt(7, _getFrontCacheHits1()); + stmt.setInt(8, _getFrontCacheHits2()); + stmt.setTimestamp(9, new Timestamp(System.currentTimeMillis())); - stmt.setString(9, _httpserverSite); - stmt.setString(10, _httpserverPath); + stmt.setString(10, _httpserverSite); + stmt.setString(11, _httpserverPath); return stmt; } @Override - public long getHits() + public int getHits() { return _newHits; } - private long _getServerCacheHits() + private int _getServerCacheHits() { return _httpserverCacheHit ? _newHits : 0; } - private long _getFrontCacheHits1() + private int _getFrontCacheHits1() { return _frontCacheHit1 ? _newHits : 0; } - private long _getFrontCacheHits2() + private int _getFrontCacheHits2() { return _frontCacheHit2 ? _newHits : 0; } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/HTTPServerOnlyResourceStatistics.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/HTTPServerOnlyResourceStatistics.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/HTTPServerOnlyResourceStatistics.java (working copy) @@ -19,6 +19,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Timestamp; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.statistics.ResourceStatistics; @@ -32,7 +33,7 @@ private final String _site; private final String _path; private final boolean _cacheHit; - private final long _newHits; + private final int _newHits; /** * Creates a statistics @@ -41,7 +42,7 @@ * @param cacheHit The cache hit status * @param newHits The number of hits */ - public HTTPServerOnlyResourceStatistics(String site, String path, boolean cacheHit, long newHits) + public HTTPServerOnlyResourceStatistics(String site, String path, boolean cacheHit, int newHits) { _site = site; _path = path; @@ -52,7 +53,7 @@ @Override public PreparedStatement getFindStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("SELECT count(1) " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE Server_Site = ? AND Server_Path = ?"); + PreparedStatement stmt = connection.prepareStatement("SELECT count(1) FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE Server_Site = ? AND Server_Path = ?"); stmt.setString(1, _site); stmt.setString(2, _path); @@ -63,12 +64,16 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " (Server_Site, Server_Path, Server_Hits, Server_Cache_Hits) values (?, ?, ?, ?)"); + PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " (Server_Site, Server_Path, Server_Hits, Server_Cache_Hits, Created_At, Updated_At) values (?, ?, ?, ?, ?, ?)"); stmt.setString(1, _site); stmt.setString(2, _path); - stmt.setLong(3, _newHits); - stmt.setLong(4, _getCacheHits()); + stmt.setInt(3, _newHits); + stmt.setInt(4, _getCacheHits()); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + stmt.setTimestamp(5, now); + stmt.setTimestamp(6, now); return stmt; } @@ -76,24 +81,25 @@ @Override public PreparedStatement getUpdateStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " SET Server_Hits = Server_Hits + ?, Server_Cache_Hits = Server_Cache_Hits + ? WHERE Server_Site = ? AND Server_Path = ?"); + PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " SET Server_Hits = Server_Hits + ?, Server_Cache_Hits = Server_Cache_Hits + ?, Updated_At = ? WHERE Server_Site = ? AND Server_Path = ?"); - stmt.setLong(1, _newHits); - stmt.setLong(2, _getCacheHits()); + stmt.setInt(1, _newHits); + stmt.setInt(2, _getCacheHits()); + stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis())); - stmt.setString(3, _site); - stmt.setString(4, _path); + stmt.setString(4, _site); + stmt.setString(5, _path); return stmt; } @Override - public long getHits() + public int getHits() { return _newHits; } - private long _getCacheHits() + private int _getCacheHits() { return _cacheHit ? _newHits : 0; } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/HTTPServerOnlyResourceStatisticsFactory.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/HTTPServerOnlyResourceStatisticsFactory.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/HTTPServerOnlyResourceStatisticsFactory.java (working copy) @@ -63,15 +63,15 @@ try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("SELECT count(*) AS increment, Site, Path, Cache_Hit FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " T WHERE PROCESSED = false AND Cache_Hit = true AND (Ori_Status_Code = 200 OR Ori_Status_Code = 304) GROUP BY Site, Path, Cache_Hit ORDER BY max(T.Id)"); + stmt = connection.prepareStatement("SELECT count(*) AS \"increment\", Site, Path, Cache_Hit FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " WHERE PROCESSED = 0 AND Cache_Hit = 1 AND (Ori_Status_Code = '200' OR Ori_Status_Code = '304') GROUP BY Site, Path, Cache_Hit"); resultSet = stmt.executeQuery(); while (resultSet.next()) { String site = resultSet.getString("Site"); String path = resultSet.getString("Path"); - boolean cacheHit = BooleanUtils.toBoolean(resultSet.getBoolean("Cache_Hit")); // converts null to false, avoiding NPE while unboxing. - long newHits = resultSet.getLong("increment"); + boolean cacheHit = BooleanUtils.toBoolean(resultSet.getInt("Cache_Hit")); + int newHits = resultSet.getInt("increment"); resourceStatisticsList.add(new HTTPServerOnlyResourceStatistics(site, path, cacheHit, newHits)); } @@ -87,43 +87,33 @@ } @Override - public long getMaxIdToProcess() throws SQLException + public int markResourcesAsProcessed() throws SQLException { Connection connection = null; Statement stmt = null; - ResultSet resultSet = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); stmt = connection.createStatement(); - resultSet = stmt.executeQuery("SELECT max(Id) FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE PROCESSED = false AND (Ori_Status_Code = 200 OR Ori_Status_Code = 304)"); - - if (resultSet.next()) - { - return resultSet.getLong(1); - } - return -1; + return stmt.executeUpdate("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " SET Processed = 1 WHERE Processed = 0 AND Cache_Hit = 1 AND (Ori_Status_Code = '200' OR Ori_Status_Code = '304')"); } finally { - ConnectionHelper.cleanup(resultSet); ConnectionHelper.cleanup(stmt); ConnectionHelper.cleanup(connection); } } @Override - public int markResourcesAsProcessed(long id) throws SQLException + public int purgeRawData() throws SQLException { Connection connection = null; - PreparedStatement stmt = null; + Statement stmt = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " AS S LEFT OUTER JOIN " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " F ON S.Unique_Id = F.Unique_Id SET S.Processed = true WHERE S.Id <= ? AND F.Unique_Id is NULL AND S.Processed = false AND (S.Ori_Status_Code = 200 OR S.Ori_Status_Code = 304)"); - stmt.setLong(1, id); - - return stmt.executeUpdate(); + stmt = connection.createStatement(); + return stmt.executeUpdate("DELETE FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " WHERE PROCESSED = 1"); } finally { Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageElementResourceStatisticsFactory.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageElementResourceStatisticsFactory.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageElementResourceStatisticsFactory.java (working copy) @@ -63,7 +63,7 @@ try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("SELECT count(*) AS increment, Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Cache_Hit FROM " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " T WHERE PROCESSED = false GROUP BY Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Cache_Hit ORDER BY max(T.Id)"); + stmt = connection.prepareStatement("SELECT count(*) AS \"increment\", Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Cache_Hit FROM " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS + " WHERE PROCESSED = 0 GROUP BY Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Cache_Hit"); resultSet = stmt.executeQuery(); while (resultSet.next()) @@ -72,9 +72,9 @@ String pageId = resultSet.getString("Page_Id"); String renderingContext = resultSet.getString("Rendering_Context"); String jcrWorkspace = resultSet.getString("Workspace_JCR"); - boolean cacheable = resultSet.getBoolean("Cacheable"); - boolean cacheHit = BooleanUtils.toBoolean(resultSet.getBoolean("Cache_Hit")); // converts null to false, avoiding NPE while unboxing. - long newHits = resultSet.getLong("increment"); + boolean cacheable = BooleanUtils.toBoolean(resultSet.getInt("Cacheable")); + boolean cacheHit = BooleanUtils.toBoolean(resultSet.getInt("Cache_Hit")); + int newHits = resultSet.getInt("increment"); resourceStatisticsList.add(new PageElementResourceStatistics(pageElementId, pageId, renderingContext, jcrWorkspace, cacheable, cacheHit, newHits)); } @@ -90,43 +90,33 @@ } @Override - public long getMaxIdToProcess() throws SQLException + public int markResourcesAsProcessed() throws SQLException { Connection connection = null; Statement stmt = null; - ResultSet resultSet = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); stmt = connection.createStatement(); - resultSet = stmt.executeQuery("SELECT max(Id) FROM " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " WHERE PROCESSED = false"); - - if (resultSet.next()) - { - return resultSet.getLong(1); - } - return -1; + return stmt.executeUpdate("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS + " SET PROCESSED = 1 WHERE Processed = 0"); } finally { - ConnectionHelper.cleanup(resultSet); ConnectionHelper.cleanup(stmt); ConnectionHelper.cleanup(connection); } } @Override - public int markResourcesAsProcessed(long id) throws SQLException + public int purgeRawData() throws SQLException { Connection connection = null; - PreparedStatement stmt = null; + Statement stmt = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " SET PROCESSED = true WHERE Id <= ? AND Processed = false"); - stmt.setLong(1, id); - - return stmt.executeUpdate(); + stmt = connection.createStatement(); + return stmt.executeUpdate("DELETE FROM " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS + " WHERE PROCESSED = 1"); } finally { Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageElementResourceStatistics.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageElementResourceStatistics.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageElementResourceStatistics.java (working copy) @@ -19,6 +19,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Timestamp; + +import org.apache.commons.lang.BooleanUtils; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.statistics.ResourceStatistics; @@ -35,7 +38,7 @@ private final String _workspaceJCR; private final boolean _cacheable; private final boolean _cacheHit; - private final long _newHits; + private final int _newHits; /** * Creates a statistics @@ -47,7 +50,7 @@ * @param cacheHit The cache hit status * @param increment The number of increment */ - public PageElementResourceStatistics(String pageElementId, String pageId, String renderingContext, String jcrWorkspace, boolean cacheable, boolean cacheHit, long increment) + public PageElementResourceStatistics(String pageElementId, String pageId, String renderingContext, String jcrWorkspace, boolean cacheable, boolean cacheHit, int increment) { _pageElementId = pageElementId; _pageId = pageId; @@ -61,7 +64,7 @@ @Override public PreparedStatement getFindStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("SELECT count(1) " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " WHERE Page_Element_Id = ? AND Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); + PreparedStatement stmt = connection.prepareStatement("SELECT count(1) FROM " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " WHERE Page_Element_Id = ? AND Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); stmt.setString(1, _pageElementId); stmt.setString(2, _pageId); @@ -74,15 +77,19 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " (Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Hits, Cache_Hits) values (?, ?, ?, ?, ?, ?, ?)"); + PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " (Page_Element_Id, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Hits, Cache_Hits, Created_At, Updated_At) values (?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.setString(1, _pageElementId); stmt.setString(2, _pageId); stmt.setString(3, _renderingContext); stmt.setString(4, _workspaceJCR); - stmt.setBoolean(5, _cacheable); - stmt.setLong(6, _newHits); - stmt.setLong(7, _getCacheHits()); + stmt.setInt(5, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(6, _newHits); + stmt.setInt(7, _getCacheHits()); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + stmt.setTimestamp(8, now); + stmt.setTimestamp(9, now); return stmt; } @@ -90,27 +97,28 @@ @Override public PreparedStatement getUpdateStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " SET Cacheable = ?, Hits = Hits + ?, Cache_Hits = Cache_Hits + ? WHERE Page_Element_Id = ? AND Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); + PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS + " SET Cacheable = ?, Hits = Hits + ?, Cache_Hits = Cache_Hits + ?, Updated_At = ? WHERE Page_Element_Id = ? AND Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); - stmt.setBoolean(1, _cacheable); - stmt.setLong(2, _newHits); - stmt.setLong(3, _getCacheHits()); + stmt.setInt(1, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(2, _newHits); + stmt.setInt(3, _getCacheHits()); + stmt.setTimestamp(4, new Timestamp(System.currentTimeMillis())); - stmt.setString(4, _pageElementId); - stmt.setString(5, _pageId); - stmt.setString(6, _renderingContext); - stmt.setString(7, _workspaceJCR); + stmt.setString(5, _pageElementId); + stmt.setString(6, _pageId); + stmt.setString(7, _renderingContext); + stmt.setString(8, _workspaceJCR); return stmt; } @Override - public long getHits() + public int getHits() { return _newHits; } - private long _getCacheHits() + private int _getCacheHits() { return _cacheHit ? _newHits : 0; } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageResourceStatisticsFactory.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageResourceStatisticsFactory.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageResourceStatisticsFactory.java (working copy) @@ -24,6 +24,8 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang.BooleanUtils; + import org.ametys.runtime.datasource.ConnectionHelper; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.statistics.ResourceStatistics; @@ -61,7 +63,7 @@ try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("SELECT count(*) AS increment, Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable FROM " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " T WHERE PROCESSED = false GROUP BY Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable ORDER BY max(T.Id)"); + stmt = connection.prepareStatement("SELECT count(*) AS \"increment\", Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable FROM " + Constants.__SQL_TABLE_NAME_PAGE_ACCESS + " WHERE PROCESSED = 0 GROUP BY Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable"); resultSet = stmt.executeQuery(); while (resultSet.next()) @@ -70,8 +72,8 @@ String path = resultSet.getString("Page_Path"); String renderingContext = resultSet.getString("Rendering_Context"); String workspaceJCR = resultSet.getString("Workspace_JCR"); - boolean cacheable = resultSet.getBoolean("Cacheable"); - long increment = resultSet.getLong("increment"); + boolean cacheable = BooleanUtils.toBoolean(resultSet.getInt("Cacheable")); + int increment = resultSet.getInt("increment"); resourceStatisticsList.add(new PageResourceStatistics(pageId, path, renderingContext, workspaceJCR, cacheable, increment)); } @@ -87,43 +89,33 @@ } @Override - public long getMaxIdToProcess() throws SQLException + public int markResourcesAsProcessed() throws SQLException { Connection connection = null; Statement stmt = null; - ResultSet resultSet = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); stmt = connection.createStatement(); - resultSet = stmt.executeQuery("SELECT max(Id) FROM " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " WHERE PROCESSED = false"); - - if (resultSet.next()) - { - return resultSet.getLong(1); - } - return -1; + return stmt.executeUpdate("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_ACCESS + " SET PROCESSED = 1 WHERE Processed = 0"); } finally { - ConnectionHelper.cleanup(resultSet); ConnectionHelper.cleanup(stmt); ConnectionHelper.cleanup(connection); } } @Override - public int markResourcesAsProcessed(long id) throws SQLException + public int purgeRawData() throws SQLException { Connection connection = null; - PreparedStatement stmt = null; + Statement stmt = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " SET PROCESSED = true WHERE Id <= ? AND Processed = false"); - stmt.setLong(1, id); - - return stmt.executeUpdate(); + stmt = connection.createStatement(); + return stmt.executeUpdate("DELETE FROM " + Constants.__SQL_TABLE_NAME_PAGE_ACCESS + " WHERE PROCESSED = 1"); } finally { Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontFromHTTPServerResourceStatisticsFactory.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontFromHTTPServerResourceStatisticsFactory.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontFromHTTPServerResourceStatisticsFactory.java (working copy) @@ -67,20 +67,24 @@ try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("SELECT count(*) AS increment, S.Site AS S_Site, S.Path AS S_Path, S.Cache_Hit AS S_Cache_Hit, T.Site AS F_Site, T.Ametys_Path AS F_Ametys_Path, T.Cacheable AS F_Cacheable, T.Cache_Hit_1 AS F_Cache_Hit_1, T.Cache_Hit_2 AS F_Cache_Hit_2 FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " T INNER JOIN " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " S ON T.Unique_Id = S.Unique_Id AND T.Processed = false AND T.Unique_Id is not NULL AND (S.Ori_Status_Code = 200 OR S.Ori_Status_Code = 304) GROUP BY S.Site, S.Path, S.Cache_Hit, T.Site, T.Ametys_Path, T.Cacheable, T.Cache_Hit_1, T.Cache_Hit_2 ORDER BY max(T.Id)"); + stmt = connection.prepareStatement("SELECT count(*) AS \"increment\", S.Site AS \"S_Site\", S.Path AS \"S_Path\", S.Cache_Hit AS \"S_Cache_Hit\"," + + " F.Site AS \"F_Site\", F.Ametys_Path AS \"F_Ametys_Path\", F.Cacheable AS \"F_Cacheable\", F.Cache_Hit_1 AS \"F_Cache_Hit_1\", F.Cache_Hit_2 AS \"F_Cache_Hit_2\"" + + " FROM " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " F" + + " INNER JOIN " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " S ON F.Unique_Id = S.Unique_Id AND F.Processed = 0 AND (S.Ori_Status_Code = '200' OR S.Ori_Status_Code = '304')" + + " GROUP BY S.Site, S.Path, S.Cache_Hit, F.Site, F.Ametys_Path, F.Cacheable, F.Cache_Hit_1, F.Cache_Hit_2"); resultSet = stmt.executeQuery(); while (resultSet.next()) { String httpserverSite = resultSet.getString("S_Site"); String httpserverPath = resultSet.getString("S_Path"); - boolean httpserverCacheHit = BooleanUtils.toBoolean(resultSet.getBoolean("S_Cache_Hit")); // converts null to false, avoiding NPE while unboxing. + boolean httpserverCacheHit = BooleanUtils.toBoolean(resultSet.getInt("S_Cache_Hit")); String frontSite = resultSet.getString("F_Site"); String frontPath = resultSet.getString("F_Ametys_Path"); - boolean frontCacheable = resultSet.getBoolean("F_Cacheable"); - boolean frontCacheHit1 = BooleanUtils.toBoolean(resultSet.getBoolean("F_Cache_Hit_1")); // converts null to false, avoiding NPE while unboxing. - boolean frontCacheHit2 = BooleanUtils.toBoolean(resultSet.getBoolean("F_Cache_Hit_2")); // converts null to false, avoiding NPE while unboxing. - long newHits = resultSet.getLong("increment"); + boolean frontCacheable = BooleanUtils.toBoolean(resultSet.getInt("F_Cacheable")); + boolean frontCacheHit1 = BooleanUtils.toBoolean(resultSet.getInt("F_Cache_Hit_1")); + boolean frontCacheHit2 = BooleanUtils.toBoolean(resultSet.getInt("F_Cache_Hit_2")); + int newHits = resultSet.getInt("increment"); resourceStatisticsList.add(new FrontFromHTTPServerResourceStatistics(httpserverSite, httpserverPath, httpserverCacheHit, frontSite, frontPath, frontCacheable, frontCacheHit1, frontCacheHit2, newHits)); } @@ -96,51 +100,38 @@ } @Override - public long getMaxIdToProcess() throws SQLException + public int markResourcesAsProcessed() throws SQLException { Connection connection = null; Statement stmt = null; - ResultSet resultSet = null; + Statement stmt2 = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); + + StringBuilder sql = new StringBuilder(); + sql.append("UPDATE CACHE_RA_FRONT "); + sql.append("SET Processed = 1 "); + sql.append("WHERE Processed = 0 "); + sql.append("AND Unique_Id IN "); + sql.append(" (SELECT Unique_Id FROM CACHE_RA_HTTPSERVER WHERE (Ori_Status_Code = '200' OR Ori_Status_Code = '304'))"); stmt = connection.createStatement(); - resultSet = stmt.executeQuery("SELECT max(F.Id) FROM $tbl_name$ AS F INNER JOIN " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " S ON F.Unique_Id = S.Unique_Id AND F.Processed = false AND F.Unique_Id is not NULL AND (S.Ori_Status_Code = 200 OR S.Ori_Status_Code = 304)"); - - if (resultSet.next()) - { - return resultSet.getLong(1); - } - return -1; - } - finally - { - ConnectionHelper.cleanup(resultSet); - ConnectionHelper.cleanup(stmt); - ConnectionHelper.cleanup(connection); - } - } - - @Override - public int markResourcesAsProcessed(long id) throws SQLException - { - Connection connection = null; - PreparedStatement stmt = null; - PreparedStatement stmt2 = null; - try - { - connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " AS F INNER JOIN " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " S ON F.Unique_Id = S.Unique_Id AND F.Processed = false AND F.Unique_Id is not NULL AND (S.Ori_Status_Code = 200 OR S.Ori_Status_Code = 304) SET F.Processed = true WHERE F.Id <= ?"); - stmt.setLong(1, id); + int processed = stmt.executeUpdate(sql.toString()); - int processed = stmt.executeUpdate(); - stmt2 = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " AS S INNER JOIN " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " F ON S.Unique_Id = F.Unique_Id AND S.Processed = false AND F.Processed = true SET S.Processed = true"); - int processed2 = stmt2.executeUpdate(); + StringBuilder sql2 = new StringBuilder(); + sql2.append("UPDATE CACHE_RA_HTTPSERVER "); + sql2.append("SET Processed = 1 "); + sql2.append("WHERE Processed = 0 "); + sql2.append("AND (Ori_Status_Code = '200' OR Ori_Status_Code = '304') "); + sql2.append("AND Unique_Id IN "); + sql2.append(" (SELECT DISTINCT Unique_Id FROM CACHE_RA_FRONT)"); + stmt2 = connection.createStatement(); + int processed2 = stmt2.executeUpdate(sql2.toString()); - if (__LOGGER.isWarnEnabled()) + if (__LOGGER.isDebugEnabled()) { - __LOGGER.warn(String.format("Comparing processed and apacheProcessed for type 'FRONT_FROM_APACHE': %s-%s . These values should be equals.", processed, processed2)); + __LOGGER.debug(String.format("Comparing processed and apacheProcessed for type 'FRONT_FROM_APACHE': %s-%s . These values should be equals.", processed, processed2)); } return processed; @@ -152,4 +143,11 @@ ConnectionHelper.cleanup(connection); } } + + @Override + public int purgeRawData() throws SQLException + { + // Nothing to do here (as it is already done is FrontOnly & HTTPServerOnly factories) + return 0; + } } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontOnlyResourceStatistics.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontOnlyResourceStatistics.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontOnlyResourceStatistics.java (working copy) @@ -19,6 +19,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Timestamp; + +import org.apache.commons.lang.BooleanUtils; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.statistics.ResourceStatistics; @@ -33,7 +36,7 @@ private final boolean _cacheable; private final boolean _cacheHit1; private final boolean _cacheHit2; - private final long _newHits; + private final int _newHits; /** * Creates a statistics @@ -44,7 +47,7 @@ * @param cacheHit2 The cache hit 2 status * @param newHits The number of hits */ - public FrontOnlyResourceStatistics(String site, String path, boolean cacheable, boolean cacheHit1, boolean cacheHit2, long newHits) + public FrontOnlyResourceStatistics(String site, String path, boolean cacheable, boolean cacheHit1, boolean cacheHit2, int newHits) { _site = site; _path = path; @@ -57,7 +60,7 @@ @Override public PreparedStatement getFindStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("SELECT count(1) " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE Front_Site = ? AND Front_Path = ? AND Server_Path is NULL"); + PreparedStatement stmt = connection.prepareStatement("SELECT count(1) FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE Front_Site = ? AND Front_Path = ? AND Server_Path = '-'"); stmt.setString(1, _site); stmt.setString(2, _path); @@ -68,14 +71,18 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " (Front_Site, Front_Path, Front_Cacheable, Front_Hits, Front_Cache_Hits_1, Front_Cache_Hits_2) values (?, ?, ?, ?, ?, ?)"); + PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " (Front_Site, Front_Path, Front_Cacheable, Front_Hits, Front_Cache_Hits_1, Front_Cache_Hits_2, Created_At, Updated_At) values (?, ?, ?, ?, ?, ?, ?, ?)"); stmt.setString(1, _site); stmt.setString(2, _path); - stmt.setBoolean(3, _cacheable); - stmt.setLong(4, _newHits); - stmt.setLong(5, _getCacheHits1()); - stmt.setLong(6, _getCacheHits2()); + stmt.setInt(3, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(4, _newHits); + stmt.setInt(5, _getCacheHits1()); + stmt.setInt(6, _getCacheHits2()); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + stmt.setTimestamp(7, now); + stmt.setTimestamp(8, now); return stmt; } @@ -83,31 +90,32 @@ @Override public PreparedStatement getUpdateStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " SET Front_Cacheable = ?, Front_Hits = Front_Hits + ?, Front_Cache_Hits_1 = Front_Cache_Hits_1 + ?, Front_Cache_Hits_2 = Front_Cache_Hits_2 + ? WHERE Front_Site = ? AND Front_Path = ? AND Server_Path is NULL"); + PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " SET Front_Cacheable = ?, Front_Hits = Front_Hits + ?, Front_Cache_Hits_1 = Front_Cache_Hits_1 + ?, Front_Cache_Hits_2 = Front_Cache_Hits_2 + ?, Updated_At = ? WHERE Front_Site = ? AND Front_Path = ? AND Server_Path = '-'"); - stmt.setBoolean(1, _cacheable); - stmt.setLong(2, _newHits); - stmt.setLong(3, _getCacheHits1()); - stmt.setLong(4, _getCacheHits2()); + stmt.setInt(1, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(2, _newHits); + stmt.setInt(3, _getCacheHits1()); + stmt.setInt(4, _getCacheHits2()); + stmt.setTimestamp(5, new Timestamp(System.currentTimeMillis())); - stmt.setString(5, _site); - stmt.setString(6, _path); + stmt.setString(6, _site); + stmt.setString(7, _path); return stmt; } @Override - public long getHits() + public int getHits() { return _newHits; } - private long _getCacheHits1() + private int _getCacheHits1() { return _cacheHit1 ? _newHits : 0; } - private long _getCacheHits2() + private int _getCacheHits2() { return _cacheHit2 ? _newHits : 0; } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontOnlyResourceStatisticsFactory.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontOnlyResourceStatisticsFactory.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/FrontOnlyResourceStatisticsFactory.java (working copy) @@ -63,17 +63,17 @@ try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("SELECT count(*) AS increment, Site, Ametys_Path, Cacheable, Cache_Hit_1, Cache_Hit_2 FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " T WHERE PROCESSED = false AND Unique_Id is NULL GROUP BY Site, Ametys_Path, Cacheable, Cache_Hit_1, Cache_Hit_2 ORDER BY max(T.Id)"); + stmt = connection.prepareStatement("SELECT count(*) AS \"increment\", Site, Ametys_Path, Cacheable, Cache_Hit_1, Cache_Hit_2 FROM " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " WHERE PROCESSED = 0 AND Unique_Id = '-' GROUP BY Site, Ametys_Path, Cacheable, Cache_Hit_1, Cache_Hit_2"); resultSet = stmt.executeQuery(); while (resultSet.next()) { String site = resultSet.getString("Site"); String path = resultSet.getString("Ametys_Path"); - boolean cacheable = resultSet.getBoolean("Cacheable"); - boolean cacheHit1 = BooleanUtils.toBoolean(resultSet.getBoolean("Cache_Hit_1")); // converts null to false, avoiding NPE while unboxing. - boolean cacheHit2 = BooleanUtils.toBoolean(resultSet.getBoolean("Cache_Hit_2")); // converts null to false, avoiding NPE while unboxing. - long newHits = resultSet.getLong("increment"); + boolean cacheable = BooleanUtils.toBoolean(resultSet.getInt("Cacheable")); + boolean cacheHit1 = BooleanUtils.toBoolean(resultSet.getInt("Cache_Hit_1")); + boolean cacheHit2 = BooleanUtils.toBoolean(resultSet.getInt("Cache_Hit_2")); + int newHits = resultSet.getInt("increment"); resourceStatisticsList.add(new FrontOnlyResourceStatistics(site, path, cacheable, cacheHit1, cacheHit2, newHits)); } @@ -89,43 +89,33 @@ } @Override - public long getMaxIdToProcess() throws SQLException + public int markResourcesAsProcessed() throws SQLException { Connection connection = null; Statement stmt = null; - ResultSet resultSet = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); stmt = connection.createStatement(); - resultSet = stmt.executeQuery("SELECT max(Id) FROM " + Constants.__SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS + " WHERE PROCESSED = false AND Unique_Id is NULL"); - - if (resultSet.next()) - { - return resultSet.getLong(1); - } - return -1; + return stmt.executeUpdate("UPDATE " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " SET PROCESSED = 1 WHERE Processed = 0 AND Unique_Id = '-'"); } finally { - ConnectionHelper.cleanup(resultSet); ConnectionHelper.cleanup(stmt); ConnectionHelper.cleanup(connection); } } @Override - public int markResourcesAsProcessed(long id) throws SQLException + public int purgeRawData() throws SQLException { Connection connection = null; - PreparedStatement stmt = null; + Statement stmt = null; try { connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_HTTPSERVER_ACCESS + " SET PROCESSED = true WHERE Id <= ? AND Processed = false AND Unique_Id is NULL"); - stmt.setLong(1, id); - - return stmt.executeUpdate(); + stmt = connection.createStatement(); + return stmt.executeUpdate("DELETE FROM " + Constants.__SQL_TABLE_NAME_FRONT_ACCESS + " WHERE PROCESSED = 1"); } finally { Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageResourceStatistics.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageResourceStatistics.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/impl/PageResourceStatistics.java (working copy) @@ -19,6 +19,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Timestamp; + +import org.apache.commons.lang.BooleanUtils; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.statistics.ResourceStatistics; @@ -34,7 +37,7 @@ private final String _renderingContext; private final String _workspaceJCR; private final boolean _cacheable; - private final long _newHits; + private final int _newHits; /** * Creates a page resource statistics @@ -45,7 +48,7 @@ * @param cacheable Is the page cacheable ? * @param increment Number of associated hits */ - public PageResourceStatistics(String pageId, String path, String renderingContext, String jcrWorkspace, boolean cacheable, long increment) + public PageResourceStatistics(String pageId, String path, String renderingContext, String jcrWorkspace, boolean cacheable, int increment) { _pageId = pageId; _path = path; @@ -58,7 +61,7 @@ @Override public PreparedStatement getFindStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("SELECT count(1) " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " WHERE Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); + PreparedStatement stmt = connection.prepareStatement("SELECT count(1) FROM " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " WHERE Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); stmt.setString(1, _pageId); stmt.setString(2, _renderingContext); @@ -70,14 +73,18 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " (Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable, Hits) values (?, ?, ?, ?, ?, ?)"); + PreparedStatement stmt = connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " (Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable, Hits, Created_At, Updated_At) values (?, ?, ?, ?, ?, ?, ?, ?)"); stmt.setString(1, _pageId); stmt.setString(2, _path); stmt.setString(3, _renderingContext); stmt.setString(4, _workspaceJCR); - stmt.setBoolean(5, _cacheable); - stmt.setLong(6, _newHits); + stmt.setInt(5, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(6, _newHits); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + stmt.setTimestamp(7, now); + stmt.setTimestamp(8, now); return stmt; } @@ -85,21 +92,22 @@ @Override public PreparedStatement getUpdateStatement(Connection connection) throws SQLException { - PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " SET Page_Path = ?, Cacheable = ?, Hits = Hits + ? WHERE Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); + PreparedStatement stmt = connection.prepareStatement("UPDATE " + Constants.__SQL_TABLE_NAME_PAGE_STATISTICS + " SET Page_Path = ?, Cacheable = ?, Hits = Hits + ?, Updated_At = ? WHERE Page_Id = ? AND Rendering_Context = ? AND Workspace_JCR = ?"); stmt.setString(1, _path); - stmt.setBoolean(2, _cacheable); - stmt.setLong(3, _newHits); + stmt.setInt(2, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(3, _newHits); + stmt.setTimestamp(4, new Timestamp(System.currentTimeMillis())); - stmt.setString(4, _pageId); - stmt.setString(5, _renderingContext); - stmt.setString(6, _workspaceJCR); + stmt.setString(5, _pageId); + stmt.setString(6, _renderingContext); + stmt.setString(7, _workspaceJCR); return stmt; } @Override - public long getHits() + public int getHits() { return _newHits; } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatistics.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatistics.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatistics.java (working copy) @@ -54,5 +54,5 @@ * Returns the number of hits * @return int the hits */ - public long getHits(); + public int getHits(); } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatisticsComponent.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatisticsComponent.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatisticsComponent.java (working copy) @@ -29,8 +29,6 @@ import org.ametys.runtime.datasource.ConnectionHelper; import org.ametys.web.cache.monitoring.Constants; -import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess; -import org.ametys.web.cache.monitoring.process.access.impl.PageResourceAccess; import org.ametys.web.cache.monitoring.process.statistics.impl.FrontFromHTTPServerResourceStatisticsFactory; import org.ametys.web.cache.monitoring.process.statistics.impl.FrontOnlyResourceStatisticsFactory; import org.ametys.web.cache.monitoring.process.statistics.impl.HTTPServerOnlyResourceStatisticsFactory; @@ -50,7 +48,10 @@ */ public void updateStatistics() { - getLogger().debug("Updating cache stats tables..."); + if (getLogger().isDebugEnabled()) + { + getLogger().debug("Updating cache stats tables..."); + } long start = System.currentTimeMillis(); int totalUpdated = 0; @@ -86,34 +87,19 @@ private int _update(Connection connection, String logName, ResourceStatisticsFactory factory) throws SQLException { - ResultSet rs = null; + // Retrieves resources to process + update cache stats + List<ResourceStatistics> resourceStatisticsList = factory.getResourceAccessToProcess(); + int hits = _updateCacheStats(connection, resourceStatisticsList); - try - { - long id = factory.getMaxIdToProcess(); - if (id <= 0) - { - // nothing to do. - return 0; - } - - // Retrieves resources to process + update cache stats - List<ResourceStatistics> resourceStatisticsList = factory.getResourceAccessToProcess(); - int hits = _updateCacheStats(connection, resourceStatisticsList); - - // Mark handled resource access as processed - int processed = factory.markResourcesAsProcessed(id); - if (getLogger().isDebugEnabled()) - { - getLogger().debug(String.format("It appears to be %s new hits for the ResourceStatistics '%s'. Also, %s access logs have been marked has processed.", hits, logName, processed)); - } - - return processed; - } - finally + // Mark handled resource access as processed + int processed = factory.markResourcesAsProcessed(); + + if (getLogger().isDebugEnabled()) { - ConnectionHelper.cleanup(rs); + getLogger().debug(String.format("It appears to be %s new hits for the ResourceStatistics '%s'. Also, %s access logs have been marked has processed.", hits, logName, processed)); } + + return processed; } private int _updateCacheStats(Connection connection, List<ResourceStatistics> resourceStatisticsList) throws SQLException @@ -121,7 +107,6 @@ int hits = 0; PreparedStatement stmt = null; - ResultSet resultSet = null; try { for (ResourceStatistics resourceStatistics : resourceStatisticsList) @@ -141,7 +126,6 @@ } finally { - ConnectionHelper.cleanup(resultSet); ConnectionHelper.cleanup(stmt); } @@ -173,33 +157,25 @@ */ public void purgeRawData() { - getLogger().debug("Purging raw monitoring data..."); - long start = System.currentTimeMillis(); + long start = 0; + if (getLogger().isDebugEnabled()) + { + getLogger().debug("Purging raw monitoring data..."); + start = System.currentTimeMillis(); + } int totalPurged = 0; - - Connection connection = null; - PreparedStatement stmt = null; - PreparedStatement stmt2 = null; try { - connection = ConnectionHelper.getConnection(Constants.MONITORING_DATASOURCE_POOLNAME); - - stmt = PageResourceAccess.getPurgeStatement(connection); - totalPurged += stmt.executeUpdate(); - - stmt2 = PageElementResourceAccess.getPurgeStatement(connection); - totalPurged += stmt2.executeUpdate(); + totalPurged += PageResourceStatisticsFactory.getInstance().purgeRawData(); + totalPurged += PageElementResourceStatisticsFactory.getInstance().purgeRawData(); + totalPurged += FrontOnlyResourceStatisticsFactory.getInstance().purgeRawData(); + totalPurged += HTTPServerOnlyResourceStatisticsFactory.getInstance().purgeRawData(); + totalPurged += FrontFromHTTPServerResourceStatisticsFactory.getInstance().purgeRawData(); } catch (SQLException e) { - getLogger().error("An error occured whil purging raw monitoring data", e); - } - finally - { - ConnectionHelper.cleanup(stmt); - ConnectionHelper.cleanup(stmt2); - ConnectionHelper.cleanup(connection); + getLogger().error("An error occured while purging raw monitoring data", e); } if (getLogger().isDebugEnabled()) Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatisticsFactory.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatisticsFactory.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/statistics/ResourceStatisticsFactory.java (working copy) @@ -32,17 +32,16 @@ public List<ResourceStatistics> getResourceAccessToProcess() throws SQLException; /** - * Get the max id of this kind of statistics - * @return The id + * Mark the statistics of this kind as processed + * @return The number of resources processed * @throws SQLException If an error occured */ - public long getMaxIdToProcess() throws SQLException; + public int markResourcesAsProcessed() throws SQLException; /** - * Mark the statistics of this kind as processed - * @param id The max id to process - * @return The number of resources processed - * @throws SQLException If an error occured + * Purge the processed raw data related to this kind of statistics. + * @return The number of purged rows. + * @throws SQLException */ - public int markResourcesAsProcessed(long id) throws SQLException; + public int purgeRawData() throws SQLException; } Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/CacheMonitoringScheduler.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/CacheMonitoringScheduler.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/CacheMonitoringScheduler.java (working copy) @@ -74,29 +74,33 @@ return; } - if (_logger.isDebugEnabled()) - { - _logger.debug("Scheduling the CacheMonitoringScheduler component to run its task each hours"); - } - // Daemon thread _timer = new Timer("CacheMonitoringScheduler", true); - // The task is each hour, starting at h5m if not too late. + // The task is each hour, starting at h15m if not too late. // It is a quarter after the execution of the task of the FrontCacheMonitoringScheduler GregorianCalendar calendar = new GregorianCalendar(); int minute = calendar.get(Calendar.MINUTE); - if (minute > 0) + // If 3h10, will starts at 3h15. + // If 3h11, will starts at 4h15 + if (minute > 10) { calendar.add(Calendar.HOUR_OF_DAY, 1); } - calendar.set(Calendar.MINUTE, 5); + calendar.set(Calendar.MINUTE, 15); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); - _timer.scheduleAtFixedRate(this, calendar.getTime(), 60 * 60 * 1000); + // TODO uncomment after testing +// _timer.scheduleAtFixedRate(this, calendar.getTime(), 60 * 60 * 1000); + _timer.scheduleAtFixedRate(this, 30 * 1000, 60 * 1000); + + if (_logger.isInfoEnabled()) + { + _logger.info("Cache monitoring scheduler : The process will run each hour, starting " + calendar.getTime()); + } } @Override Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/ResourceAccessComponent.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/ResourceAccessComponent.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/ResourceAccessComponent.java (working copy) @@ -16,6 +16,7 @@ package org.ametys.web.cache.monitoring.process.access; +import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; @@ -155,10 +156,15 @@ return 0; } - catch (SQLException e) + catch (BatchUpdateException e) { - // more detailed treatment is possible through e.getUpdateCounts() getLogger().error("Batch exception while inserting new records to the database", e); + // more detailed treatment is possible through e.getUpdateCounts() + return 0; + } + catch (SQLException e) + { + getLogger().error("SQLException exception while inserting new records to the database", e); return 0; } finally Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/impl/PageResourceAccess.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/impl/PageResourceAccess.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/impl/PageResourceAccess.java (working copy) @@ -19,8 +19,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.sql.Statement; +import java.sql.Timestamp; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.ametys.web.cache.monitoring.Constants; @@ -49,7 +50,7 @@ */ public PageResourceAccess(String internalUuid, String pageID, String path) { - _internalUuid = internalUuid; + _internalUuid = StringUtils.defaultIfEmpty(internalUuid, "-"); _pageID = pageID; _path = StringUtils.substringBefore(path, "?"); } @@ -58,7 +59,7 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - return connection.prepareStatement("INSERT IGNORE INTO " + Constants.__SQL_TABLE_NAME_PAGE_ACCESS + " (Internal_Uuid, Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable) values (?, ?, ?, ?, ?, ?)", Statement.NO_GENERATED_KEYS); + return connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_PAGE_ACCESS + " (Internal_Uuid, Page_Id, Page_Path, Rendering_Context, Workspace_JCR, Cacheable, Created_At) values (?, ?, ?, ?, ?, ?, ?)"); } @Override @@ -69,23 +70,10 @@ stmt.setString(3, _path); stmt.setString(4, _renderingContext.toString()); stmt.setString(5, _workspaceJCR); - stmt.setBoolean(6, _cacheable); - } - - /** - * Creates the purge statement used when doing the SQL purge - * @param connection - * @return The prepares statement ready to execute - * @throws SQLException - */ - public static PreparedStatement getPurgeStatement(Connection connection) throws SQLException - { - return connection.prepareStatement("DELETE FROM " + Constants.__SQL_TABLE_NAME_PAGE_ACCESS + " WHERE PROCESSED = true"); + stmt.setInt(6, BooleanUtils.toInteger(_cacheable)); + stmt.setTimestamp(7, new Timestamp(System.currentTimeMillis())); } - - - /** * Create a page element resource access for this page resource access. * @param pageElementID Index: main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/impl/PageElementResourceAccess.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/impl/PageElementResourceAccess.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/process/access/impl/PageElementResourceAccess.java (working copy) @@ -19,8 +19,10 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; +import java.sql.Timestamp; + +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; import org.ametys.web.cache.monitoring.Constants; import org.ametys.web.cache.monitoring.process.access.ResourceAccess; @@ -50,31 +52,31 @@ /** * Utility method the get the PageElementType corresponding to a ZoneType - * @param ziType + * @param zoneItemType * @return the PageElementType */ - public static PageElementType fromZoneItemType(ZoneType ziType) + public static PageElementType fromZoneItemType(ZoneType zoneItemType) { - switch (ziType) + switch (zoneItemType) { case CONTENT: - return CONTENT; + return PageElementType.CONTENT; case SERVICE: - return SERVICE; + return PageElementType.SERVICE; default: - throw new IllegalArgumentException("Unknown ZoneType : " + ziType); + throw new IllegalArgumentException("Unknown ZoneType : " + zoneItemType); } } } private final String _internalUuid; + private final String _pageID; private final String _pageElementID; private final PageElementType _pageElementType; - private final String _pageID; private final RenderingContext _renderingContext; private final String _workspaceJCR; private boolean _cacheable; - private Boolean _cacheHit; + private boolean _cacheHit; /** * Ctor @@ -85,12 +87,12 @@ * @param rc * @param ws */ - public PageElementResourceAccess(String uuid, String peid, String pageID, PageElementType pet, RenderingContext rc, String ws) + public PageElementResourceAccess(String uuid, String pageID, String peid, PageElementType pet, RenderingContext rc, String ws) { - _internalUuid = uuid; + _internalUuid = StringUtils.defaultIfEmpty(uuid, "-"); + _pageID = pageID; _pageElementID = peid; _pageElementType = pet; - _pageID = pageID; _renderingContext = rc; _workspaceJCR = ws; } @@ -98,7 +100,7 @@ @Override public PreparedStatement getInsertStatement(Connection connection) throws SQLException { - return connection.prepareStatement("INSERT IGNORE INTO " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS + " (Internal_Uuid, Page_Element_Id, Page_Element_Type, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Cache_Hit) values (?, ?, ?, ?, ?, ?, ?, ?)", Statement.NO_GENERATED_KEYS); + return connection.prepareStatement("INSERT INTO " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS + " (Internal_Uuid, Page_Element_Id, Page_Element_Type, Page_Id, Rendering_Context, Workspace_JCR, Cacheable, Cache_Hit, Created_At) values (?, ?, ?, ?, ?, ?, ?, ?, ?)"); } @Override @@ -110,20 +112,9 @@ stmt.setString(4, _pageID); stmt.setString(5, _renderingContext.toString()); stmt.setString(6, _workspaceJCR); - stmt.setBoolean(7, _cacheable); - // Handle null cases, avoid NPE and set NULL into the db in thoses cases. - stmt.setObject(8, _cacheHit, Types.BOOLEAN); - } - - /** - * Creates the purge statement used when doing the SQL purge - * @param connection - * @return The prepares statement ready to execute - * @throws SQLException - */ - public static PreparedStatement getPurgeStatement(Connection connection) throws SQLException - { - return connection.prepareStatement("DELETE FROM " + Constants.__SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS + " WHERE PROCESSED = true"); + stmt.setInt(7, BooleanUtils.toInteger(_cacheable)); + stmt.setInt(8, BooleanUtils.toInteger(_cacheHit)); + stmt.setTimestamp(9, new Timestamp(System.currentTimeMillis())); } /** Index: main/plugin-web/src/org/ametys/web/cache/monitoring/Constants.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/monitoring/Constants.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/cache/monitoring/Constants.java (working copy) @@ -25,18 +25,18 @@ public static final String MONITORING_DATASOURCE_POOLNAME = "cache.monitoring.datasource"; /** The name of the table for page resource access */ - public static final String __SQL_TABLE_NAME_PAGE_ACCESS = "Back_Requests"; + public static final String __SQL_TABLE_NAME_PAGE_ACCESS = "Cache_RA_Back"; /** The name of the table for page elements resource access */ - public static final String __SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS = "Back_Page_Element_Requests"; + public static final String __SQL_TABLE_NAME_PAGE_ELEMENTS_ACCESS = "Cache_RA_Back_Page_Element"; /** The name of the table for front resource access */ - public static final String __SQL_TABLE_NAME_FRONT_ACCESS = "Front_Requests"; + public static final String __SQL_TABLE_NAME_FRONT_ACCESS = "Cache_RA_Front"; /** The name of the table for httpserver resource access */ - public static final String __SQL_TABLE_NAME_HTTPSERVER_ACCESS = "Server_Requests"; + public static final String __SQL_TABLE_NAME_HTTPSERVER_ACCESS = "Cache_RA_HTTPServer"; /** The name of the table for back statictics */ - public static final String __SQL_TABLE_NAME_PAGE_STATISTICS = "Cache_Back_Stats"; + public static final String __SQL_TABLE_NAME_PAGE_STATISTICS = "Cache_Stats_Back"; /** The name of the table for back statictics for page elements*/ - public static final String __SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS = "Cache_Back_Page_Element_Stats"; + public static final String __SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS = "Cache_Stats_Back_Page_Element"; /** The name of the table for front statictics */ - public static final String __SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS = "Cache_Front_Stats"; + public static final String __SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS = "Cache_Stats_Front"; } Index: main/plugin-web/src/org/ametys/web/repository/site/SiteGenerator.java =================================================================== --- main/plugin-web/src/org/ametys/web/repository/site/SiteGenerator.java (revision 20673) +++ main/plugin-web/src/org/ametys/web/repository/site/SiteGenerator.java (working copy) @@ -74,6 +74,7 @@ attr.addAttribute("", "id", "id", "CDATA", site.getId()); attr.addAttribute("", "name", "name", "CDATA", site.getName()); attr.addAttribute("", "title", "title", "CDATA", StringUtils.defaultString(site.getTitle())); + attr.addAttribute("", "path", "path", "CDATA", site.getSitePath()); XMLUtils.startElement(contentHandler, "site", attr); _saxSite (site); XMLUtils.endElement(contentHandler, "site"); @@ -84,7 +85,7 @@ private void _saxSite (Site site) throws SAXException { CompositeMetadata metaHolder = site.getMetadataHolder(); - + XMLUtils.startElement(contentHandler, "metadata"); String[] metadataNames = metaHolder.getMetadataNames(); for (int i = 0; i < metadataNames.length; i++) @@ -100,5 +101,5 @@ XMLUtils.endElement(contentHandler, "metadata"); } - + } Index: main/plugin-web/pages/administrator/sites/cache-statistics-back-tree.xsl =================================================================== --- main/plugin-web/pages/administrator/sites/cache-statistics-back-tree.xsl (revision 0) +++ main/plugin-web/pages/administrator/sites/cache-statistics-back-tree.xsl (revision 0) @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2012 Anyware Services + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:i18n="http://apache.org/cocoon/i18n/2.1" + xmlns:text="http://ametys.org/text/3.0" + extension-element-prefixes="text"> + + <xsl:import href="plugin:core://stylesheets/helper/text.xsl"/> + + <xsl:param name="contextPath"/> + <xsl:param name="pluginName"/> + + + <xsl:template match="/stats"> + <root> + <!-- filters site that contains at least a page with a context (ie. some statistics) --> + <xsl:apply-templates select="site" /> + </root> + </xsl:template> + + <xsl:template match="site"> + <site id="{@id}" label="{@name}" qtip="{@id}" leaf="true" expanded="true" + icon="{$contextPath}/plugins/{$pluginName}/resources/img/administrator/stats/sitemap_16.png" cls="site-node"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum" /></xsl:variable> + + <xsl:attribute name="pageHits"><xsl:call-template name="get-pagehits-sum" /></xsl:attribute> + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="sitemap[descendant::context[1]]"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </site> + </xsl:template> + + <xsl:template match="sitemap"> + <sitemap id="{@id}" label="{@name}" qtip="{@id}" leaf="true" expanded="true" + icon="{$contextPath}/plugins/{$pluginName}/resources/img/administrator/stats/sitemap_16.png" cls="sitemap-node"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum" /></xsl:variable> + + <xsl:attribute name="pageHits"><xsl:call-template name="get-pagehits-sum" /></xsl:attribute> + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="page[descendant::context[1]]"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </sitemap> + </xsl:template> + + <xsl:template match="page"> + <page id="{@id}" label="{@name}.html" qtip="{@id}" leaf="true" + icon="{$contextPath}/plugins/{$pluginName}/resources/img/administrator/stats/content_16.png" cls="page-node"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum" /></xsl:variable> + + <xsl:attribute name="pageHits"><xsl:call-template name="get-pagehits-sum" /></xsl:attribute> + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="self::page[context[1]]" mode="alone" /> + <xsl:apply-templates select="page[descendant::context[1]]"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </page> + </xsl:template> + + <xsl:template match="page" mode="alone"> + <context id="{@id}_alone" label="détails" qtip="Détails des statistiques pour la page {@name}.html" leaf="true" + iconCls="x-tree-node-inline-icon" cls="context-node"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum-details" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum-details" /></xsl:variable> + + <xsl:attribute name="pageHits"><xsl:call-template name="get-pagehits-sum-details" /></xsl:attribute> + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean-details" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="context"> + <xsl:sort select="@renderingContext" /> + <xsl:sort select="@workspaceJCR" /> + </xsl:apply-templates> + </context> + </xsl:template> + + <xsl:template match="context"> + <context id="{../@id}_{@renderingContext}_{@workspaceJCR}" leaf="true" icon="" iconCls="x-tree-node-inline-icon" cls="context-node" + label="{@renderingContext}/{@workspaceJCR}" pageHits="{hits}"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum" /></xsl:variable> + + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="zone|inputdata" /> + </context> + </xsl:template> + + <xsl:template match="zone"> + <zone id="{@id}_{../@renderingContext}_{../@workspaceJCR}" label="{@name}" qtip="{@id}" leaf="true" icon="" iconCls="x-tree-node-inline-icon" cls="zone-node"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum" /></xsl:variable> + + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="zoneitem" /> + </zone> + </xsl:template> + + <xsl:template match="zoneitem"> + <zoneitem id="{@id}_{../../@renderingContext}_{../../@workspaceJCR}" leaf="true" icon="" iconCls="x-tree-node-inline-icon" + label="#{@index} ({@type})" cacheable="{@cacheable}" hits="{hits}" cacheHits="{cacheHits}" eff="{round(cacheHits*100 div hits)} %"> + + <xsl:attribute name="qtip"> + <xsl:value-of select="concat('id : ', @id, '<br/>')" /> + <xsl:value-of select="concat('type : ', @type, '<br/>')" /> + <xsl:choose> + <xsl:when test="@type = 'content'"> + <xsl:value-of select="concat('content type : ', @contentType, '<br/>')" /> + <xsl:value-of select="concat('content id : ', @contentId)" /> + </xsl:when> + <xsl:when test="@type = 'service'"> + <xsl:value-of select="concat('service id : ', @serviceId)" /> + </xsl:when> + </xsl:choose> + </xsl:attribute> + </zoneitem> + </xsl:template> + + <xsl:template match="inputdata"> + <inputdata id="{../../@id}_{../@renderingContext}_{../@workspaceJCR}_inputdata" label="InputData" leaf="true" icon="" iconCls="x-tree-node-inline-icon" cls="inputdata-node"> + <xsl:variable name="hits"><xsl:call-template name="get-hits-sum" /></xsl:variable> + <xsl:variable name="cacheHits"><xsl:call-template name="get-cachehits-sum" /></xsl:variable> + + <xsl:attribute name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:attribute> + <xsl:attribute name="hits"><xsl:value-of select="$hits" /></xsl:attribute> + <xsl:attribute name="cacheHits"><xsl:value-of select="$cacheHits" /></xsl:attribute> + <xsl:attribute name="eff"><xsl:value-of select="round($cacheHits*100 div $hits)" /><xsl:text> %</xsl:text></xsl:attribute> + + <xsl:apply-templates select="inputdataitem" /> + </inputdata> + </xsl:template> + + <xsl:template match="inputdataitem"> + <inputdataitem id="{../../../@id}_{../../@renderingContext}_{../../@workspaceJCR}_{@id}" qtip="{@id}" leaf="true" icon="" iconCls="x-tree-node-inline-icon" + label="{@title}" cacheable="{@cacheable}" hits="{hits}" cacheHits="{cacheHits}" eff="{round(cacheHits*100 div hits)} %"> + </inputdataitem> + </xsl:template> + + <xsl:template name="get-pagehits-sum"> + <xsl:value-of select="sum(.//context/hits)" /> + </xsl:template> + + <xsl:template name="get-cachehits-sum"> + <xsl:value-of select="sum(.//zoneitem/cacheHits|.//inputdataitem/cacheHits)" /> + </xsl:template> + + <xsl:template name="get-hits-sum"> + <xsl:value-of select="sum(.//zoneitem/hits|.//inputdataitem/hits)" /> + </xsl:template> + + <xsl:template name="get-pagehits-sum-details"> + <xsl:value-of select="sum(context/hits)" /> + </xsl:template> + + <!-- moyenne du nombre de page element cacheables --> + <xsl:template name="get-cacheable-mean"> + <xsl:variable name="cacheables" select="count(.//zoneitem[@cacheable='true']|.//inputdataitem[@cacheable='true'])" /> + <xsl:variable name="total" select="count(.//zoneitem|.//inputdataitem)" /> + <xsl:value-of select="round($cacheables*100 div $total)" /><xsl:text> %</xsl:text> + </xsl:template> + + <!-- moyenne du nombre de pages element cacheables ponderée par le nombre de hits --> + <xsl:template name="get-weighted-cacheable-mean"> + <xsl:variable name="cacheables" select="sum(.//zoneitem[@cacheable='true']/hits|.//inputdataitem[@cacheable='true']/hits)" /> + <xsl:variable name="total" select="sum(.//zoneitem/hits|.//inputdataitem/hits)" /> + <xsl:value-of select="round($cacheables*100 div $total)" /><xsl:text> %</xsl:text> + </xsl:template> + + <!-- moyenne du nombre de page element cacheables pour la page courante --> + <xsl:template name="get-cacheable-mean-details"> + <xsl:variable name="cacheables" select="count(context/zone/zoneitem[@cacheable='true']|context/inputdata/inputdataitem[@cacheable='true'])" /> + <xsl:variable name="total" select="count(context/zone/zoneitem|context/inputdata/inputdataitem)" /> + <xsl:value-of select="round($cacheables*100 div $total)" /><xsl:text> %</xsl:text> + </xsl:template> + + <!-- moyenne du nombre de pages element cacheables ponderée par le nombre de hits pour la page courante --> + <xsl:template name="get-weighted-cacheable-mean-details"> + <xsl:variable name="cacheables" select="sum(context/zone/zoneitem[@cacheable='true']/hits|context/inputdata/inputdataitem[@cacheable='true']/hits)" /> + <xsl:variable name="total" select="sum(context/zone/zoneitem/hits|context/inputdata/inputdataitem/hits)" /> + <xsl:value-of select="round($cacheables*100 div $total)" /><xsl:text> %</xsl:text> + </xsl:template> + + <xsl:template name="get-cachehits-sum-details"> + <xsl:value-of select="sum(context/zone/zoneitem/cacheHits|context/inputdata/inputdataitem/cacheHits)" /> + </xsl:template> + + <xsl:template name="get-hits-sum-details"> + <xsl:value-of select="sum(context/zone/zoneitem/hits|context/inputdata/inputdataitem/hits)" /> + </xsl:template> + +</xsl:stylesheet> Index: main/plugin-web/pages/administrator/sites/cache-statistics-back.xsl =================================================================== --- main/plugin-web/pages/administrator/sites/cache-statistics-back.xsl (revision 0) +++ main/plugin-web/pages/administrator/sites/cache-statistics-back.xsl (revision 0) @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2012 Anyware Services + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<xsl:stylesheet version="1.0" + xmlns:i18n="http://apache.org/cocoon/i18n/2.1" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:ametys="org.ametys.web.transformation.xslt.AmetysXSLTHelper" + exclude-result-prefixes="ametys"> + + <xsl:param name="contextPath"/> + <xsl:param name="pluginName"/> + + <xsl:template match="/"> + <html> + <head> + <title> + <i18n:translate> + <i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_BACK_STATISTICS_TITLE"/> + <i18n:param name="name"><xsl:value-of select="site/@name"/></i18n:param> + </i18n:translate> + </title> + <link rel="stylesheet" href="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/treegrid.css')}" type="text/css"/> + <style> + .custom-hd-row { background-image: url("<xsl:value-of select="ametys:pluginResourceURL('extjs', 'images/default/grid/grid3-hrow.gif')" />"); } + </style> + </head> + + <script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGrid.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridColumnResizer.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridColumns.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridLoader.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridNodeUI.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridSorter.js')}"></script> + + <script type="text/javascript" src="{ametys:pluginResourceURL($pluginName, 'js/org/ametys/web/administration/CacheStatistics.i18n.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL($pluginName, 'js/org/ametys/web/administration/CacheStatisticsBack.i18n.js')}"></script> + + <script type="text/javascript"> + org.ametys.web.administration.CacheStatisticsBack.init("<xsl:value-of select="$pluginName"/>", "<xsl:value-of select="site/@name"/>", "<xsl:value-of select="site/@path"/>"); + + org.ametys.runtime.administrator.Panel.createPanel = function () + { + return new Ext.Panel({ + region: 'center', + + baseCls: 'transparent-panel', + border: false, + layout: 'border', + autoScroll: true, + + items : [org.ametys.web.administration.CacheStatisticsBack._centerPanel, + org.ametys.web.administration.CacheStatisticsBack._rightPanel + ] + }); + } + </script> + </script> + + <body> + </body> + </html> + </xsl:template> + +</xsl:stylesheet> Index: main/plugin-web/pages/administrator/sites/cache-statistics-servers-tree.xsl =================================================================== --- main/plugin-web/pages/administrator/sites/cache-statistics-servers-tree.xsl (revision 0) +++ main/plugin-web/pages/administrator/sites/cache-statistics-servers-tree.xsl (revision 0) @@ -0,0 +1,435 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2012 Anyware Services + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:i18n="http://apache.org/cocoon/i18n/2.1" + xmlns:text="http://ametys.org/text/3.0" + extension-element-prefixes="text"> + + <xsl:import href="plugin:core://stylesheets/helper/text.xsl"/> + + <xsl:param name="contextPath"/> + <xsl:param name="pluginName"/> + + <xsl:template match="/stats"> + <root> + <xsl:apply-templates select="site" /> + + <!-- Displays orphans if it contains at least some statistics --> + <xsl:apply-templates select="orphans[descendant::resource[1]]" /> + </root> + </xsl:template> + + <xsl:template match="site"> + <site> + <xsl:call-template name="entry-attributes"> + <xsl:with-param name="label" select="concat('Site : ', @name)" /> + <xsl:with-param name="desc" select="@id" /> + <xsl:with-param name="expanded" select="'true'" /> + <xsl:with-param name="icon" select="concat($contextPath, '/plugins/', $pluginName, '/resources/img/administrator/stats/sitemap_16.png')" /> + </xsl:call-template> + + <xsl:apply-templates select="resource"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </site> + <total> + <!-- Total for pages only --> + <xsl:call-template name="entry-attributes"> + <xsl:with-param name="label" select="concat('Site : ', @name, ' (pages)')" /> + <xsl:with-param name="desc" select="concat('Total des statistiques pour les pages du site ', @name)" /> + <xsl:with-param name="icon" select="concat($contextPath, '/plugins/', $pluginName, '/resources/img/administrator/stats/sitemap_16.png')" /> + + <xsl:with-param name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean-total-page" /></xsl:with-param> + <xsl:with-param name="apacheHits"><xsl:call-template name="get-apacheHits-sum-total-page" /></xsl:with-param> + <xsl:with-param name="apacheCacheHits"><xsl:call-template name="get-apacheCachehits-sum-total-page" /></xsl:with-param> + <xsl:with-param name="frontHits"><xsl:call-template name="get-frontHits-sum-total-page" /></xsl:with-param> + <xsl:with-param name="frontCacheHits"><xsl:call-template name="get-frontCachehits-sum-total-page" /></xsl:with-param> + <xsl:with-param name="backHits"><xsl:call-template name="get-backHits-sum-total-page" /></xsl:with-param> + </xsl:call-template> + </total> + + <spacer> + <xsl:call-template name="node-attributes" /> + </spacer> + </xsl:template> + + <xsl:template match="orphans"> + <orphans> + <xsl:call-template name="entry-attributes"> + <xsl:with-param name="label" select="'Orphelins'" /> + <xsl:with-param name="desc" select="'Statistiques non rattachées à un site.'" /> + <xsl:with-param name="expanded" select="'true'" /> + <xsl:with-param name="icon" select="concat($contextPath, '/plugins/', $pluginName, '/resources/img/administrator/stats/sitemap_16.png')" /> + </xsl:call-template> + + <xsl:apply-templates select="resource"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </orphans> + </xsl:template> + + <xsl:template match="resource"> + <xsl:choose> + <xsl:when test="@type='folder'"><xsl:call-template name="folder" /></xsl:when> + <xsl:otherwise><xsl:call-template name="file" /></xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="folder"> + <resource> + <xsl:call-template name="entry-attributes"> + <xsl:with-param name="label" select="@name" /> + </xsl:call-template> + + <xsl:apply-templates select="resource"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </resource> + </xsl:template> + + <xsl:template name="file"> + <xsl:variable name="isApacheEntry" select="boolean(entry[@type='apache'])" /> + <xsl:variable name="isFrontEntry" select="boolean(entry[@type='front'])" /> + <xsl:variable name="isBackEntry" select="boolean(entry[@type='back'])" /> + + <resource> + <xsl:variable name="apachePath"> + <xsl:if test="$isApacheEntry"><xsl:value-of select="concat('Apache : ', entry[@type='apache']/@apachePath, '<br/>')" /></xsl:if> + </xsl:variable> + <xsl:variable name="frontPath"> + <xsl:choose> + <xsl:when test="$isFrontEntry"><xsl:value-of select="concat('Front : ', entry[@type='front']/@path, '<br/>')" /></xsl:when> + <xsl:when test="entry[@type='apache']/@frontPath"><xsl:value-of select="concat('Front : ', entry[@type='apache']/@frontPath, '<br/>')" /></xsl:when> + </xsl:choose> + </xsl:variable> + <xsl:variable name="backId"> + <xsl:if test="$isBackEntry"><xsl:value-of select="concat('Id : ', entry[@type='back']/@id)" /></xsl:if> + </xsl:variable> + + <xsl:variable name="cacheable"> + <xsl:call-template name="get-weighted-cacheable-mean-page" /> + </xsl:variable> + <xsl:variable name="apacheHits"> + <xsl:variable name="child"><xsl:call-template name="get-apacheHits-sum" /></xsl:variable> + <xsl:value-of select="$child + sum(entry[@type='apache']/apacheHits)" /> + </xsl:variable> + <xsl:variable name="apacheCacheHits"> + <xsl:variable name="child"><xsl:call-template name="get-apacheCachehits-sum" /></xsl:variable> + <xsl:value-of select="$child + sum(entry[@type='apache']/apacheCacheHits)" /> + </xsl:variable> + <xsl:variable name="frontHits"> + <xsl:variable name="child"><xsl:call-template name="get-frontHits-sum" /></xsl:variable> + <xsl:value-of select="$child + sum(entry[@type='apache' or @type='front']/*[local-name()='frontHits' or local-name()='hits'])" /> + </xsl:variable> + <xsl:variable name="frontCacheHits"> + <xsl:variable name="child"><xsl:call-template name="get-frontCachehits-sum" /></xsl:variable> + <xsl:value-of select="$child + sum(entry[@type='apache' or @type='front']/*[local-name()='frontCacheHits1' or local-name()='frontCacheHits2' or local-name()='cacheHits1' or local-name()='cacheHits2'])" /> + </xsl:variable> + <xsl:variable name="backHits"> + <xsl:choose> + <xsl:when test="@type = 'page'"> + <xsl:variable name="child"><xsl:call-template name="get-backHits-sum" /></xsl:variable> + <xsl:value-of select="$child + sum(entry[@type='back']/hits)" /> + </xsl:when> + <xsl:otherwise><xsl:text>N/A</xsl:text></xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:call-template name="entry-attributes"> + <xsl:with-param name="label" select="@name" /> + <xsl:with-param name="desc" select="concat($apachePath, $frontPath, $backId)" /> + + <xsl:with-param name="cacheable" select="$cacheable" /> + <xsl:with-param name="apacheHits" select="$apacheHits" /> + <xsl:with-param name="apacheCacheHits" select="$apacheCacheHits" /> + <xsl:with-param name="frontHits" select="$frontHits" /> + <xsl:with-param name="frontCacheHits" select="$frontCacheHits" /> + <xsl:with-param name="backHits" select="$backHits" /> + </xsl:call-template> + + <xsl:apply-templates select="self::resource[resource]" mode="alone" /> + + <xsl:apply-templates select="resource"> + <xsl:sort select="@name" /> + </xsl:apply-templates> + </resource> + </xsl:template> + + <xsl:template match="resource" mode="alone"> + <xsl:if test="@type='page'"> + <xsl:call-template name="file-alone" /> + </xsl:if> + </xsl:template> + + <xsl:template name="file-alone"> + <resource> + <xsl:call-template name="entry-attributes"> + <xsl:with-param name="label" select="'détails'" /> + <xsl:with-param name="desc" select="concat('Détails des statistiques pour la page ', @name)" /> + <xsl:with-param name="icon" select="''" /> + <xsl:with-param name="iconCls" select="'x-tree-node-inline-icon'" /> + + <xsl:with-param name="cacheable" select="@cacheable" /> + <xsl:with-param name="apacheHits" select="sum(entry[@type='apache']/apacheHits)" /> + <xsl:with-param name="apacheCacheHits" select="sum(entry[@type='apache']/apacheCacheHits)" /> + <xsl:with-param name="frontHits" select="sum(entry[@type='apache' or @type='front']/*[local-name()='frontHits' or local-name()='hits'])" /> + <xsl:with-param name="frontCacheHits" select="sum(entry[@type='apache' or @type='front']/*[local-name()='frontCacheHits1' or local-name()='frontCacheHits2' or local-name()='cacheHits1' or local-name()='cacheHits2'])" /> + <xsl:with-param name="backHits" select="sum(entry[@type='back']/hits)" /> + </xsl:call-template> + </resource> + </xsl:template> + + <xsl:template name="node-attributes"> + <xsl:param name="label" /> + <xsl:param name="id" /> + <xsl:param name="desc" /> + <xsl:param name="leaf" select="'true'" /> + <xsl:param name="expanded" /> + <xsl:param name="icon" /> + <xsl:param name="iconCls" select="'x-tree-node-inline-icon'" /> + <xsl:param name="cls" /> + + <xsl:param name="cacheable" /> + <xsl:param name="hits" /> + <xsl:param name="hitsA" /> + <xsl:param name="hitsF" /> + <xsl:param name="hitsB" /> + <xsl:param name="cacheHits" /> + <xsl:param name="cacheHitsA" /> + <xsl:param name="cacheHitsF" /> + <xsl:param name="eff" /> + <xsl:param name="effA" /> + <xsl:param name="effF" /> + + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'label'" /><xsl:with-param name="value" select="$label" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'id'" /><xsl:with-param name="value" select="$id" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'qtip'" /><xsl:with-param name="value" select="$desc" /></xsl:call-template><!-- desc -> qtip --> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'leaf'" /><xsl:with-param name="value" select="$leaf" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'expanded'" /><xsl:with-param name="value" select="$expanded" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'icon'" /><xsl:with-param name="value" select="$icon" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'iconCls'" /><xsl:with-param name="value" select="$iconCls" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'cls'" /><xsl:with-param name="value" select="$cls" /></xsl:call-template> + + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'cacheable'" /><xsl:with-param name="value" select="$cacheable" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'hits'" /><xsl:with-param name="value" select="$hits" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'hitsA'" /><xsl:with-param name="value" select="$hitsA" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'hitsF'" /><xsl:with-param name="value" select="$hitsF" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'hitsB'" /><xsl:with-param name="value" select="$hitsB" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'cacheHits'" /><xsl:with-param name="value" select="$cacheHits" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'cacheHitsA'" /><xsl:with-param name="value" select="$cacheHitsA" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'cacheHitsF'" /><xsl:with-param name="value" select="$cacheHitsF" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'eff'" /><xsl:with-param name="value" select="$eff" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'effA'" /><xsl:with-param name="value" select="$effA" /></xsl:call-template> + <xsl:call-template name="if-param-attr"><xsl:with-param name="name" select="'effF'" /><xsl:with-param name="value" select="$effF" /></xsl:call-template> + </xsl:template> + + <xsl:template name="if-param-attr"> + <xsl:param name="name" /> + <xsl:param name="value" /> + + <xsl:if test="$value != ''"> + <xsl:attribute name="{$name}"><xsl:value-of select="$value" /></xsl:attribute> + </xsl:if> + </xsl:template> + + <xsl:template name="entry-attributes"> + <xsl:param name="label" /> + <xsl:param name="id" /> + <xsl:param name="desc" /> + <xsl:param name="leaf" select="'true'" /> + <xsl:param name="expanded" /> + <xsl:param name="icon"><xsl:call-template name="get-entry-icon" /></xsl:param> + <xsl:param name="iconCls"><xsl:call-template name="get-entry-iconCls" /></xsl:param> + <xsl:param name="cls" /> + + <xsl:param name="cacheable"><xsl:call-template name="get-weighted-cacheable-mean" /></xsl:param> + <xsl:param name="apacheHits"><xsl:call-template name="get-apacheHits-sum" /></xsl:param> + <xsl:param name="apacheCacheHits"><xsl:call-template name="get-apacheCachehits-sum" /></xsl:param> + <xsl:param name="frontHits"><xsl:call-template name="get-frontHits-sum" /></xsl:param> + <xsl:param name="frontCacheHits"><xsl:call-template name="get-frontCachehits-sum" /></xsl:param> + <xsl:param name="backHits"><xsl:call-template name="get-backHits-sum" /></xsl:param> + + <xsl:variable name="hits" select="$frontHits + $apacheCacheHits" /> + <xsl:variable name="hitsA" select="$apacheHits" /> + <xsl:variable name="hitsF" select="$frontHits - ($apacheHits - $apacheCacheHits)" /> + <xsl:variable name="hitsB"> + <xsl:choose> + <xsl:when test="string(number($backHits)) != 'NaN'"><xsl:value-of select="$backHits" /></xsl:when> + <xsl:otherwise><xsl:text>-</xsl:text></xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="cacheHits" select="$apacheCacheHits + $frontCacheHits" /> + <xsl:variable name="cacheHitsA" select="$apacheCacheHits" /> + <xsl:variable name="cacheHitsF" select="$frontCacheHits" /> + + <xsl:variable name="eff"><xsl:call-template name="get-percent"><xsl:with-param name="value" select="round(100*$cacheHits div $hits)" /></xsl:call-template></xsl:variable> + <xsl:variable name="effA"><xsl:call-template name="get-percent"><xsl:with-param name="value" select="round(100*$cacheHitsA div $hits)" /></xsl:call-template></xsl:variable> + <xsl:variable name="effF"><xsl:call-template name="get-percent"><xsl:with-param name="value" select="round(100*$cacheHitsF div $hits)" /></xsl:call-template></xsl:variable> + + <xsl:call-template name="node-attributes"> + <xsl:with-param name="label" select="$label" /> + <xsl:with-param name="id" select="$id" /> + <xsl:with-param name="desc" select="$desc" /> + <xsl:with-param name="leaf" select="$leaf" /> + <xsl:with-param name="expanded" select="$expanded" /> + <xsl:with-param name="icon" select="$icon" /> + <xsl:with-param name="iconCls" select="$iconCls" /> + <xsl:with-param name="cls" select="$cls" /> + + <xsl:with-param name="cacheable" select="$cacheable" /> + <xsl:with-param name="hits" select="$hits" /> + <xsl:with-param name="hitsA" select="$hitsA" /> + <xsl:with-param name="hitsF" select="$hitsF" /> + <xsl:with-param name="hitsB" select="$hitsB" /> + <xsl:with-param name="cacheHits" select="$cacheHits" /> + <xsl:with-param name="cacheHitsA" select="$cacheHitsA" /> + <xsl:with-param name="cacheHitsF" select="$cacheHitsF" /> + <xsl:with-param name="eff" select="$eff" /> + <xsl:with-param name="effA" select="$effA" /> + <xsl:with-param name="effF" select="$effF" /> + </xsl:call-template> + </xsl:template> + + <xsl:template name="get-percent"> + <xsl:param name="value" /> + <xsl:variable name="svalue" select="string(number($value))" /> + <xsl:if test="$svalue != 'NaN' and $svalue != 'Infinity'"><xsl:value-of select="concat($value, ' %')" /></xsl:if> + </xsl:template> + + <xsl:template name="get-apacheHits-sum"> + <xsl:value-of select="sum(.//resource/entry[@type='apache']/apacheHits)" /> + </xsl:template> + + <xsl:template name="get-apacheCachehits-sum"> + <xsl:value-of select="sum(.//resource/entry[@type='apache']/apacheCacheHits)" /> + </xsl:template> + + <xsl:template name="get-frontHits-sum"> + <xsl:value-of select="sum(.//resource/entry[@type='apache' or @type='front']/*[local-name()='frontHits' or local-name()='hits'])" /> + </xsl:template> + + <xsl:template name="get-frontCachehits-sum"> + <xsl:value-of select="sum(.//resource/entry[@type='apache' or @type='front']/*[local-name()='frontCacheHits1' or local-name()='frontCacheHits2' or local-name()='cacheHits1' or local-name()='cacheHits2'])" /> + </xsl:template> + + <!-- Currently, only applicable to pages --> + <xsl:template name="get-backHits-sum"> + <xsl:choose> + <xsl:when test="@type = 'page'"> + <xsl:value-of select="sum(.//resource[@type='page']/entry[@type='back']/hits)" /> + </xsl:when> + <xsl:otherwise><xsl:text>N/A</xsl:text></xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- moyenne du nombre de pages cacheables --> + <xsl:template name="get-cacheable-mean"> + <xsl:variable name="cacheables" select="count(.//resource[@type != 'folder' and @cacheable='true'])" /> + <xsl:variable name="total" select="count(.//resource[@type != 'folder'])" /> + <xsl:call-template name="get-percent"><xsl:with-param name="value" select="round($cacheables*100 div $total)" /></xsl:call-template> + </xsl:template> + + <!-- moyenne du nombre de pages cacheables ponderée par le nombre de hits --> + <xsl:template name="get-weighted-cacheable-mean"> + <!-- sum apacheCacheHits + frontHits to get the total hits for a resource. --> + <xsl:variable name="cacheables" select="sum(.//resource[@type != 'folder' and @cacheable='true']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits'])" /> + <xsl:variable name="total" select="sum(.//resource[@type != 'folder']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits'])" /> + <xsl:call-template name="get-percent"><xsl:with-param name="value" select="round($cacheables*100 div $total)" /></xsl:call-template> + </xsl:template> + + <!-- moyenne du nombre de sous ressources cacheables (incluant la ressource courante) --> + <xsl:template name="get-cacheable-mean-page"> + <xsl:choose> + <!-- cas où la page courante n'as pas de sous-ressources --> + <xsl:when test="not(resource)"><xsl:value-of select="@cacheable" /></xsl:when> + <xsl:otherwise> + <xsl:variable name="cacheables" select="count(.//resource[@type != 'folder' and @cacheable='true']) + count(self::resource[@type != 'folder' and @cacheable='true'])" /> + <xsl:variable name="total" select="count(.//resource[@type != 'folder']) + count(self::resource[@type != 'folder'])" /> + <xsl:call-template name="get-percent"><xsl:with-param name="value" select="round($cacheables*100 div $total)" /></xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- moyenne du nombre de sous ressources cacheables (incluant la ressource courante) ponderée par le nombre de hits --> + <xsl:template name="get-weighted-cacheable-mean-page"> + <xsl:choose> + <!-- cas où la page courante n'as pas de sous-ressources --> + <xsl:when test="not(resource)"><xsl:value-of select="@cacheable" /></xsl:when> + <xsl:otherwise> + <!-- sum apacheCacheHits + frontHits to get the total hits for a resource. --> + <xsl:variable name="cacheables" select="sum(.//resource[@type != 'folder' and @cacheable='true']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits']) + sum(self::resource[@type != 'folder' and @cacheable='true']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits'])" /> + <xsl:variable name="total" select="sum(.//resource[@type != 'folder']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits']) + sum(self::resource[@type != 'folder']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits'])" /> + <xsl:call-template name="get-percent"><xsl:with-param name="value" select="round($cacheables*100 div $total)" /></xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- moyenne du nombre de pages cacheables --> + <xsl:template name="get-cacheable-mean-total-page"> + <xsl:variable name="cacheables" select="count(.//resource[@type = 'page' and @cacheable='true'])" /> + <xsl:variable name="total" select="count(.//resource[@type = 'page'])" /> + <xsl:call-template name="get-percent"><xsl:with-param name="value" select="round($cacheables*100 div $total)" /></xsl:call-template> + </xsl:template> + + <!-- moyenne du nombre de pages cacheables ponderée par le nombre de hits --> + <xsl:template name="get-weighted-cacheable-mean-total-page"> + <!-- sum apacheCacheHits + frontHits to get the total hits for a resource. --> + <xsl:variable name="cacheables" select="sum(.//resource[@type = 'page' and @cacheable='true']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits'])" /> + <xsl:variable name="total" select="sum(.//resource[@type = 'page']/entry[@type='apache' or @type='front']/*[local-name()='apacheCacheHits' or local-name()='frontHits' or local-name()='hits'])" /> + <xsl:call-template name="get-percent"><xsl:with-param name="value" select="round($cacheables*100 div $total)" /></xsl:call-template> + </xsl:template> + + <xsl:template name="get-apacheHits-sum-total-page"> + <xsl:value-of select="sum(.//resource[@type='page']/entry[@type='apache']/apacheHits)" /> + </xsl:template> + + <xsl:template name="get-apacheCachehits-sum-total-page"> + <xsl:value-of select="sum(.//resource[@type='page']/entry[@type='apache']/apacheCacheHits)" /> + </xsl:template> + + <xsl:template name="get-frontHits-sum-total-page"> + <xsl:value-of select="sum(.//resource[@type='page']/entry[@type='apache' or @type='front']/*[local-name()='frontHits' or local-name()='hits'])" /> + </xsl:template> + + <xsl:template name="get-frontCachehits-sum-total-page"> + <xsl:value-of select="sum(.//resource[@type='page']/entry[@type='apache' or @type='front']/*[local-name()='frontCacheHits1' or local-name()='frontCacheHits2' or local-name()='cacheHits1' or local-name()='cacheHits2'])" /> + </xsl:template> + + <xsl:template name="get-backHits-sum-total-page"> + <xsl:value-of select="sum(.//resource[@type='page']/entry[@type='back']/hits)" /> + </xsl:template> + + <xsl:template name="get-entry-icon"> + <xsl:choose> + <xsl:when test="@type = 'folder'"> + <xsl:value-of select="concat($contextPath, '/plugins/', $pluginName, '/resources/img/administrator/stats/resources_16.png')" /> + </xsl:when> + <xsl:when test="@type = 'page'"> + <xsl:value-of select="concat($contextPath, '/plugins/', $pluginName, '/resources/img/administrator/stats/content_16.png')" /> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template name="get-entry-iconCls"> + <xsl:if test="@type = 'asset'"> + <xsl:value-of select="'x-tree-node-inline-icon'" /> + </xsl:if> + </xsl:template> +</xsl:stylesheet> Index: main/plugin-web/pages/administrator/sites/cache-statistics-servers.xsl =================================================================== --- main/plugin-web/pages/administrator/sites/cache-statistics-servers.xsl (revision 0) +++ main/plugin-web/pages/administrator/sites/cache-statistics-servers.xsl (revision 0) @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2012 Anyware Services + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<xsl:stylesheet version="1.0" + xmlns:i18n="http://apache.org/cocoon/i18n/2.1" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:ametys="org.ametys.web.transformation.xslt.AmetysXSLTHelper" + exclude-result-prefixes="ametys"> + + <xsl:param name="contextPath"/> + <xsl:param name="pluginName"/> + + <xsl:template match="/"> + <html> + <head> + <title> + <i18n:translate> + <i18n:text i18n:key="PLUGINS_WEB_ADMINISTRATOR_CACHE_SERVERS_STATISTICS_TITLE"/> + <i18n:param name="name"><xsl:value-of select="site/@name"/></i18n:param> + </i18n:translate> + </title> + <link rel="stylesheet" href="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/treegrid.css')}" type="text/css"/> + <style> + .custom-hd-row { background-image: url("<xsl:value-of select="ametys:pluginResourceURL('extjs', 'images/default/grid/grid3-hrow.gif')" />"); } + /* Fixing chrome custom header issue */ + td.x-treegrid-hd-hidden { border: 0; } + td.x-treegrid-hd-hidden div.x-treegrid-hd-inner { display: none; } + </style> + </head> + + <script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGrid.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridColumnResizer.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridColumns.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridLoader.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridNodeUI.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL('extjs', 'ux/js/treegrid/TreeGridSorter.js')}"></script> + + <script type="text/javascript" src="{ametys:pluginResourceURL($pluginName, 'js/org/ametys/web/administration/CacheStatistics.i18n.js')}"></script> + <script type="text/javascript" src="{ametys:pluginResourceURL($pluginName, 'js/org/ametys/web/administration/CacheStatisticsServers.i18n.js')}"></script> + + <script type="text/javascript"> + org.ametys.web.administration.CacheStatisticsServers.init("<xsl:value-of select="$pluginName"/>", "<xsl:value-of select="site/@name"/>", "<xsl:value-of select="site/@path"/>"); + + org.ametys.runtime.administrator.Panel.createPanel = function() + { + return new Ext.Panel({ + region: 'center', + + baseCls: 'transparent-panel', + border: false, + layout: 'border', + autoScroll: true, + + items : [org.ametys.web.administration.CacheStatisticsServers._centerPanel, + org.ametys.web.administration.CacheStatisticsServers._rightPanel + ] + }); + } + </script> + </script> + + <body> + </body> + </html> + </xsl:template> + +</xsl:stylesheet> Index: main/plugin-web/sitemap-back.xmap =================================================================== --- main/plugin-web/sitemap-back.xmap (revision 20673) +++ main/plugin-web/sitemap-back.xmap (working copy) @@ -28,6 +28,8 @@ <map:generator name="convert-pagepath-to-id" src="org.ametys.web.repository.page.generators.ConvertPagePathToIdGenerator" label="xml" pool-grow="2" pool-max="16" pool-min="0"/> <map:generator name="child-pages" src="org.ametys.web.repository.page.generators.ChildrenPagesIdGenerator" label="xml" pool-grow="2" pool-max="16" pool-min="0"/> <map:generator name="global-statistics" src="org.ametys.web.site.GlobalStatisticsGenerator" logger="org.ametys.web.site.GlobalStatisticsGenerator"/> + <map:generator name="cache-stats-back" src="org.ametys.web.cache.monitoring.ui.PageElementCacheStatsGenerator" logger="org.ametys.web.cachemonitoring.generators.PageElementCacheStatsGenerator" label="xml"/> + <map:generator name="cache-stats-servers" src="org.ametys.web.cache.monitoring.ui.ServersCacheStatsGenerator" logger="org.ametys.web.cachemonitoring.generators.ServersCacheStatsGenerator" label="xml"/> <map:generator name="site-statistics" src="org.ametys.web.site.SiteStatisticsGenerator" logger="org.ametys.web.site.SiteStatisticsGenerator" label="xml" pool-grow="2" pool-max="16" pool-min="0"/> <map:generator name="site-parameters" src="org.ametys.web.site.SiteParametersGenerator" logger="org.ametys.web.site.SiteParametersGenerator" label="xml"/> <map:generator name="page-info" src="org.ametys.web.repository.page.generators.PageInformationGenerator" label="xml" pool-grow="2" pool-max="16" pool-min="0"/> @@ -300,6 +302,67 @@ <map:serialize type="xml"/> </map:match> + <map:match pattern="administrator/sites/*/cache-statistics-back.html"> + <map:generate type="site-configuration" label="xml"> + <map:parameter name="name" value="{1}"/> + </map:generate> + <map:transform src="pages/administrator/sites/cache-statistics-back.xsl"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + <map:parameter name="pluginName" value="{request-attr:pluginName}"/> + </map:transform> + <map:transform type="i18n"> + <map:parameter name="locale" value="{locale:locale}"/> + <map:parameter name="plugin" value="{request-attr:pluginName}"/> + </map:transform> + <map:serialize type="xml"/> + </map:match> + + <map:match pattern="administrator/sites/*/cache-statistics-back-tree.xml"> + <map:generate type="cache-stats-back" label="xml"> + <map:parameter name="siteName" value="{1}"/> + <map:parameter name="contexts" value="{request-param:contexts}"/> + </map:generate> + <map:transform src="pages/administrator/sites/cache-statistics-back-tree.xsl"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + <map:parameter name="pluginName" value="{request-attr:pluginName}"/> + </map:transform> + <map:transform type="i18n"> + <map:parameter name="locale" value="{locale:locale}"/> + <map:parameter name="plugin" value="{request-attr:pluginName}"/> + </map:transform> + <map:serialize type="xml"/> + </map:match> + + <map:match pattern="administrator/sites/*/cache-statistics-servers.html"> + <map:generate type="site-configuration" label="xml"> + <map:parameter name="name" value="{1}"/> + </map:generate> + <map:transform src="pages/administrator/sites/cache-statistics-servers.xsl"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + <map:parameter name="pluginName" value="{request-attr:pluginName}"/> + </map:transform> + <map:transform type="i18n"> + <map:parameter name="locale" value="{locale:locale}"/> + <map:parameter name="plugin" value="{request-attr:pluginName}"/> + </map:transform> + <map:serialize type="xml"/> + </map:match> + + <map:match pattern="administrator/sites/*/cache-statistics-servers-tree.xml"> + <map:generate type="cache-stats-servers"> + <map:parameter name="siteName" value="{1}"/> + </map:generate> + <map:transform src="pages/administrator/sites/cache-statistics-servers-tree.xsl"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + <map:parameter name="pluginName" value="{request-attr:pluginName}"/> + </map:transform> + <map:transform type="i18n"> + <map:parameter name="locale" value="{locale:locale}"/> + <map:parameter name="plugin" value="{request-attr:pluginName}"/> + </map:transform> + <map:serialize type="xml"/> + </map:match> + <map:match pattern="administrator/skins/view.html"> <map:generate type="admin-skin-actions" label="content"/> <map:transform type="i18n"> Index: main/workspace-web/src/org/ametys/web/repository/IsPageCacheableAction.java =================================================================== --- main/workspace-web/src/org/ametys/web/repository/IsPageCacheableAction.java (revision 20673) +++ main/workspace-web/src/org/ametys/web/repository/IsPageCacheableAction.java (working copy) @@ -32,14 +32,15 @@ import org.apache.cocoon.environment.SourceResolver; import org.ametys.plugins.repository.AmetysObjectIterable; +import org.ametys.web.cache.monitoring.process.access.impl.PageResourceAccess; import org.ametys.web.inputdata.InputData; import org.ametys.web.inputdata.InputDataExtensionPoint; import org.ametys.web.pageaccess.PageAccessInfo; import org.ametys.web.pageaccess.PageAccessManager; import org.ametys.web.repository.page.Page; +import org.ametys.web.repository.page.Page.PageType; import org.ametys.web.repository.page.Zone; import org.ametys.web.repository.page.ZoneItem; -import org.ametys.web.repository.page.Page.PageType; import org.ametys.web.repository.page.ZoneItem.ZoneType; import org.ametys.web.service.Service; import org.ametys.web.service.ServiceExtensionPoint; @@ -66,15 +67,21 @@ public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception { Request request = ObjectModelHelper.getRequest(objectModel); - Page page = (Page) request.getAttribute(Page.class.getName()); - if (_isCacheable(page)) + boolean isCacheable = _isCacheable(page); + if (isCacheable) { Response response = ObjectModelHelper.getResponse(objectModel); response.addHeader("X-Ametys-Cacheable", "true"); } - + + // Page access monitoring. + String uuid = request.getHeader("X-Ametys-FO-UUID"); + PageResourceAccess pageAccess = new PageResourceAccess(uuid, page.getId(), request.getRequestURI()); + pageAccess.setCacheable(isCacheable); + request.setAttribute("PAGE_ACCESS", pageAccess); + return EMPTY_MAP; } Index: main/workspace-web/src/org/ametys/web/repository/PageGenerator.java =================================================================== --- main/workspace-web/src/org/ametys/web/repository/PageGenerator.java (revision 20673) +++ main/workspace-web/src/org/ametys/web/repository/PageGenerator.java (working copy) @@ -51,6 +51,10 @@ import org.ametys.runtime.authentication.AccessDeniedException; import org.ametys.runtime.authentication.AuthorizationRequiredException; import org.ametys.runtime.util.IgnoreRootHandler; +import org.ametys.web.cache.monitoring.process.access.ResourceAccessComponent; +import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess; +import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess.PageElementType; +import org.ametys.web.cache.monitoring.process.access.impl.PageResourceAccess; import org.ametys.web.cache.pageelement.PageElementCache; import org.ametys.web.renderingcontext.RenderingContext; import org.ametys.web.renderingcontext.RenderingContextHandler; @@ -105,11 +109,17 @@ /** The service assignment handler. */ private ServicesAssignmentHandler _serviceAssignmentHandler; + /** The resource access monitoring component */ + private ResourceAccessComponent _resourceAccessComponent; + + /** The monitored resource access */ + private PageResourceAccess _pageAccess; + private int _zoneItemsInCache; private int _zoneItemsSaxed; private int _zonesSaxed; - + @Override public void service(ServiceManager serviceManager) throws ServiceException { @@ -124,6 +134,7 @@ _renderingContextHandler = (RenderingContextHandler) serviceManager.lookup(RenderingContextHandler.ROLE); _cTypeAssignmentHandler = (ContentTypesAssignmentHandler) serviceManager.lookup(ContentTypesAssignmentHandler.ROLE); _serviceAssignmentHandler = (ServicesAssignmentHandler) serviceManager.lookup(ServicesAssignmentHandler.ROLE); + _resourceAccessComponent = (ResourceAccessComponent) serviceManager.lookup(ResourceAccessComponent.ROLE); } @Override @@ -131,12 +142,12 @@ { long t0 = System.currentTimeMillis(); + Request request = ObjectModelHelper.getRequest(objectModel); + _zoneItemsInCache = 0; _zoneItemsSaxed = 0; _zonesSaxed = 0; - - Request request = ObjectModelHelper.getRequest(objectModel); - + Page page = (Page) request.getAttribute(Page.class.getName()); String title = page.getTitle(); @@ -149,13 +160,19 @@ throw new IllegalStateException("Cannot invoke the PageGenerator on a Page without a PageContent"); } + // Monitor the access to this page. + _pageAccess = (PageResourceAccess) request.getAttribute("PAGE_ACCESS"); + _pageAccess.setRenderingContext(renderingContext); + _pageAccess.setWorkspaceJCR(workspace); + _resourceAccessComponent.addAccessRecord(_pageAccess); + contentHandler.startDocument(); AttributesImpl attrs = new AttributesImpl(); attrs.addCDATAAttribute("title", title); attrs.addCDATAAttribute("long-title", page.getLongTitle()); attrs.addCDATAAttribute("id", page.getId()); XMLUtils.startElement(contentHandler, "page", attrs); - + try { XMLUtils.startElement(contentHandler, "metadata"); @@ -187,16 +204,17 @@ } catch (AmetysRepositoryException e) { + _pageAccess = null; throw new ProcessingException("Unable to SAX page metadata", e); } - - AttributesImpl pcattrs = new AttributesImpl(); + + AttributesImpl pcattrs = new AttributesImpl(); pcattrs.addCDATAAttribute("modifiable", Boolean.toString(page instanceof ModifiablePage)); pcattrs.addCDATAAttribute("moveable", Boolean.toString(page instanceof MoveablePage)); XMLUtils.startElement(contentHandler, "pageContents", pcattrs); long t1 = System.currentTimeMillis(); - + try { // Iterate on existing zones @@ -204,7 +222,7 @@ { String zoneName = zone.getName(); AmetysObjectIterable<? extends ZoneItem> zoneItems = zone.getZoneItems(); - + _saxZone(page, zoneName, zoneItems, workspace, siteName, renderingContext); } @@ -223,6 +241,7 @@ } catch (AmetysRepositoryException ex) { + _pageAccess = null; throw new ProcessingException("Unable to get Content", ex); } @@ -239,8 +258,10 @@ XMLUtils.endElement(contentHandler, "pageContents"); XMLUtils.endElement(contentHandler, "page"); contentHandler.endDocument(); + + _pageAccess = null; } - + /** * Sax a zone * @param page The page @@ -259,7 +280,7 @@ AttributesImpl zoneAttrs = new AttributesImpl(); zoneAttrs.addCDATAAttribute("name", zoneName); - + if (localZoneItems == null || !localZoneItems.hasNext()) { // zone is empty => try to inherit @@ -271,7 +292,7 @@ localZoneItems = parentPageZone.getZoneItems(); } } - + Request request = ObjectModelHelper.getRequest(objectModel); request.setAttribute(Zone.class.getName(), zoneName); @@ -281,10 +302,10 @@ _saxAvailableServices(page, zoneName); _saxZoneItems(page, localZoneItems, workspace, site, renderingContext); - + XMLUtils.endElement(contentHandler, "zone"); request.setAttribute(Zone.class.getName(), null); - + } /** @@ -331,7 +352,7 @@ /** * Sax zone items - * @param page + * @param page * @param zoneItems The zone items to sax * @throws SAXException * @throws MalformedURLException @@ -355,18 +376,23 @@ String id = zoneItem.getId(); ZoneType type = zoneItem.getType(); - + request.setAttribute(ZoneItem.class.getName(), zoneItem); AttributesImpl zoneItemAttrs = new AttributesImpl(); zoneItemAttrs.addCDATAAttribute("id", id); + PageElementResourceAccess zoneAccess = _pageAccess.createPageElementAccess(id, PageElementType.fromZoneItemType(type)); + // try to get content from cache SaxBuffer cachedContent = _zoneItemCache.getPageElement(workspace, site, _getType(zoneItem), id, page.getId(), renderingContext); - + if (cachedContent != null) { _zoneItemsInCache++; + zoneAccess.setCacheable(true); + zoneAccess.setCacheHit(true); + cachedContent.toSAX(contentHandler); } else @@ -381,14 +407,17 @@ { String serviceId = zoneItem.getServiceId(); Service service = _serviceExtPt.getExtension(serviceId); - + if (service != null) - { + { isCacheable = service.isCacheable(zoneItem); } // if service is null, an exception will be thrown later } + zoneAccess.setCacheable(isCacheable); + zoneAccess.setCacheHit(false); + SaxBuffer buffer = null; ContentHandler handler; // the actual ContentHandler, either the real one, or a buffer if (isCacheable) @@ -402,10 +431,10 @@ } XMLUtils.startElement(handler, "zoneItem", zoneItemAttrs); - + XMLUtils.startElement(handler, "information"); XMLUtils.createElement(handler, "type", type.toString()); - + Source src = null; Exception ex = null; if (type == ZoneType.CONTENT) @@ -414,7 +443,7 @@ { Content content = zoneItem.getContent(); String metadataSetName = StringUtils.defaultString(zoneItem.getMetadataSetName(), "main"); - + XMLUtils.createElement(handler, "contentId", content.getId()); XMLUtils.createElement(handler, "contentName", content.getName()); XMLUtils.createElement(handler, "metadataSetName", metadataSetName); @@ -462,7 +491,7 @@ { String serviceId = zoneItem.getServiceId(); Service service = _serviceExtPt.getExtension(serviceId); - + if (service == null) { ex = new ProcessingException("Unable to get service for name '" + serviceId + "'"); @@ -472,20 +501,20 @@ AttributesImpl serviceAttrs = new AttributesImpl(); serviceAttrs.addCDATAAttribute("id", service.getId()); XMLUtils.startElement(handler, "type-information", serviceAttrs); - + service.getLabel().toSAX(handler, "label"); service.getDescription().toSAX(handler, "description"); XMLUtils.createElement(handler, "smallIcon", service.getSmallIcon()); XMLUtils.createElement(handler, "mediumIcon", service.getMediumIcon()); - + XMLUtils.endElement(handler, "type-information"); - + src = resolver.resolveURI(service.getURL(), null, _getParameters(service, zoneItem)); } } - + XMLUtils.endElement(handler, "information"); - + if (src == null) { getLogger().error("Unable to display zone item", ex); @@ -515,7 +544,7 @@ resolver.release(src); } } - + XMLUtils.endElement(handler, "zoneItem"); // finally store the buffered data in the cache and SAX it to the pipeline @@ -526,6 +555,9 @@ } } + // Monitor the access to this zone item. + _resourceAccessComponent.addAccessRecord(zoneAccess); + // Empty content request attributes request.setAttribute(Content.class.getName(), null); // Empty zone item request attribute @@ -619,7 +651,7 @@ getLogger().error("The page '" + childPage.getId() + "' cannot inherit a zone '" + zoneName + "' of template '" + templateName + "' in skin '" + skinId + "' as asked for page '" + page.getId() + "' in site '" + site.getName() + "'", e); return null; } - + // This zone is not defined for the template if (zoneDef == null) { @@ -632,7 +664,7 @@ { return null; } - + // Get the parent page (that is a container page) Page parentPage = page; do @@ -656,8 +688,8 @@ // No inheritance for this template return null; } - - // Finally we will inherit from the parentPage and the zone inheritanceSrc + + // Finally we will inherit from the parentPage and the zone inheritanceSrc return _inherit(childPage, parentPage, inheritanceSrc); } @@ -689,7 +721,7 @@ { CompositeMetadata serviceParams = zoneItem.getServiceParameters(); Map<String, Object> params = new HashMap<String, Object>(); - + for (ServiceParameterOrRepeater serviceParameter : service.getParameters().values()) { if (serviceParameter instanceof ServiceParameter) @@ -716,7 +748,7 @@ return params; } - + /** * Get the values of a repeater in a service instance. * @param repeater the repeater definition. Index: main/workspace-web/src/org/ametys/web/inputdata/InputDataGenerator.java =================================================================== --- main/workspace-web/src/org/ametys/web/inputdata/InputDataGenerator.java (revision 20673) +++ main/workspace-web/src/org/ametys/web/inputdata/InputDataGenerator.java (working copy) @@ -27,6 +27,10 @@ import org.xml.sax.SAXException; import org.ametys.plugins.repository.provider.WorkspaceSelector; +import org.ametys.web.cache.monitoring.process.access.ResourceAccessComponent; +import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess; +import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess.PageElementType; +import org.ametys.web.cache.monitoring.process.access.impl.PageResourceAccess; import org.ametys.web.cache.pageelement.PageElementCache; import org.ametys.web.renderingcontext.RenderingContext; import org.ametys.web.renderingcontext.RenderingContextHandler; @@ -45,6 +49,9 @@ private RenderingContextHandler _renderingconContextHandler; private SiteManager _sitesManager; + /** The resource access monitoring component */ + private ResourceAccessComponent _resourceAccessComponent; + @Override public void service(ServiceManager sManager) throws ServiceException { @@ -54,8 +61,9 @@ _renderingconContextHandler = (RenderingContextHandler) sManager.lookup(RenderingContextHandler.ROLE); _workspaceSelector = (WorkspaceSelector) sManager.lookup(WorkspaceSelector.ROLE); _sitesManager = (SiteManager) sManager.lookup(SiteManager.ROLE); + _resourceAccessComponent = (ResourceAccessComponent) sManager.lookup(ResourceAccessComponent.ROLE); } - + @Override public void generate() throws SAXException, ProcessingException { @@ -66,7 +74,7 @@ String siteName; Site site; String pageId = null; - + Page page = (Page) request.getAttribute(Page.class.getName()); if (page != null) { @@ -83,6 +91,9 @@ String workspace = _workspaceSelector.getWorkspace(); RenderingContext renderingContext = _renderingconContextHandler.getRenderingContext(); + // Access monitoring + PageResourceAccess pageAccess = (PageResourceAccess) request.getAttribute("PAGE_ACCESS"); + contentHandler.startDocument(); XMLUtils.startElement(contentHandler, "inputData"); @@ -90,17 +101,25 @@ { InputData inputData = _inputDataExtensionPoint.getExtension(id); + PageElementResourceAccess inputDataAccess = pageAccess.createPageElementAccess(id, PageElementType.INPUTDATA); + // lookup cached content SaxBuffer cachedContent = _inputDataCache.getPageElement(workspace, siteName, id, pageId, renderingContext); if (cachedContent != null) { + inputDataAccess.setCacheable(true); + inputDataAccess.setCacheHit(true); + cachedContent.toSAX(contentHandler); } else { boolean isCacheable = inputData.isCacheable(site, page); + inputDataAccess.setCacheable(isCacheable); + inputDataAccess.setCacheHit(false); + SaxBuffer buffer = null; ContentHandler handler; // the actual ContentHandler, either the real one, or a buffer if (isCacheable) @@ -122,6 +141,9 @@ buffer.toSAX(contentHandler); } } + + // Monitor the access to this zone item. + _resourceAccessComponent.addAccessRecord(inputDataAccess); } XMLUtils.endElement(contentHandler, "inputData");