1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ddmuilib.log.event; 18 19 import com.android.ddmlib.log.EventContainer; 20 import com.android.ddmlib.log.EventLogParser; 21 import com.android.ddmlib.log.InvalidTypeException; 22 import org.eclipse.swt.widgets.Composite; 23 import org.eclipse.swt.widgets.Control; 24 import org.jfree.chart.labels.CustomXYToolTipGenerator; 25 import org.jfree.chart.plot.XYPlot; 26 import org.jfree.chart.renderer.xy.XYBarRenderer; 27 import org.jfree.data.time.SimpleTimePeriod; 28 import org.jfree.data.time.TimePeriodValues; 29 import org.jfree.data.time.TimePeriodValuesCollection; 30 31 import java.awt.Color; 32 import java.util.ArrayList; 33 import java.util.List; 34 35 public class DisplaySyncPerf extends SyncCommon { 36 37 CustomXYToolTipGenerator mTooltipGenerator; 38 List mTooltips[]; 39 40 // The series number for each graphed item. 41 // sync authorities are 0-3 42 private static final int DB_QUERY = 4; 43 private static final int DB_WRITE = 5; 44 private static final int HTTP_NETWORK = 6; 45 private static final int HTTP_PROCESSING = 7; 46 private static final int NUM_SERIES = (HTTP_PROCESSING + 1); 47 private static final String SERIES_NAMES[] = {"Calendar", "Gmail", "Feeds", "Contacts", 48 "DB Query", "DB Write", "HTTP Response", "HTTP Processing",}; 49 private static final Color SERIES_COLORS[] = {Color.MAGENTA, Color.GREEN, Color.BLUE, 50 Color.ORANGE, Color.RED, Color.CYAN, Color.PINK, Color.DARK_GRAY}; 51 private static final double SERIES_YCOORD[] = {0, 0, 0, 0, 1, 1, 2, 2}; 52 53 // Values from data/etc/event-log-tags 54 private static final int EVENT_DB_OPERATION = 52000; 55 private static final int EVENT_HTTP_STATS = 52001; 56 // op types for EVENT_DB_OPERATION 57 final int EVENT_DB_QUERY = 0; 58 final int EVENT_DB_WRITE = 1; 59 60 // Information to graph for each authority 61 private TimePeriodValues mDatasets[]; 62 63 /** 64 * TimePeriodValuesCollection that supports Y intervals. This allows the 65 * creation of "floating" bars, rather than bars rooted to the axis. 66 */ 67 class YIntervalTimePeriodValuesCollection extends TimePeriodValuesCollection { 68 /** default serial UID */ 69 private static final long serialVersionUID = 1L; 70 71 private double yheight; 72 73 /** 74 * Constructs a collection of bars with a fixed Y height. 75 * 76 * @param yheight The height of the bars. 77 */ 78 YIntervalTimePeriodValuesCollection(double yheight) { 79 this.yheight = yheight; 80 } 81 82 /** 83 * Returns ending Y value that is a fixed amount greater than the starting value. 84 * 85 * @param series the series (zero-based index). 86 * @param item the item (zero-based index). 87 * @return The ending Y value for the specified series and item. 88 */ 89 @Override 90 public Number getEndY(int series, int item) { 91 return getY(series, item).doubleValue() + yheight; 92 } 93 } 94 95 /** 96 * Constructs a graph of network and database stats. 97 * 98 * @param name The name of this graph in the graph list. 99 */ 100 public DisplaySyncPerf(String name) { 101 super(name); 102 } 103 104 /** 105 * Creates the UI for the event display. 106 * 107 * @param parent the parent composite. 108 * @param logParser the current log parser. 109 * @return the created control (which may have children). 110 */ 111 @Override 112 public Control createComposite(final Composite parent, EventLogParser logParser, 113 final ILogColumnListener listener) { 114 Control composite = createCompositeChart(parent, logParser, "Sync Performance"); 115 resetUI(); 116 return composite; 117 } 118 119 /** 120 * Resets the display. 121 */ 122 @Override 123 void resetUI() { 124 super.resetUI(); 125 XYPlot xyPlot = mChart.getXYPlot(); 126 xyPlot.getRangeAxis().setVisible(false); 127 mTooltipGenerator = new CustomXYToolTipGenerator(); 128 mTooltips = new List[NUM_SERIES]; 129 130 XYBarRenderer br = new XYBarRenderer(); 131 br.setUseYInterval(true); 132 mDatasets = new TimePeriodValues[NUM_SERIES]; 133 134 TimePeriodValuesCollection tpvc = new YIntervalTimePeriodValuesCollection(1); 135 xyPlot.setDataset(tpvc); 136 xyPlot.setRenderer(br); 137 138 for (int i = 0; i < NUM_SERIES; i++) { 139 br.setSeriesPaint(i, SERIES_COLORS[i]); 140 mDatasets[i] = new TimePeriodValues(SERIES_NAMES[i]); 141 tpvc.addSeries(mDatasets[i]); 142 mTooltips[i] = new ArrayList<String>(); 143 mTooltipGenerator.addToolTipSeries(mTooltips[i]); 144 br.setSeriesToolTipGenerator(i, mTooltipGenerator); 145 } 146 } 147 148 /** 149 * Updates the display with a new event. 150 * 151 * @param event The event 152 * @param logParser The parser providing the event. 153 */ 154 @Override 155 void newEvent(EventContainer event, EventLogParser logParser) { 156 super.newEvent(event, logParser); // Handle sync operation 157 try { 158 if (event.mTag == EVENT_DB_OPERATION) { 159 // 52000 db_operation (name|3),(op_type|1|5),(time|2|3) 160 String tip = event.getValueAsString(0); 161 long endTime = (long) event.sec * 1000L + (event.nsec / 1000000L); 162 int opType = Integer.parseInt(event.getValueAsString(1)); 163 long duration = Long.parseLong(event.getValueAsString(2)); 164 165 if (opType == EVENT_DB_QUERY) { 166 mDatasets[DB_QUERY].add(new SimpleTimePeriod(endTime - duration, endTime), 167 SERIES_YCOORD[DB_QUERY]); 168 mTooltips[DB_QUERY].add(tip); 169 } else if (opType == EVENT_DB_WRITE) { 170 mDatasets[DB_WRITE].add(new SimpleTimePeriod(endTime - duration, endTime), 171 SERIES_YCOORD[DB_WRITE]); 172 mTooltips[DB_WRITE].add(tip); 173 } 174 } else if (event.mTag == EVENT_HTTP_STATS) { 175 // 52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2) 176 String tip = event.getValueAsString(0) + ", tx:" + event.getValueAsString(3) + 177 ", rx: " + event.getValueAsString(4); 178 long endTime = (long) event.sec * 1000L + (event.nsec / 1000000L); 179 long netEndTime = endTime - Long.parseLong(event.getValueAsString(2)); 180 long netStartTime = netEndTime - Long.parseLong(event.getValueAsString(1)); 181 mDatasets[HTTP_NETWORK].add(new SimpleTimePeriod(netStartTime, netEndTime), 182 SERIES_YCOORD[HTTP_NETWORK]); 183 mDatasets[HTTP_PROCESSING].add(new SimpleTimePeriod(netEndTime, endTime), 184 SERIES_YCOORD[HTTP_PROCESSING]); 185 mTooltips[HTTP_NETWORK].add(tip); 186 mTooltips[HTTP_PROCESSING].add(tip); 187 } 188 } catch (NumberFormatException e) { 189 // This can happen when parsing events from froyo+ where the event with id 52000 190 // as a completely different format. For now, skip this event if this happens. 191 } catch (InvalidTypeException e) { 192 } 193 } 194 195 /** 196 * Callback from super.newEvent to process a sync event. 197 * 198 * @param event The sync event 199 * @param startTime Start time (ms) of events 200 * @param stopTime Stop time (ms) of events 201 * @param details Details associated with the event. 202 * @param newEvent True if this event is a new sync event. False if this event 203 * @param syncSource 204 */ 205 @Override 206 void processSyncEvent(EventContainer event, int auth, long startTime, long stopTime, 207 String details, boolean newEvent, int syncSource) { 208 if (newEvent) { 209 mDatasets[auth].add(new SimpleTimePeriod(startTime, stopTime), SERIES_YCOORD[auth]); 210 } 211 } 212 213 /** 214 * Gets display type 215 * 216 * @return display type as an integer 217 */ 218 @Override 219 int getDisplayType() { 220 return DISPLAY_TYPE_SYNC_PERF; 221 } 222 } 223