001/*
002 *  Copyright 2013 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016
017package org.ametys.web.cache.monitoring.process.statistics;
018
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.ibatis.session.SqlSession;
024import org.joda.time.Duration;
025import org.joda.time.format.PeriodFormat;
026
027import org.ametys.core.datasource.AbstractMyBatisDAO;
028import org.ametys.web.cache.monitoring.Constants;
029import org.ametys.web.cache.monitoring.process.statistics.impl.FrontFromHTTPServerResourceStatisticsFactory;
030import org.ametys.web.cache.monitoring.process.statistics.impl.FrontOnlyResourceStatisticsFactory;
031import org.ametys.web.cache.monitoring.process.statistics.impl.HTTPServerOnlyResourceStatisticsFactory;
032import org.ametys.web.cache.monitoring.process.statistics.impl.PageElementResourceStatisticsFactory;
033import org.ametys.web.cache.monitoring.process.statistics.impl.PageResourceStatisticsFactory;
034
035/**
036 * The cache monitoring updater. It updates the statistics in the monitoring database, given the new request entries.
037 */
038public class ResourceStatisticsComponent extends AbstractMyBatisDAO
039{
040    /** Avalon ROLE. */
041    public static final String ROLE = ResourceStatisticsComponent.class.getName();
042    
043    /**
044     * Update the cache statistics tables.
045     */
046    public void updateStatistics()
047    {
048        if (getLogger().isDebugEnabled())
049        {
050            getLogger().debug("Updating cache stats tables...");
051        }
052        
053        long start = System.currentTimeMillis();
054        int totalUpdated = 0;
055        
056        totalUpdated += _update("page", PageResourceStatisticsFactory.getInstance());
057        totalUpdated += _update("pageElements", PageElementResourceStatisticsFactory.getInstance());
058        totalUpdated += _update("frontOnly", FrontOnlyResourceStatisticsFactory.getInstance());
059        totalUpdated += _update("httpServerOnly", HTTPServerOnlyResourceStatisticsFactory.getInstance());
060        totalUpdated += _update("frontFromHTTPServer", FrontFromHTTPServerResourceStatisticsFactory.getInstance());
061        
062        if (getLogger().isDebugEnabled())
063        {
064            String durationStr = PeriodFormat.getDefault().print(new Duration(System.currentTimeMillis() - start).toPeriod());
065            getLogger().debug(String.format("\tTotal count of new request log that have been processed : %s", totalUpdated));
066            getLogger().debug(String.format("Update of the cache stats tables took %s", durationStr));
067        }
068    }
069    
070    private int _update(String logName, ResourceStatisticsFactory factory)
071    {
072        int processed = 0;
073        
074        try (SqlSession sqlSession = getSession())
075        {
076            // Retrieves resources to process + update cache stats
077            List<ResourceStatistics> resourceStatisticsList = factory.getResourceAccessToProcess(sqlSession);
078            int hits = _updateCacheStats(sqlSession, resourceStatisticsList);
079            
080            // Mark handled resource access as processed
081            if (resourceStatisticsList.size() > 0)
082            {
083                processed = factory.markResourcesAsProcessed(sqlSession);
084            }
085            
086            // Commit the transaction.
087            sqlSession.commit();
088            
089            if (getLogger().isDebugEnabled())
090            {
091                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));
092            }
093        }
094        catch (Exception e)
095        {
096            getLogger().error("Exception during update cache stats", e);
097        }
098        
099        return processed;
100    }
101    
102    private int _updateCacheStats(SqlSession sqlSession, List<ResourceStatistics> resourceStatisticsList)
103    {
104        int hits = 0;
105        
106        for (ResourceStatistics resourceStatistics : resourceStatisticsList)
107        {
108            if (resourceStatistics.statExists(sqlSession))
109            {
110                resourceStatistics.updateStat(sqlSession);
111            }
112            else
113            {
114                resourceStatistics.createStat(sqlSession);
115            }
116            
117            hits += resourceStatistics.getHits();
118        }
119        
120        return hits;
121    }
122    
123    /**
124     * Purge the processed raw request entries.
125     */
126    public void purgeRawData()
127    {
128        long start = 0;
129        if (getLogger().isDebugEnabled())
130        {
131            getLogger().debug("Purging raw monitoring data...");
132            start = System.currentTimeMillis();
133        }
134        
135        int totalPurged = 0;
136        try (SqlSession sqlSession = getSession())
137        {
138            totalPurged += PageResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
139            totalPurged += PageElementResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
140            totalPurged += FrontOnlyResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
141            totalPurged += HTTPServerOnlyResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
142            totalPurged += FrontFromHTTPServerResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
143            
144            // Commit the transaction.
145            sqlSession.commit();
146        }
147        catch (Exception e)
148        {
149            getLogger().error("An error occured while purging raw monitoring data", e);
150        }
151
152        if (getLogger().isDebugEnabled())
153        {
154            String durationStr = PeriodFormat.getDefault().print(new Duration(System.currentTimeMillis() - start).toPeriod());
155            getLogger().debug(String.format("%s row purged from the database in %s", totalPurged, durationStr));
156        }
157    }
158    
159    /**
160     * Get the raw data for the page elements cache statistics.
161     * @return A list a map, each map representing a page stat entry
162     */
163    public List<Map<String, Object>> getPageElementCacheStats()
164    {
165        try (SqlSession sqlSession = getSession())
166        {
167            String stmtId = "CacheMonitoringStatistics.getPageElementCacheStats";
168            
169            Map<String, Object> params = new HashMap<>();
170            params.put("tableNamePage", Constants.SQL_TABLE_NAME_PAGE_STATISTICS);
171            params.put("tableNamePageElements", Constants.SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS);
172            
173            return sqlSession.selectList(stmtId, params);
174        }
175    }
176    
177    /**
178     * Get the raw data for the server cache statistics.
179     * @param siteName The name of the site for which data will be extracted
180     * @return A list a map, each map representing a raw stat entry
181     */
182    public List<Map<String, Object>> getServerCacheStats(String siteName)
183    {
184        try (SqlSession sqlSession = getSession())
185        {
186            String stmtId = "CacheMonitoringStatistics.getServerCacheStats";
187            
188            Map<String, Object> params = new HashMap<>();
189            params.put("tableNameHttpFront", Constants.SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS);
190            params.put("tableNamePage", Constants.SQL_TABLE_NAME_PAGE_STATISTICS);
191            
192            params.put("siteName", siteName);
193            
194            return sqlSession.selectList(stmtId, params);
195        }
196    }
197}