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}