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;
024
025import org.ametys.core.datasource.AbstractMyBatisDAO;
026import org.ametys.core.util.DateUtils;
027import org.ametys.web.cache.monitoring.Constants;
028import org.ametys.web.cache.monitoring.process.statistics.impl.FrontFromHTTPServerResourceStatisticsFactory;
029import org.ametys.web.cache.monitoring.process.statistics.impl.FrontOnlyResourceStatisticsFactory;
030import org.ametys.web.cache.monitoring.process.statistics.impl.HTTPServerOnlyResourceStatisticsFactory;
031import org.ametys.web.cache.monitoring.process.statistics.impl.PageElementResourceStatisticsFactory;
032import org.ametys.web.cache.monitoring.process.statistics.impl.PageResourceStatisticsFactory;
033
034/**
035 * The cache monitoring updater. It updates the statistics in the monitoring database, given the new request entries.
036 */
037public class ResourceStatisticsComponent extends AbstractMyBatisDAO
038{
039    /** Avalon ROLE. */
040    public static final String ROLE = ResourceStatisticsComponent.class.getName();
041    
042    /**
043     * Update the cache statistics tables.
044     */
045    public void updateStatistics()
046    {
047        if (getLogger().isDebugEnabled())
048        {
049            getLogger().debug("Updating cache stats tables...");
050        }
051        
052        long start = System.currentTimeMillis();
053        int totalUpdated = 0;
054        
055        totalUpdated += _update("page", PageResourceStatisticsFactory.getInstance());
056        totalUpdated += _update("pageElements", PageElementResourceStatisticsFactory.getInstance());
057        totalUpdated += _update("frontOnly", FrontOnlyResourceStatisticsFactory.getInstance());
058        totalUpdated += _update("httpServerOnly", HTTPServerOnlyResourceStatisticsFactory.getInstance());
059        totalUpdated += _update("frontFromHTTPServer", FrontFromHTTPServerResourceStatisticsFactory.getInstance());
060        
061        if (getLogger().isDebugEnabled())
062        {
063            String durationStr = DateUtils.formatDuration(System.currentTimeMillis() - start);
064            getLogger().debug(String.format("\tTotal count of new request log that have been processed : %s", totalUpdated));
065            getLogger().debug(String.format("Update of the cache stats tables took %s", durationStr));
066        }
067    }
068    
069    private int _update(String logName, ResourceStatisticsFactory factory)
070    {
071        int processed = 0;
072        
073        try (SqlSession sqlSession = getSession())
074        {
075            // Retrieves resources to process + update cache stats
076            List<ResourceStatistics> resourceStatisticsList = factory.getResourceAccessToProcess(sqlSession);
077            int hits = _updateCacheStats(sqlSession, resourceStatisticsList);
078            
079            // Mark handled resource access as processed
080            if (resourceStatisticsList.size() > 0)
081            {
082                processed = factory.markResourcesAsProcessed(sqlSession);
083            }
084            
085            // Commit the transaction.
086            sqlSession.commit();
087            
088            if (getLogger().isDebugEnabled())
089            {
090                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));
091            }
092        }
093        catch (Exception e)
094        {
095            getLogger().error("Exception during update cache stats", e);
096        }
097        
098        return processed;
099    }
100    
101    private int _updateCacheStats(SqlSession sqlSession, List<ResourceStatistics> resourceStatisticsList)
102    {
103        int hits = 0;
104        
105        for (ResourceStatistics resourceStatistics : resourceStatisticsList)
106        {
107            if (resourceStatistics.statExists(sqlSession))
108            {
109                resourceStatistics.updateStat(sqlSession);
110            }
111            else
112            {
113                resourceStatistics.createStat(sqlSession);
114            }
115            
116            hits += resourceStatistics.getHits();
117        }
118        
119        return hits;
120    }
121    
122    /**
123     * Purge the processed raw request entries.
124     */
125    public void purgeRawData()
126    {
127        long start = 0;
128        if (getLogger().isDebugEnabled())
129        {
130            getLogger().debug("Purging raw monitoring data...");
131            start = System.currentTimeMillis();
132        }
133        
134        int totalPurged = 0;
135        try (SqlSession sqlSession = getSession())
136        {
137            totalPurged += PageResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
138            totalPurged += PageElementResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
139            totalPurged += FrontOnlyResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
140            totalPurged += HTTPServerOnlyResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
141            totalPurged += FrontFromHTTPServerResourceStatisticsFactory.getInstance().purgeRawData(sqlSession);
142            
143            // Commit the transaction.
144            sqlSession.commit();
145        }
146        catch (Exception e)
147        {
148            getLogger().error("An error occured while purging raw monitoring data", e);
149        }
150
151        if (getLogger().isDebugEnabled())
152        {
153            String durationStr = DateUtils.formatDuration(System.currentTimeMillis() - start);
154            getLogger().debug(String.format("%s row purged from the database in %s", totalPurged, durationStr));
155        }
156    }
157    
158    /**
159     * Get the raw data for the page elements cache statistics.
160     * @return A list a map, each map representing a page stat entry
161     */
162    public List<Map<String, Object>> getPageElementCacheStats()
163    {
164        try (SqlSession sqlSession = getSession())
165        {
166            String stmtId = "CacheMonitoringStatistics.getPageElementCacheStats";
167            
168            Map<String, Object> params = new HashMap<>();
169            params.put("tableNamePage", Constants.SQL_TABLE_NAME_PAGE_STATISTICS);
170            params.put("tableNamePageElements", Constants.SQL_TABLE_NAME_PAGE_ELEMENTS_STATISTICS);
171            
172            return sqlSession.selectList(stmtId, params);
173        }
174    }
175    
176    /**
177     * Get the raw data for the server cache statistics.
178     * @param siteName The name of the site for which data will be extracted
179     * @return A list a map, each map representing a raw stat entry
180     */
181    public List<Map<String, Object>> getServerCacheStats(String siteName)
182    {
183        try (SqlSession sqlSession = getSession())
184        {
185            String stmtId = "CacheMonitoringStatistics.getServerCacheStats";
186            
187            Map<String, Object> params = new HashMap<>();
188            params.put("tableNameHttpFront", Constants.SQL_TABLE_NAME_HTTPSERVER_AND_FRONT_STATISTICS);
189            params.put("tableNamePage", Constants.SQL_TABLE_NAME_PAGE_STATISTICS);
190            
191            params.put("siteName", siteName);
192            
193            return sqlSession.selectList(stmtId, params);
194        }
195    }
196}