001package org.javasimon.callback.lastsplits;
002
003import org.javasimon.Simon;
004import org.javasimon.Split;
005import org.javasimon.Stopwatch;
006import org.javasimon.StopwatchSample;
007import org.javasimon.callback.CallbackSkeleton;
008import org.javasimon.callback.logging.LogTemplate;
009
010import static org.javasimon.callback.logging.LogTemplates.disabled;
011import static org.javasimon.callback.logging.LogTemplates.everyNSplits;
012import static org.javasimon.callback.logging.LogTemplates.toSLF4J;
013
014/**
015 * Callback retaining the last N stopwatch splits.
016 * Splits can be logged when buffer revolves.
017 *
018 * @author gquintana
019 * @see LastSplits
020 * @since 3.2
021 */
022public class LastSplitsCallback extends CallbackSkeleton {
023        /**
024         * Simon attribute name of the LastSplit object stored in Simons.
025         */
026        public static final String ATTR_NAME_LAST_SPLITS = "lastSplits";
027
028        /**
029         * Number of splits retained in each Simon.
030         * Default 10
031         */
032        private final int capacity;
033
034        /**
035         * Global flag indicating whether last splits should be logged once in a while.
036         */
037        private boolean logEnabled = false;
038
039        /**
040         * SLF4J log template shared by all stopwatches.
041         */
042        private final LogTemplate<Split> enabledStopwatchLogTemplate = toSLF4J(getClass().getName(), "debug");
043
044        /**
045         * Default constructor with a buffer capacity of 10.
046         */
047        public LastSplitsCallback() {
048                this.capacity = 10;
049        }
050
051        /**
052         * Constructor with buffer capacity.
053         *
054         * @param capacity buffer capacity
055         */
056        public LastSplitsCallback(int capacity) {
057                this.capacity = capacity;
058        }
059
060        /**
061         * Get the {@link LastSplits} object from Simon attributes.
062         *
063         * @param stopwatch stopwatch
064         * @return LastSplits object
065         */
066        private LastSplits getLastSplits(Stopwatch stopwatch) {
067                return (LastSplits) stopwatch.getAttribute(ATTR_NAME_LAST_SPLITS);
068        }
069
070        /**
071         * When Stopwatch is created, a Last Splits attributes is added.
072         */
073        @Override
074        public void onSimonCreated(Simon simon) {
075                if (simon instanceof Stopwatch) {
076                        Stopwatch stopwatch = (Stopwatch) simon;
077                        LastSplits lastSplits = new LastSplits(capacity);
078                        lastSplits.setLogTemplate(createLogTemplate(stopwatch));
079                        stopwatch.setAttribute(ATTR_NAME_LAST_SPLITS, lastSplits);
080                }
081
082        }
083
084        /**
085         * When a Splits is stopped, it is added to the stopwatch a Last Splits attribute.
086         */
087        @Override
088        public void onStopwatchStop(Split split, StopwatchSample sample) {
089                LastSplits lastSplits = getLastSplits(split.getStopwatch());
090                lastSplits.add(split);
091                lastSplits.log(split);
092        }
093
094        @Override
095        public void onStopwatchAdd(Stopwatch stopwatch, Split split, StopwatchSample sample) {
096                LastSplits lastSplits = getLastSplits(stopwatch);
097                lastSplits.add(split);
098                lastSplits.log(split);
099        }
100
101        public boolean isLogEnabled() {
102                return logEnabled;
103        }
104
105        public void setLogEnabled(boolean logEnabled) {
106                this.logEnabled = logEnabled;
107        }
108
109        /**
110         * Create log template for given stopwatch.
111         * This method can be overridden to tune logging strategy.
112         * By default, when {@link #isLogEnabled()} is set, last splits are logged at each buffer revolution.
113         *
114         * @param stopwatch Stopwatch
115         * @return Log template
116         */
117        @SuppressWarnings("UnusedParameters")
118        protected LogTemplate<Split> createLogTemplate(Stopwatch stopwatch) {
119                LogTemplate<Split> logTemplate;
120                if (logEnabled) {
121                        logTemplate = everyNSplits(enabledStopwatchLogTemplate, capacity);
122                } else {
123                        logTemplate = disabled();
124                }
125                return logTemplate;
126        }
127}