001package org.javasimon.callback.timeline; 002 003import org.javasimon.Split; 004import org.javasimon.Stopwatch; 005import org.javasimon.clock.SimonClock; 006 007/** 008 * Timeline for Stopwatches, historicize {@link Stopwatch} state on a rolling period of time. 009 * 010 * @author gerald 011 */ 012public final class StopwatchTimeline extends Timeline<StopwatchTimeRange> { 013 014 /** 015 * Main constructor. 016 * 017 * @param capacity Number of time range. 018 * @param timeRangeWidth Width of each time range 019 */ 020 public StopwatchTimeline(int capacity, long timeRangeWidth) { 021 super(capacity, timeRangeWidth); 022 } 023 024 /** 025 * Produces a {@link StopwatchTimeRange} object. 026 * 027 * @param startTimestamp Range beginning 028 * @param endTimestamp Range ending 029 * @return {@link StopwatchTimeRange} object 030 */ 031 @Override 032 protected StopwatchTimeRange createTimeRange(long startTimestamp, long endTimestamp) { 033 return new StopwatchTimeRange(startTimestamp, endTimestamp); 034 } 035 036 /** 037 * Main method used to insert the split on the timeline: <ol> 038 * <li>Split start is used to determine in which time-range it should be split. A new time range may be created if needed.</li> 039 * <li>Split duration is added to time range statistics. 040 * </ol> 041 * The split might be drop if it's too old. 042 * 043 * @param split Split 044 */ 045 public void addSplit(Split split) { 046 final long timestamp = split.getStartMillis(); 047 StopwatchTimeRange timeRange; 048 synchronized (this) { 049 timeRange = getOrCreateTimeRange(timestamp); 050 } 051 if (timeRange != null) { 052 //noinspection SynchronizationOnLocalVariableOrMethodParameter 053 synchronized (timeRange) { 054 timeRange.addSplit(timestamp, split.runningFor()); 055 } 056 } 057 } 058 059 /** 060 * Take a snapshot of the timeline. 061 * 062 * @return Timeline sample 063 */ 064 @Override 065 public TimelineSample<StopwatchTimeRange> sample() { 066 StopwatchTimeRange[] timeRangesCopy; 067 synchronized (this) { 068 timeRangesCopy = timeRanges.toArray(new StopwatchTimeRange[timeRanges.size()]); 069 } 070 // TODO sample each time-range by making a copy of it 071 return new TimelineSample<>(timeRanges.getCapacity(), timeRangeWidth * SimonClock.NANOS_IN_MILLIS, timeRangesCopy); 072 } 073}