/* * Copyright 2015 the original author or authors. * @https://github.com/scouter-project/scouter * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package scouter.client.util; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.function.DoubleFunction; import java.util.function.Function; import java.util.function.ToDoubleFunction; import org.csstudio.swt.xygraph.dataprovider.IDataProvider; import org.csstudio.swt.xygraph.dataprovider.ISample; import org.csstudio.swt.xygraph.figures.PlotArea; import org.csstudio.swt.xygraph.figures.Trace; import org.csstudio.swt.xygraph.figures.XYGraph; import org.csstudio.swt.xygraph.undo.ZoomType; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.window.DefaultToolTip; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import scouter.client.Images; import scouter.client.constants.MenuStr; import scouter.client.group.GroupManager; import scouter.client.model.AgentModelThread; import scouter.client.model.AgentObject; import scouter.client.net.INetReader; import scouter.client.net.TcpProxy; import scouter.io.DataInputX; import scouter.lang.TimeTypeEnum; import scouter.lang.counters.CounterConstants; import scouter.lang.pack.MapPack; import scouter.lang.pack.Pack; import scouter.lang.value.ListValue; import scouter.lang.value.Value; import scouter.lang.value.ValueEnum; import scouter.net.RequestCmd; import scouter.util.CastUtil; import scouter.util.DateUtil; import scouter.util.FormatUtil; import scouter.util.LinkedMap; public class ScouterUtil { public static String listToComma(List list) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < list.size(); i++) { sb.append(String.valueOf(list.get(i))); if (i < list.size() - 1) { sb.append(","); } } return sb.toString(); } public static double getRealTotalValue(String counter, List<Pack> result, String mode) { // if (CounterConstants.WAS_ELAPSED_TIME.equalsIgnoreCase(counter)) { // return getRealElapsedAvgValue(result); // } int count = 0; double value = 0.0; for (Pack p : result) { MapPack m = (MapPack) p; ListValue valueLv = m.getList("value"); for (int i = 0; i < valueLv.size(); i++) { value += CastUtil.cdouble(valueLv.get(i)); count++; } } if (count > 0 && "avg".equals(mode)) { value = value / count; } return value; } private static double getRealElapsedAvgValue(List<Pack> result) { double totalValue = 0.0d; double tpsSum = 0.0d; for (Pack p : result) { MapPack m = (MapPack) p; ListValue objHashLv = m.getList("objHash"); ListValue valueLv = m.getList("value"); for (int i = 0; i < objHashLv.size(); i++) { int objHash = (int) objHashLv.getLong(i); double elapsed = CastUtil.cdouble(valueLv.get(i)); AgentObject agent = AgentModelThread.getInstance().getAgentObject(objHash); if (agent == null) { continue; } final List<Double> tpsValue = new ArrayList<Double>(1); TcpProxy tcp = TcpProxy.getTcpProxy(agent.getServerId()); try { MapPack param = new MapPack(); param.put("objHash", objHash); param.put("counter", CounterConstants.WAS_TPS); param.put("timetype", TimeTypeEnum.REALTIME); tcp.process(RequestCmd.COUNTER_REAL_TIME, param, new INetReader() { public void process(DataInputX in) throws IOException { Value v = in.readValue(); if (v != null && v.getValueType() != ValueEnum.NULL) { tpsValue.add(CastUtil.cdouble(v)); } } }); } catch (Exception e) { e.printStackTrace(); } finally { TcpProxy.putTcpProxy(tcp); } double tps = tpsValue.get(0); totalValue += (elapsed * tps); tpsSum += tps; } } if (totalValue == 0 || tpsSum == 0) { return 0; } return totalValue / tpsSum; } public static Map<Long, Double> getLoadTotalMap(String counter, List<Pack> result, String mode, byte timeTypeCode) { // if (CounterConstants.WAS_ELAPSED_TIME.equalsIgnoreCase(counter)) { // return getLoadElapsedAvgMap(result, timeTypeCode); // } long now = TimeUtil.getCurrentTime(); TimedSeries<Integer, Double> sereis = new TimedSeries<Integer, Double>(); for (Pack p : result) { MapPack m = (MapPack) p; int objHash = m.getInt("objHash"); ListValue timeLv = m.getList("time"); ListValue valueLv = m.getList("value"); for (int i = 0; i < timeLv.size(); i++) { long time = CastUtil.clong(timeLv.get(i)); double value = CastUtil.cdouble(valueLv.get(i)); if (time > now) { break; } sereis.add(objHash, time, value); } } Map<Long, Double> tempMap = new HashMap<Long, Double>(); if (sereis.getSeriesCount() > 0) { long stime = sereis.getMinTime(); long etime = sereis.getMaxTime(); boolean isAvg = "avg".equals(mode); while (stime <= etime) { double sum = 0.0d; List<Double> list = sereis.getInTimeList(stime, getKeepTime(timeTypeCode)); for (int i = 0; i < list.size(); i++) { sum += list.get(i); } if (isAvg) { if (list.size() > 0) { tempMap.put(stime, sum / list.size()); } } else { tempMap.put(stime, sum); } stime += TimeTypeEnum.getTime(timeTypeCode); } } return new TreeMap<Long, Double>(tempMap); } public static Map<Long, Double> getLoadMinOrMaxMap(List<Pack> result, String mode, byte timeTypeCode) { long now = TimeUtil.getCurrentTime(); TimedSeries<Integer, Double> sereis = new TimedSeries<Integer, Double>(); for (Pack p : result) { MapPack m = (MapPack) p; int objHash = m.getInt("objHash"); ListValue timeLv = m.getList("time"); ListValue valueLv = m.getList("value"); for (int i = 0; i < timeLv.size(); i++) { long time = CastUtil.clong(timeLv.get(i)); double value = CastUtil.cdouble(valueLv.get(i)); if (time > now) { break; } sereis.add(objHash, time, value); } } Map<Long, Double> tempMap = new HashMap<Long, Double>(); if (sereis.getSeriesCount() > 0) { long stime = sereis.getMinTime(); long etime = sereis.getMaxTime(); boolean isMinMode = "min".equalsIgnoreCase(mode); while (stime <= etime) { double pivot = isMinMode ? Double.MAX_VALUE : Double.MIN_VALUE; List<Double> list = sereis.getInTimeList(stime, getKeepTime(timeTypeCode)); for (int i = 0; i < list.size(); i++) { double v = list.get(i); if (isMinMode && pivot > v) { pivot = v; continue; } if (!isMinMode && v > pivot) { pivot = v; continue; } } if (list.size() > 0) { tempMap.put(stime, pivot); } stime += TimeTypeEnum.getTime(timeTypeCode); } } return new TreeMap<Long, Double>(tempMap); } private static long getKeepTime(byte timeType) { switch (timeType) { case TimeTypeEnum.REALTIME: return 10000; case TimeTypeEnum.ONE_MIN: return DateUtil.MILLIS_PER_MINUTE + 3000; case TimeTypeEnum.FIVE_MIN: return DateUtil.MILLIS_PER_MINUTE * 5 + 3000; case TimeTypeEnum.TEN_MIN: return DateUtil.MILLIS_PER_MINUTE * 10 + 3000; case TimeTypeEnum.HOUR: return DateUtil.MILLIS_PER_HOUR + 3000; default: return 30 * 10000; } } public static void addShowTotalValueListener(FigureCanvas canvas, final XYGraph xyGraph) { final DefaultToolTip toolTip = new DefaultToolTip(canvas, DefaultToolTip.RECREATE, true); toolTip.setFont(new Font(null, "Arial", 10, SWT.BOLD)); toolTip.setBackgroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); canvas.addMouseListener(new MouseListener() { public void mouseUp(MouseEvent e) { toolTip.hide(); } public void mouseDown(MouseEvent e) { double x = xyGraph.primaryXAxis.getPositionValue(e.x, false); double y = xyGraph.primaryYAxis.getPositionValue(e.y, false); if (x < 0 || y < 0) { return; } double minDistance = 30.0d; long time = 0; double value = 0; Trace t = xyGraph.getPlotArea().getTraceList().get(0); if (t == null) { return; } ISample s = getNearestPoint(t.getDataProvider(), x); if (s != null) { int x2 = xyGraph.primaryXAxis.getValuePosition(s.getXValue(), false); int y2 = xyGraph.primaryYAxis.getValuePosition(s.getYValue(), false); double distance = ScouterUtil.getPointDistance(e.x, e.y, x2, y2); if (minDistance > distance) { minDistance = distance; time = (long) s.getXValue(); value = s.getYValue(); } } if (t != null) { toolTip.setText("Time : " + DateUtil.format(time, "HH:mm:ss") + "\nValue : " + FormatUtil.print(value, "#,###.##")); toolTip.show(new Point(e.x, e.y)); } } public void mouseDoubleClick(MouseEvent e) { } }); } public static void collectGroupObjcts(String grpName, Map<Integer, ListValue> serverObjMap) { serverObjMap.clear(); Set<Integer> objHashs = GroupManager.getInstance().getObjectsByGroup(grpName); for (int objHash : objHashs) { AgentObject agentObj = AgentModelThread.getInstance().getAgentObject(objHash); if (agentObj == null) { continue; } int serverId = agentObj.getServerId(); ListValue lv = serverObjMap.get(serverId); if (lv == null) { lv = new ListValue(); serverObjMap.put(serverId, lv); } lv.add(objHash); } } public static String getFullObjName(int objHash) { try { AgentObject agent = AgentModelThread.getInstance().getAgentObject(objHash); String objName = agent.getObjName(); return objName; } catch (Exception e) { } return ""; } public static String getShortObjName(int objHash) { try { AgentObject agent = AgentModelThread.getInstance().getAgentObject(objHash); String objName = agent.getObjName(); if (objName.lastIndexOf("/") > -1) { objName = objName.substring(objName.lastIndexOf("/") + 1, objName.length()); } return objName; } catch (Exception e) { } return ""; } static Set<String> liveMenuSet = new HashSet<String>(); static { liveMenuSet.add(CounterConstants.REAL_TIME); liveMenuSet.add(CounterConstants.TODAY); liveMenuSet.add(CounterConstants.REAL_TIME_ALL); liveMenuSet.add(CounterConstants.REAL_TIME_TOTAL); liveMenuSet.add(CounterConstants.TODAY_ALL); liveMenuSet.add(CounterConstants.TODAY_TOTAL); } public static boolean isLiveMenu(String menu) { boolean result = false; if (liveMenuSet.contains(menu)) { result = true; } return result; } public static String getActionName(String key) { if (CounterConstants.REAL_TIME_ALL.equals(key) || CounterConstants.PAST_TIME_ALL.equals(key)) { return MenuStr.TIME_ALL; } else if (CounterConstants.REAL_TIME_TOTAL.equals(key) || CounterConstants.PAST_TIME_TOTAL.equals(key)) { return MenuStr.TIME_TOTAL; } else if (CounterConstants.TODAY_ALL.equals(key) || CounterConstants.PAST_DATE_ALL.equals(key)) { return MenuStr.DAILY_ALL; } else if (CounterConstants.TODAY_TOTAL.equals(key) || CounterConstants.PAST_DATE_TOTAL.equals(key)) { return MenuStr.DAILY_TOTAL; } else { return ""; } } public static ImageDescriptor getActionIconName(String key) { if (CounterConstants.REAL_TIME_ALL.equals(key) || CounterConstants.TODAY_ALL.equals(key)) { return ImageUtil.getImageDescriptor(Images.all); } else if (CounterConstants.REAL_TIME_TOTAL.equals(key) || CounterConstants.TODAY_TOTAL.equals(key)) { return ImageUtil.getImageDescriptor(Images.sum); } else if (CounterConstants.PAST_TIME_ALL.equals(key) || CounterConstants.PAST_DATE_ALL.equals(key)) { return ImageUtil.getImageDescriptor(Images.all); } else if (CounterConstants.PAST_TIME_TOTAL.equals(key) || CounterConstants.PAST_DATE_TOTAL.equals(key)) { return ImageUtil.getImageDescriptor(Images.sum); } else { return null; } } public static String mapPackToTableString(MapPack m) { if (m == null) { return null; } StringBuilder sb = new StringBuilder(); ArrayList<String> keyList = new ArrayList<String>(); HashMap<Integer, Integer> maxLenMap = new HashMap<Integer, Integer>(); LinkedMap<Integer, ArrayList<String>> valueMap = new LinkedMap<Integer, ArrayList<String>>(); int width = 1; Iterator<String> itr = m.keys(); int index = 0; while (itr.hasNext()) { String key = itr.next(); Value v = m.get(key); int maxLen = key.length(); if (v instanceof ListValue) { ListValue lv = (ListValue) v; for (int i = 0; i < lv.size(); i++) { String s = lv.get(i).toString(); if (s.length() > maxLen) { maxLen = s.length(); } ArrayList<String> list = valueMap.get(i); if (list == null) { list = new ArrayList<String>(); valueMap.put(i, list); } list.add(s); } width += (maxLen + 3); maxLenMap.put(index, maxLen); keyList.add(key); index++; } } if (keyList.size() > 0) { // 1. draw header sb.append("\n+"); for (int i = 0; i < width - 2; i++) { sb.append("-"); } sb.append("+\n"); sb.append("|"); for (int i = 0; i < keyList.size(); i++) { int maxLen = maxLenMap.get(i); String key = keyList.get(i); sb.append(" " + key); int gap = maxLen - key.length(); while (gap > 0) { sb.append(" "); gap--; } sb.append(" |"); } sb.append("\n"); for (int i = 0; i < width; i++) { sb.append("-"); } sb.append("\n"); // 2. draw content while (valueMap.size() > 0) { ArrayList<String> list = valueMap.removeFirst(); sb.append("|"); for (int i = 0; i < list.size(); i++) { int maxLen = maxLenMap.get(i); String s = list.get(i); sb.append(" " + s); int gap = maxLen - s.length(); while (gap > 0) { sb.append(" "); gap--; } sb.append(" |"); } sb.append("\n"); if (valueMap.size() == 0) { sb.append("+"); for (int i = 0; i < width - 2; i++) { sb.append("-"); } sb.append("+\n"); } else { for (int i = 0; i < width; i++) { sb.append("-"); } sb.append("\n"); } } } return sb.toString(); } public static double getNearestValue(IDataProvider provider, double time) { int high = provider.getSize() - 1; int low = 0; while (true) { int mid = (high + low) / 2; ISample s = provider.getSample(mid); double x = s.getXValue(); if (x == time) { return s.getYValue(); } else { if (x > time) { high = mid; } else { low = mid; } if ((high - low) <= 1) { ISample highSample = provider.getSample(high); ISample lowSample = provider.getSample(low); if (highSample == null && lowSample == null) { return 0.0d; } if (highSample == null) { return lowSample.getYValue(); } if (lowSample == null) { return highSample.getYValue(); } double highGap = highSample.getXValue() - time; double lowGqp = time - lowSample.getXValue(); if (highGap < lowGqp) { return highSample.getYValue(); } else { return lowSample.getYValue(); } } } } } public static ISample getNearestPoint(IDataProvider provider, double time) { int high = provider.getSize() - 1; int low = 0; while (high >= low) { int mid = (high + low) / 2; ISample s = provider.getSample(mid); double x = s.getXValue(); if (x == time) { return s; } else { if (x > time) { high = mid; } else { low = mid; } if ((high - low) <= 1) { ISample highSample = provider.getSample(high); ISample lowSample = provider.getSample(low); if (highSample == null && lowSample == null) { return null; } if (highSample == null) { return lowSample; } if (lowSample == null) { return highSample; } double highGap = highSample.getXValue() - time; double lowGqp = time - lowSample.getXValue(); if (highGap < lowGqp) { return highSample; } else { return lowSample; } } } } return null; } public static String humanReadableByteCount(long bytes, boolean si) { int unit = 1024; if (bytes < unit) return bytes + " B"; int exp = (int) (Math.log(bytes) / Math.log(unit)); String pre = "KMGTPE".charAt(exp - 1) + (si ? "" : "i"); return String.format("%.1f %s", bytes / Math.pow(unit, exp), pre); } public static String humanReadableByteCount(double bytes, boolean si) { int unit = 1024; if (bytes < unit) return bytes + " B"; int exp = (int) (Math.log(bytes) / Math.log(unit)); String pre = "KMGTPE".charAt(exp - 1) + (si ? "" : "i"); return String.format("%.1f %s", bytes / Math.pow(unit, exp), pre); } public static void addHorizontalRangeListener(PlotArea plotArea, PropertyChangeListener listener, boolean withZoom) { plotArea.setZoomType(ZoomType.HORIZONTAL_ZOOM); plotArea.enableZoom(withZoom); plotArea.addPropertyChangeListener("horizontal_range", listener); } public static double getPointDistance(double x1, double y1, double x2, double y2) { return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); } public static DoubleFunction<Comparator<Trace>> comparatorByTime = (time) -> (t1, t2) -> { ISample sample1 = ScouterUtil.getNearestPoint(t1.getDataProvider(), time); ISample sample2 = ScouterUtil.getNearestPoint(t2.getDataProvider(), time); return Double.compare(sample2.getYValue(), sample1.getYValue()); }; public static ToDoubleFunction<Trace> nearestPointYValueFunc(double time) { return t -> ScouterUtil.getNearestValue(t.getDataProvider(), time); } }