001package org.javasimon.callback.logging;
002
003import static org.javasimon.callback.logging.LogTemplates.toSLF4J;
004
005import org.javasimon.SimonManager;
006import org.javasimon.Split;
007import org.javasimon.Stopwatch;
008import org.javasimon.StopwatchSample;
009import org.javasimon.callback.CallbackSkeleton;
010import org.javasimon.utils.SimonUtils;
011
012/**
013 * Callback which logs stopwatch splits and manager warnings.
014 * By default every split is logged, but one can configure this callback to log
015 * only:<ul>
016 * <li>Splits too long (longer that threshold)</li>
017 * <li>One split out of N</li>
018 * <li>One split every N milliseconds</li>
019 * </li>
020 */
021public class LoggingCallback extends CallbackSkeleton {
022
023        /** Log template used for Stopwatch splits. */
024        private final LogTemplate<Split> stopwatchLogTemplate;
025
026        /** Split to string converter. */
027        private final LogMessageSource<Split> stopwatchLogMessageSource = new LogMessageSource<Split>() {
028                public String getLogMessage(Split split) {
029                        return "Split " + SimonUtils.presentNanoTime(split.runningFor()) + " in Stopwatch " + split.getStopwatch();
030                }
031        };
032
033        /** Log template used for manager. */
034        private final LogTemplate<String> managerLogTemplate;
035
036        /** String to string (no-op) converter. */
037        private final LogMessageSource<String> managerLogMessageSource = new LogMessageSource<String>() {
038                public String getLogMessage(String message) {
039                        return message;
040                }
041        };
042
043        /**
044         * Constructor which can be used to customize log templates.
045         *
046         * @param stopwatchLogTemplate Logger used for Stopwatch splits
047         * @param managerLogTemplate Logger used for manager
048         */
049        public LoggingCallback(LogTemplate<Split> stopwatchLogTemplate, LogTemplate<String> managerLogTemplate) {
050                this.stopwatchLogTemplate = stopwatchLogTemplate;
051                this.managerLogTemplate = managerLogTemplate;
052        }
053
054        /** Default constructor logging everything to SLF4J. */
055        public LoggingCallback() {
056                this.stopwatchLogTemplate = toSLF4J(Stopwatch.class.getName(), "debug");
057                this.managerLogTemplate = toSLF4J(SimonManager.class.getName(), "info");
058        }
059
060        /**
061         * Get log template used  for manage warnings.
062         *
063         * @return Logger
064         */
065        public LogTemplate<String> getManagerLogTemplate() {
066                return managerLogTemplate;
067        }
068
069        /**
070         * Get log template used  for stopwatch splits.
071         *
072         * @return Logger
073         */
074        public LogTemplate<Split> getStopwatchLogTemplate() {
075                return stopwatchLogTemplate;
076        }
077
078        /**
079         * Get log template for stopwatch, defaults to {@link #stopwatchLogTemplate}.
080         * This method can be overridden to get a specific log template per stopwatch.
081         *
082         * @param stopwatch Stopwatch
083         * @return Logger
084         */
085        @SuppressWarnings("UnusedParameters")
086        protected LogTemplate<Split> getStopwatchLogTemplate(Stopwatch stopwatch) {
087                return stopwatchLogTemplate;
088        }
089
090        /**
091         * {@inheritDoc}
092         * Split and stopwatch are logger to log template is enabled.
093         *
094         * @param split Split
095         * @param sample Stopwatch sample
096         */
097        @Override
098        public void onStopwatchStop(Split split, StopwatchSample sample) {
099                getStopwatchLogTemplate(split.getStopwatch()).log(split, stopwatchLogMessageSource);
100        }
101
102        @Override
103        public void onManagerWarning(String warning, Exception cause) {
104                managerLogTemplate.log(warning, managerLogMessageSource);
105        }
106}