OSCache - Statistics

### Description With the cache event handlers a listerner can be implemented to provide cache hits and misses information. You can copy and paste the following code to get a statistic of your OSCache integration. Just change the used logger and the sample helps you to improve the cache key creation and to decide which scope to use. The SimpleStatisticListenerImpl should be configured via the cache.event.listeners in the oscache.properties. ### Sample Code SimpleStatisticListenerImpl.java
    /*
     * Copyright (c) 2002-2007 by OpenSymphony
     * All rights reserved.
     */
    package com.opensymphony.oscache.extra;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    import com.opensymphony.oscache.base.Cache;
    import com.opensymphony.oscache.base.events.*;

    /**
     * A simple implementation of a statistic reporter which uses the
     * CacheMapAccessEventListener, CacheEntryEventListener and ScopeEventListener.
     * It uses the events to count the cache hit and misses and of course the
     * flushes.
     * <p>
     * We are not using any synchronized so that this does not become a bottleneck.
     * The consequence is that on retrieving values, the operations that are
     * currently being done won't be counted.
     */
    public class SimpleStatisticListenerImpl implements CacheMapAccessEventListener, CacheEntryEventListener, ScopeEventListener {

        private static transient final Log log = LogFactory.getLog(SimpleStatisticListenerImpl.class);

        /**
         * Hit counter
         */
        private int hitCount = 0;

        /**
         * Miss counter
         */
        private int missCount = 0;

        /**
         * Stale hit counter
         */
        private int staleHitCount = 0;

        /**
         * Hit counter sum
         */
        private int hitCountSum = 0;

        /**
         * Miss counter sum
         */
        private int missCountSum = 0;

        /**
         * Stale hit counter
         */
        private int staleHitCountSum = 0;

        /**
         * Flush hit counter
         */
        private int flushCount = 0;

        /**
         * Constructor, empty for us
         */
        public SimpleStatisticListenerImpl() {
            log.info("Creation of SimpleStatisticListenerImpl");
        }

        /**
         * This method handles an event each time the cache is accessed
         *
         * @param event The event triggered when the cache was accessed
         * @see com.opensymphony.oscache.base.events.CacheMapAccessEventListener#accessed(CacheMapAccessEvent)
         */
        public void accessed(CacheMapAccessEvent event) {
            String result = "N/A";

            // Retrieve the event type and update the counters
            CacheMapAccessEventType type = event.getEventType();

            // Handles a hit event
            if (type == CacheMapAccessEventType.HIT) {
                hitCount++;
                result = "HIT";
            }
            // Handles a stale hit event
            else if (type == CacheMapAccessEventType.STALE_HIT) {
                staleHitCount++;
                result = "STALE HIT";
            }
            // Handles a miss event
            else if (type == CacheMapAccessEventType.MISS) {
                missCount++;
                result = "MISS";
            }

            if (log.isDebugEnabled()) {
                log.debug("ACCESS : " + result + ": " + event.getCacheEntryKey());
                log.debug("STATISTIC : Hit = " + hitCount + ", stale hit ="
                        + staleHitCount + ", miss = " + missCount);
            }
        }

        /**
         * Logs the flush of the cache.
         *
         * @param info the string to be logged.
         */
        private void flushed(String info) {
            flushCount++;

            hitCountSum += hitCount;
            staleHitCountSum += staleHitCount;
            missCountSum += missCount;

            if (log.isInfoEnabled()) {
                log.info("FLUSH : " + info);
                log.info("STATISTIC SUM : " + "Hit = " + hitCountSum
                        + ", stale hit = " + staleHitCountSum + ", miss = "
                        + missCountSum + ", flush = " + flushCount);
            }

            hitCount = 0;
            staleHitCount = 0;
            missCount = 0;
        }

        /**
         * Event fired when a specific or all scopes are flushed.
         *
         * @param event ScopeEvent
         * @see com.opensymphony.oscache.base.events.ScopeEventListener#scopeFlushed(ScopeEvent)
         */
        public void scopeFlushed(ScopeEvent event) {
            flushed("scope " + ScopeEventListenerImpl.SCOPE_NAMES[event.getScope()]);
        }

        /**
         * Event fired when an entry is added to the cache.
         *
         * @param event CacheEntryEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cacheEntryAdded(CacheEntryEvent)
         */
        public void cacheEntryAdded(CacheEntryEvent event) {
            // do nothing
        }

        /**
         * Event fired when an entry is flushed from the cache.
         *
         * @param event CacheEntryEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cacheEntryFlushed(CacheEntryEvent)
         */
        public void cacheEntryFlushed(CacheEntryEvent event) {
            // do nothing, because a group or other flush is coming
            if (!Cache.NESTED_EVENT.equals(event.getOrigin())) {
                flushed("entry " + event.getKey() + " / " + event.getOrigin());
            }
        }

        /**
         * Event fired when an entry is removed from the cache.
         *
         * @param event CacheEntryEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cacheEntryRemoved(CacheEntryEvent)
         */
        public void cacheEntryRemoved(CacheEntryEvent event) {
            // do nothing
        }

        /**
         * Event fired when an entry is updated in the cache.
         *
         * @param event CacheEntryEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cacheEntryUpdated(CacheEntryEvent)
         */
        public void cacheEntryUpdated(CacheEntryEvent event) {
            // do nothing
        }

        /**
         * Event fired when a group is flushed from the cache.
         *
         * @param event CacheGroupEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cacheGroupFlushed(CacheGroupEvent)
         */
        public void cacheGroupFlushed(CacheGroupEvent event) {
            flushed("group " + event.getGroup());
        }

        /**
         * Event fired when a key pattern is flushed from the cache.
         *
         * @param event CachePatternEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cachePatternFlushed(CachePatternEvent)
         */
        public void cachePatternFlushed(CachePatternEvent event) {
            flushed("pattern " + event.getPattern());
        }

        /**
         * An event that is fired when an entire cache gets flushed.
         *
         * @param event CachewideEvent
         * @see com.opensymphony.oscache.base.events.CacheEntryEventListener#cacheFlushed(CachewideEvent)
         */
        public void cacheFlushed(CachewideEvent event) {
            flushed("wide " + event.getDate());
        }

        /**
         * Return the counters in a string form
         *
         * @return String
         */
        public String toString() {
            return "SimpleStatisticListenerImpl: Hit = " + hitCount + " / " + hitCountSum
                    + ", stale hit = " + staleHitCount + " / " + staleHitCountSum
                    + ", miss = " + missCount + " / " + missCountSum
                    + ", flush = " + flushCount;
        }
    }