1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package ohos.devtools.views.trace.component; 17 18 import com.intellij.ui.components.JBLabel; 19 import com.intellij.ui.components.JBPanel; 20 import com.intellij.ui.components.JBScrollPane; 21 import com.intellij.ui.table.JBTable; 22 import net.miginfocom.swing.MigLayout; 23 import ohos.devtools.views.trace.Sql; 24 import ohos.devtools.views.trace.bean.Counter; 25 import ohos.devtools.views.trace.bean.TabCounterBean; 26 import ohos.devtools.views.trace.util.ComparatorUtils; 27 import ohos.devtools.views.trace.util.Db; 28 import ohos.devtools.views.trace.util.Utils; 29 30 import javax.swing.SwingUtilities; 31 import javax.swing.table.TableRowSorter; 32 import java.math.BigDecimal; 33 import java.math.RoundingMode; 34 import java.util.ArrayList; 35 import java.util.Comparator; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Objects; 39 import java.util.Set; 40 import java.util.concurrent.CompletableFuture; 41 import java.util.stream.Collectors; 42 43 /** 44 * TabCounter 45 * 46 * @since 2021/5/12 16:34 47 */ 48 public class TabCounter extends JBPanel { 49 private JBTable table = new JBTable(); 50 private FTableModel<TabCounterBean> model = new FTableModel(); 51 private List<FTableModel.Column<TabCounterBean>> columns; 52 private JBLabel selectRangeLabel = new JBLabel("selected range:"); 53 private TableRowSorter<FTableModel> tableRowSorter; 54 private long leftNs; 55 private long rightNs; 56 57 /** 58 * structure function 59 */ TabCounter()60 public TabCounter() { 61 setLayout(new MigLayout("insets 0", "[grow,fill][]", "[15!,fill][grow,fill]")); 62 setFocusable(true); 63 add(selectRangeLabel, "skip 1,wrap"); 64 initColumns(); 65 model.setColumns(columns); 66 table.setModel(model); 67 JBScrollPane jsp = new JBScrollPane(); 68 jsp.setViewportView(table); 69 add(jsp, "span"); 70 tableRowSorter = new TableRowSorter(model); 71 table.setRowSorter(tableRowSorter); 72 } 73 74 /** 75 * set TabData 76 * 77 * @param trackIds trackIds 78 * @param leftNs leftNs 79 * @param rightNs rightNs 80 */ loadTabData(final List<Integer> trackIds, long leftNs, long rightNs)81 public void loadTabData(final List<Integer> trackIds, long leftNs, long rightNs) { 82 this.leftNs = leftNs; 83 this.rightNs = rightNs; 84 selectRangeLabel.setText("Selected range:" + (rightNs - leftNs) / 1000000.0 + "ms"); 85 if (trackIds != null && !trackIds.isEmpty()) { 86 StringBuffer buffer = new StringBuffer(); 87 for (int index = 0, size = trackIds.size(); index < size; index++) { 88 buffer.append(trackIds.get(index)); 89 if (index < size - 1) { 90 buffer.append(","); 91 } 92 } 93 loadTabData2(buffer); 94 } 95 } 96 loadTabData2(StringBuffer buffer)97 private void loadTabData2(StringBuffer buffer) { 98 CompletableFuture.runAsync(() -> { 99 List<Counter> result = new ArrayList<>() { 100 }; 101 Db.getInstance().query(Sql.SYS_GET_TAB_COUNTERS, result, buffer.toString(), rightNs); 102 Map<Integer, List<Counter>> collect = result.stream().collect(Collectors.groupingBy(Counter::getTrackId)); 103 Set<Integer> keys = collect.keySet(); 104 List<TabCounterBean> source = new ArrayList<>(); 105 double range = (rightNs - leftNs) * 1.0 / 1000000000; 106 int count = 0; 107 for (Integer key : keys) { 108 List<Counter> counters = collect.get(key); 109 List<Counter> list = 110 counters.stream().filter(counter -> counter.getStartTime() > leftNs).collect(Collectors.toList()); 111 if (list.size() > 0) { 112 int index = counters.indexOf(list.get(0)); 113 if (index > 0) { 114 list.add(0, counters.get(index - 1)); 115 } 116 } else { 117 list.add(counters.get(counters.size() - 1)); 118 } 119 TabCounterBean tabCounter = getTabCounter(list, range); 120 count += tabCounter.getCount(); 121 source.add(tabCounter); 122 } 123 TabCounterBean tcb = new TabCounterBean(); 124 tcb.setCount(count); 125 source.add(0, tcb); 126 SwingUtilities.invokeLater(() -> { 127 if (result != null && result.size() > 0) { 128 // set row sorter 129 TabCounterBean cb = source.get(0); 130 for (int index = 0; index < 9; index++) { 131 if (index == 4) { 132 tableRowSorter.setComparator(index, ComparatorUtils.generateComparator(cb.getCount() + "")); 133 } else { 134 tableRowSorter.setComparator(index, ComparatorUtils.generateComparator("")); 135 } 136 } 137 } 138 model.setDataSource(source); 139 model.fireTableDataChanged(); 140 }); 141 }, Utils.getPool()).whenComplete((unused, throwable) -> { 142 if (Objects.nonNull(throwable)) { 143 throwable.printStackTrace(); 144 } 145 }); 146 } 147 getTabCounter(List<Counter> list, double range)148 private TabCounterBean getTabCounter(List<Counter> list, double range) { 149 TabCounterBean bean = new TabCounterBean(); 150 if (list.size() > 0) { 151 Counter first = list.get(0); 152 bean.setTrackId(first.getTrackId()); 153 bean.setName(first.getName()); 154 bean.setFirstValue(first.getValue()); 155 bean.setCount(list.size()); 156 bean.setLastValue(list.get(list.size() - 1).getValue()); 157 // delta value = (last value - first value) 158 bean.setDeltaValue(bean.getLastValue() - bean.getFirstValue()); 159 // rate = (last value - first value) / time range 160 bean.setRate(bean.getDeltaValue() / range); 161 List<Counter> collect = 162 list.stream().sorted(Comparator.comparing(Counter::getValue)).collect(Collectors.toList()); 163 bean.setMinValue(collect.get(0).getValue()); 164 bean.setMaxValue(collect.get(collect.size() - 1).getValue()); 165 // Calculate the weighted average value 166 double weightAvg = 0.0D; 167 long timeRange = rightNs - leftNs; 168 for (int index = 0, size = list.size(); index < size; index++) { 169 long start = index == 0 ? leftNs : list.get(index).getStartTime(); 170 long end = index == size - 1 ? rightNs : list.get(index + 1).getStartTime(); 171 weightAvg += list.get(index).getValue() * ((end - start) * 1.0 / timeRange); 172 } 173 BigDecimal decimal = BigDecimal.valueOf(weightAvg); 174 weightAvg = decimal.setScale(2, RoundingMode.HALF_UP).doubleValue(); 175 bean.setWeightAvgValue(weightAvg); 176 } 177 return bean; 178 } 179 initColumns()180 private void initColumns() { 181 columns = new ArrayList<>(); 182 columns.add(new FTableModel.Column<>("Name", item -> item.getName() == null ? "" : item.getName())); 183 columns.add( 184 new FTableModel.Column<>("Delta value", item -> item.getDeltaValue() == null ? "" : item.getDeltaValue())); 185 columns.add(new FTableModel.Column<>("Rate /s", item -> item.getRate() == null ? "" : item.getRate())); 186 columns.add(new FTableModel.Column<>("Weight avg value", 187 item -> item.getWeightAvgValue() == null ? "" : item.getWeightAvgValue())); 188 columns.add(new FTableModel.Column<>("Count", item -> item.getCount() == null ? "" : item.getCount())); 189 columns.add( 190 new FTableModel.Column<>("First value", item -> item.getFirstValue() == null ? "" : item.getFirstValue())); 191 columns.add( 192 new FTableModel.Column<>("Last value", item -> item.getLastValue() == null ? "" : item.getLastValue())); 193 columns 194 .add(new FTableModel.Column<>("Min value", item -> item.getMinValue() == null ? "" : item.getMinValue())); 195 columns 196 .add(new FTableModel.Column<>("Max value", item -> item.getMaxValue() == null ? "" : item.getMaxValue())); 197 } 198 199 } 200