ggregory

StopWatchLogger

May 2nd, 2017
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.36 KB | None | 0 0
  1. package ...time;
  2.  
  3. import org.apache.logging.log4j.Level;
  4. import org.apache.logging.log4j.Logger;
  5. import org.apache.logging.log4j.message.Message;
  6.  
  7. public class StopWatchLogger extends StopWatch<String> implements AutoCloseable {
  8.  
  9.     public StopWatchLogger(Logger logger, Level level, final String message) {
  10.         super(message);
  11.         this.logger = logger;
  12.         this.level = level;
  13.     }
  14.  
  15.     private final Logger logger;
  16.     private final Level level;
  17.  
  18.     public static StopWatchLogger start(Logger logger, Level level, final String messageStr, Object... args) {
  19.         if (logger.isEnabled(level)) {
  20.             final Message message = logger.getMessageFactory().newMessage(messageStr, args);
  21.             final StopWatchLogger sw = new StopWatchLogger(logger, level, message.getFormattedMessage());
  22.             logger.log(level, message);
  23.             sw.start();
  24.             return sw;
  25.         }
  26.         final StopWatchLogger stopWatchLogger = new StopWatchLogger(logger, level, StringUtils.EMPTY);
  27.         stopWatchLogger.start();
  28.         return stopWatchLogger;
  29.     }
  30.  
  31.     @Override
  32.     public void close() {
  33.         stop();
  34.         logger.log(level, "[" + getMessage() + "] took " + this.toFormattedTime());
  35.     }
  36.  
  37.     public Logger getLogger() {
  38.         return logger;
  39.     }
  40.  
  41.     public Level getLevel() {
  42.         return level;
  43.     }
  44.  
  45. }
  46. ----------------------------------------------------------------------------------------------
  47. /*
  48.  * Licensed to the Apache Software Foundation (ASF) under one or more
  49.  * contributor license agreements.  See the NOTICE file distributed with
  50.  * this work for additional information regarding copyright ownership.
  51.  * The ASF licenses this file to You under the Apache License, Version 2.0
  52.  * (the "License"); you may not use this file except in compliance with
  53.  * the License.  You may obtain a copy of the License at
  54.  *
  55.  *      http://www.apache.org/licenses/LICENSE-2.0
  56.  *
  57.  * Unless required by applicable law or agreed to in writing, software
  58.  * distributed under the License is distributed on an "AS IS" BASIS,
  59.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  60.  * See the License for the specific language governing permissions and
  61.  * limitations under the License.
  62.  */
  63.  
  64. // COPIED AND TWEAKSED FROM APACHE COMMONS LANG 3.5 WITH FLUENT APIs AND NEW APIS.
  65.  
  66. package ...time;
  67.  
  68. import java.util.concurrent.TimeUnit;
  69.  
  70. import org.apache.commons.lang3.time.DurationFormatUtils;
  71.  
  72. /**
  73.  * <p>
  74.  * <code>StopWatch</code> provides a convenient API for timings.
  75.  * </p>
  76.  *
  77.  * <p>
  78.  * To start the watch, call {@link #start()} or {@link StopWatch#createStarted()}. At this point you can:
  79.  * </p>
  80.  * <ul>
  81.  * <li>{@link #split()} the watch to get the time whilst the watch continues in the background. {@link #unsplit()} will remove the effect of
  82.  * the split. At this point, these three options are available again.</li>
  83.  * <li>{@link #suspend()} the watch to pause it. {@link #resume()} allows the watch to continue. Any time between the suspend and resume
  84.  * will not be counted in the total. At this point, these three options are available again.</li>
  85.  * <li>{@link #stop()} the watch to complete the timing session.</li>
  86.  * </ul>
  87.  *
  88.  * <p>
  89.  * It is intended that the output methods {@link #toString()} and {@link #getTime()} should only be called after stop, split or suspend,
  90.  * however a suitable result will be returned at other points.
  91.  * </p>
  92.  *
  93.  * <p>
  94.  * NOTE: As from v2.1, the methods protect against inappropriate calls. Thus you cannot now call stop before start, resume before suspend or
  95.  * unsplit before split.
  96.  * </p>
  97.  *
  98.  * <p>
  99.  * 1. split(), suspend(), or stop() cannot be invoked twice<br>
  100.  * 2. unsplit() may only be called if the watch has been split()<br>
  101.  * 3. resume() may only be called if the watch has been suspend()<br>
  102.  * 4. start() cannot be called twice without calling reset()
  103.  * </p>
  104.  *
  105.  * <p>
  106.  * This class is not thread-safe
  107.  * </p>
  108.  *
  109.  * @since 2.0
  110.  */
  111. public class StopWatch<T> {
  112.  
  113.     /**
  114.      * Enumeration type which indicates the split status of stopwatch.
  115.      */
  116.     private enum SplitState {
  117.         SPLIT,
  118.         UNSPLIT
  119.     }
  120.  
  121.     /**
  122.      * Enumeration type which indicates the status of stopwatch.
  123.      */
  124.     private enum State {
  125.  
  126.         UNSTARTED {
  127.             @Override
  128.             boolean isStarted() {
  129.                 return false;
  130.             }
  131.  
  132.             @Override
  133.             boolean isStopped() {
  134.                 return true;
  135.             }
  136.  
  137.             @Override
  138.             boolean isSuspended() {
  139.                 return false;
  140.             }
  141.         },
  142.         RUNNING {
  143.             @Override
  144.             boolean isStarted() {
  145.                 return true;
  146.             }
  147.  
  148.             @Override
  149.             boolean isStopped() {
  150.                 return false;
  151.             }
  152.  
  153.             @Override
  154.             boolean isSuspended() {
  155.                 return false;
  156.             }
  157.         },
  158.         STOPPED {
  159.             @Override
  160.             boolean isStarted() {
  161.                 return false;
  162.             }
  163.  
  164.             @Override
  165.             boolean isStopped() {
  166.                 return true;
  167.             }
  168.  
  169.             @Override
  170.             boolean isSuspended() {
  171.                 return false;
  172.             }
  173.         },
  174.         SUSPENDED {
  175.             @Override
  176.             boolean isStarted() {
  177.                 return true;
  178.             }
  179.  
  180.             @Override
  181.             boolean isStopped() {
  182.                 return false;
  183.             }
  184.  
  185.             @Override
  186.             boolean isSuspended() {
  187.                 return true;
  188.             }
  189.         };
  190.  
  191.         /**
  192.          * <p>
  193.          * The method is used to find out if the StopWatch is started. A suspended StopWatch is also started watch.
  194.          * </p>
  195.          *
  196.          * @return boolean If the StopWatch is started.
  197.          */
  198.         abstract boolean isStarted();
  199.  
  200.         /**
  201.          * <p>
  202.          * This method is used to find out whether the StopWatch is stopped. The stopwatch which's not yet started and explicitly stopped
  203.          * stopwatch is considered as stopped.
  204.          * </p>
  205.          *
  206.          * @return boolean If the StopWatch is stopped.
  207.          */
  208.         abstract boolean isStopped();
  209.  
  210.         /**
  211.          * <p>
  212.          * This method is used to find out whether the StopWatch is suspended.
  213.          * </p>
  214.          *
  215.          * @return boolean If the StopWatch is suspended.
  216.          */
  217.         abstract boolean isSuspended();
  218.     }
  219.  
  220.     private static final long NANO_2_MILLIS = 1000000L;
  221.  
  222.     /**
  223.      * Provides a started stopwatch for convenience.
  224.      *
  225.      * @return StopWatch a stopwatch that's already been started.
  226.      *
  227.      * @since 3.5
  228.      */
  229.     public static StopWatch<Void> createStarted() {
  230.         final StopWatch<Void> sw = new StopWatch<>();
  231.         sw.start();
  232.         return sw;
  233.     }
  234.  
  235.     public static StopWatch<String> createStarted(final String description) {
  236.         final StopWatch<String> sw = new StopWatch<>(description);
  237.         sw.start();
  238.         return sw;
  239.     }
  240.  
  241.     /**
  242.      * The current running state of the StopWatch.
  243.      */
  244.     private State runningState = State.UNSTARTED;
  245.  
  246.     /**
  247.      * Whether the stopwatch has a split time recorded.
  248.      */
  249.     private SplitState splitState = SplitState.UNSPLIT;
  250.  
  251.     /**
  252.      * The start time.
  253.      */
  254.     private long startTime;
  255.  
  256.     /**
  257.      * The start time in Millis - nanoTime is only for elapsed time so we need to also store the currentTimeMillis to maintain the old
  258.      * getStartTime API.
  259.      */
  260.     private long startTimeMillis;
  261.  
  262.     /**
  263.      * The stop time.
  264.      */
  265.     private long stopTime;
  266.  
  267.     private final T message;
  268.  
  269.     /**
  270.      * <p>
  271.      * Constructor.
  272.      * </p>
  273.      */
  274.     public StopWatch() {
  275.         super();
  276.         this.message = null;
  277.     }
  278.  
  279.     /**
  280.      * <p>
  281.      * Constructor.
  282.      * </p>
  283.      */
  284.     public StopWatch(final T message) {
  285.         super();
  286.         this.message = message;
  287.     }
  288.  
  289.     public T getMessage() {
  290.         return message;
  291.     }
  292.  
  293.     /**
  294.      * <p>
  295.      * Get the time on the stopwatch in nanoseconds.
  296.      * </p>
  297.      *
  298.      * <p>
  299.      * This is either the time between the start and the moment this method is called, or the amount of time between start and stop.
  300.      * </p>
  301.      *
  302.      * @return the time in nanoseconds
  303.      * @since 3.0
  304.      */
  305.     public long getNanoTime() {
  306.         if (this.runningState == State.STOPPED || this.runningState == State.SUSPENDED) {
  307.             return this.stopTime - this.startTime;
  308.         } else if (this.runningState == State.UNSTARTED) {
  309.             return 0;
  310.         } else if (this.runningState == State.RUNNING) {
  311.             return System.nanoTime() - this.startTime;
  312.         }
  313.         throw new RuntimeException("Illegal running state has occurred.");
  314.     }
  315.  
  316.     /**
  317.      * <p>
  318.      * Get the split time on the stopwatch in nanoseconds.
  319.      * </p>
  320.      *
  321.      * <p>
  322.      * This is the time between start and latest split.
  323.      * </p>
  324.      *
  325.      * @return the split time in nanoseconds
  326.      *
  327.      * @throws IllegalStateException
  328.      *             if the StopWatch has not yet been split.
  329.      * @since 3.0
  330.      */
  331.     public long getSplitNanoTime() {
  332.         if (this.splitState != SplitState.SPLIT) {
  333.             throw new IllegalStateException("Stopwatch must be split to get the split time. ");
  334.         }
  335.         return this.stopTime - this.startTime;
  336.     }
  337.  
  338.     /**
  339.      * <p>
  340.      * Get the split time on the stopwatch.
  341.      * </p>
  342.      *
  343.      * <p>
  344.      * This is the time between start and latest split.
  345.      * </p>
  346.      *
  347.      * @return the split time in milliseconds
  348.      *
  349.      * @throws IllegalStateException
  350.      *             if the StopWatch has not yet been split.
  351.      * @since 2.1
  352.      */
  353.     public long getSplitTime() {
  354.         return getSplitNanoTime() / NANO_2_MILLIS;
  355.     }
  356.  
  357.     /**
  358.      * Returns the time this stopwatch was started.
  359.      *
  360.      * @return the time this stopwatch was started
  361.      * @throws IllegalStateException
  362.      *             if this StopWatch has not been started
  363.      * @since 2.4
  364.      */
  365.     public long getStartTime() {
  366.         if (this.runningState == State.UNSTARTED) {
  367.             throw new IllegalStateException("Stopwatch has not been started");
  368.         }
  369.         // System.nanoTime is for elapsed time
  370.         return this.startTimeMillis;
  371.     }
  372.  
  373.     /**
  374.      * <p>
  375.      * Get the time on the stopwatch.
  376.      * </p>
  377.      *
  378.      * <p>
  379.      * This is either the time between the start and the moment this method is called, or the amount of time between start and stop.
  380.      * </p>
  381.      *
  382.      * @return the time in milliseconds
  383.      */
  384.     public long getTime() {
  385.         return getNanoTime() / NANO_2_MILLIS;
  386.     }
  387.  
  388.     /**
  389.      * <p>
  390.      * Get the time on the stopwatch in the specified TimeUnit.
  391.      * </p>
  392.      *
  393.      * <p>
  394.      * This is either the time between the start and the moment this method is called, or the amount of time between start and stop. The
  395.      * resulting time will be expressed in the desired TimeUnit with any remainder rounded down. For example, if the specified unit is
  396.      * {@code TimeUnit.HOURS} and the stopwatch time is 59 minutes, then the result returned will be {@code 0}.
  397.      * </p>
  398.      *
  399.      * @param timeUnit
  400.      *            the unit of time, not null
  401.      * @return the time in the specified TimeUnit, rounded down
  402.      * @since 3.5
  403.      */
  404.     public long getTime(final TimeUnit timeUnit) {
  405.         return timeUnit.convert(getNanoTime(), TimeUnit.NANOSECONDS);
  406.     }
  407.  
  408.     /**
  409.      * <p>
  410.      * The method is used to find out if the StopWatch is started. A suspended StopWatch is also started watch.
  411.      * </p>
  412.      *
  413.      * @return boolean If the StopWatch is started.
  414.      * @since 3.2
  415.      */
  416.     public boolean isStarted() {
  417.         return runningState.isStarted();
  418.     }
  419.  
  420.     /**
  421.      * <p>
  422.      * This method is used to find out whether the StopWatch is stopped. The stopwatch which's not yet started and explicitly stopped
  423.      * stopwatch is considered as stopped.
  424.      * </p>
  425.      *
  426.      * @return boolean If the StopWatch is stopped.
  427.      * @since 3.2
  428.      */
  429.     public boolean isStopped() {
  430.         return runningState.isStopped();
  431.     }
  432.  
  433.     /**
  434.      * <p>
  435.      * This method is used to find out whether the StopWatch is suspended.
  436.      * </p>
  437.      *
  438.      * @return boolean If the StopWatch is suspended.
  439.      * @since 3.2
  440.      */
  441.     public boolean isSuspended() {
  442.         return runningState.isSuspended();
  443.     }
  444.  
  445.     /**
  446.      * <p>
  447.      * Resets the stopwatch. Stops it if need be.
  448.      * </p>
  449.      *
  450.      * <p>
  451.      * This method clears the internal values to allow the object to be reused.
  452.      * </p>
  453.      */
  454.     public StopWatch<T> reset() {
  455.         this.runningState = State.UNSTARTED;
  456.         this.splitState = SplitState.UNSPLIT;
  457.         return this;
  458.     }
  459.  
  460.     /**
  461.      * <p>
  462.      * Resume the stopwatch after a suspend.
  463.      * </p>
  464.      *
  465.      * <p>
  466.      * This method resumes the watch after it was suspended. The watch will not include time between the suspend and resume calls in the
  467.      * total time.
  468.      * </p>
  469.      *
  470.      * @throws IllegalStateException
  471.      *             if the StopWatch has not been suspended.
  472.      */
  473.     public StopWatch<T> resume() {
  474.         if (this.runningState != State.SUSPENDED) {
  475.             throw new IllegalStateException("Stopwatch must be suspended to resume. ");
  476.         }
  477.         this.startTime += System.nanoTime() - this.stopTime;
  478.         this.runningState = State.RUNNING;
  479.         return this;
  480.     }
  481.  
  482.     /**
  483.      * <p>
  484.      * Split the time.
  485.      * </p>
  486.      *
  487.      * <p>
  488.      * This method sets the stop time of the watch to allow a time to be extracted. The start time is unaffected, enabling
  489.      * {@link #unsplit()} to continue the timing from the original start point.
  490.      * </p>
  491.      *
  492.      * @throws IllegalStateException
  493.      *             if the StopWatch is not running.
  494.      */
  495.     public StopWatch<T> split() {
  496.         if (this.runningState != State.RUNNING) {
  497.             throw new IllegalStateException("Stopwatch is not running. ");
  498.         }
  499.         this.stopTime = System.nanoTime();
  500.         this.splitState = SplitState.SPLIT;
  501.         return this;
  502.     }
  503.  
  504.     /**
  505.      * <p>
  506.      * Start the stopwatch.
  507.      * </p>
  508.      *
  509.      * <p>
  510.      * This method starts a new timing session, clearing any previous values.
  511.      * </p>
  512.      *
  513.      * @throws IllegalStateException
  514.      *             if the StopWatch is already running.
  515.      */
  516.     public StopWatch<T> start() {
  517.         if (this.runningState == State.STOPPED) {
  518.             throw new IllegalStateException("Stopwatch must be reset before being restarted. ");
  519.         }
  520.         if (this.runningState != State.UNSTARTED) {
  521.             throw new IllegalStateException("Stopwatch already started. ");
  522.         }
  523.         this.startTime = System.nanoTime();
  524.         this.startTimeMillis = System.currentTimeMillis();
  525.         this.runningState = State.RUNNING;
  526.         return this;
  527.     }
  528.  
  529.     /**
  530.      * <p>
  531.      * Stop the stopwatch.
  532.      * </p>
  533.      *
  534.      * <p>
  535.      * This method ends a new timing session, allowing the time to be retrieved.
  536.      * </p>
  537.      *
  538.      * @throws IllegalStateException
  539.      *             if the StopWatch is not running.
  540.      */
  541.     public StopWatch<T> stop() {
  542.         if (this.runningState != State.RUNNING && this.runningState != State.SUSPENDED) {
  543.             throw new IllegalStateException("Stopwatch is not running. ");
  544.         }
  545.         if (this.runningState == State.RUNNING) {
  546.             this.stopTime = System.nanoTime();
  547.         }
  548.         this.runningState = State.STOPPED;
  549.         return this;
  550.     }
  551.  
  552.     /**
  553.      * <p>
  554.      * Suspend the stopwatch for later resumption.
  555.      * </p>
  556.      *
  557.      * <p>
  558.      * This method suspends the watch until it is resumed. The watch will not include time between the suspend and resume calls in the total
  559.      * time.
  560.      * </p>
  561.      *
  562.      * @throws IllegalStateException
  563.      *             if the StopWatch is not currently running.
  564.      */
  565.     public StopWatch<T> suspend() {
  566.         if (this.runningState != State.RUNNING) {
  567.             throw new IllegalStateException("Stopwatch must be running to suspend. ");
  568.         }
  569.         this.stopTime = System.nanoTime();
  570.         this.runningState = State.SUSPENDED;
  571.         return this;
  572.     }
  573.  
  574.     public String toFormattedSplitTime() {
  575.         return DurationFormatUtils.formatDurationHMS(getSplitTime());
  576.     }
  577.  
  578.     public String toFormattedTime() {
  579.         return DurationFormatUtils.formatDurationHMS(getTime());
  580.     }
  581.  
  582.     /**
  583.      * <p>
  584.      * Gets a summary of the split time that the stopwatch recorded as a string.
  585.      * </p>
  586.      *
  587.      * <p>
  588.      * The format used is ISO 8601-like, <i>hours</i>:<i>minutes</i>:<i>seconds</i>.<i>milliseconds</i>.
  589.      * </p>
  590.      *
  591.      * @return the split time as a String
  592.      * @since 2.1
  593.      */
  594.     public String toSplitString() {
  595.         final String msgStr = message.toString();
  596.         final String formattedTime = toFormattedSplitTime();
  597.         return msgStr.isEmpty() ? formattedTime : msgStr + " " + formattedTime;
  598.     }
  599.  
  600.     /**
  601.      * <p>
  602.      * Gets a summary of the time that the stopwatch recorded as a string.
  603.      * </p>
  604.      *
  605.      * <p>
  606.      * The format used is ISO 8601-like, <i>hours</i>:<i>minutes</i>:<i>seconds</i>.<i>milliseconds</i>.
  607.      * </p>
  608.      *
  609.      * @return the time as a String
  610.      */
  611.     @Override
  612.     public String toString() {
  613.         final String msgStr = message.toString();
  614.         final String formattedTime = toFormattedTime();
  615.         return msgStr.isEmpty() ? formattedTime : msgStr + " " + formattedTime;
  616.     }
  617.  
  618.     /**
  619.      * <p>
  620.      * Remove a split.
  621.      * </p>
  622.      *
  623.      * <p>
  624.      * This method clears the stop time. The start time is unaffected, enabling timing from the original start point to continue.
  625.      * </p>
  626.      *
  627.      * @throws IllegalStateException
  628.      *             if the StopWatch has not been split.
  629.      */
  630.     public StopWatch<T> unsplit() {
  631.         if (this.splitState != SplitState.SPLIT) {
  632.             throw new IllegalStateException("Stopwatch has not been split. ");
  633.         }
  634.         this.splitState = SplitState.UNSPLIT;
  635.         return this;
  636.     }
  637.  
  638. }
Advertisement
Add Comment
Please, Sign In to add comment