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