private void parseStack(String word) { String[] tokens1 = new ColonSplitter(word).split(); if (tokens1.length != 2 && tokens1.length != 3) { throw new IllegalArgumentException("Invalid STACK statement: " + word); } String[] tokens2 = tokens1[1].split("#"); if (tokens2.length != 1 && tokens2.length != 2) { throw new IllegalArgumentException("Invalid STACK statement: " + word); } String name = tokens2[0]; Paint color = tokens2.length == 2 ? Util.parseColor(tokens2[1]) : BLIND_COLOR; String legend = tokens1.length == 3 ? tokens1[2] : null; gdef.stack(name, color, legend); }
public RrdGraphDef getGraphDef( long nowInSeconds, SourceIdentifier sourceIdentifier, boolean showMax) { String absoluteRrdPath = getRrdFile(sourceIdentifier).getAbsolutePath(); RrdGraphDef graphDef = new RrdGraphDef(); graphDef.setColor(RrdGraphConstants.COLOR_CANVAS, new Color(0xcc, 0xcc, 0xcc)); graphDef.setNoMinorGrid(true); graphDef.setShowSignature(false); graphDef.setMinValue(0); graphDef.setAltAutoscaleMax(true); graphDef.setAltYGrid(false); graphDef.setTimeAxis( RrdGraphConstants.HOUR, 1, RrdGraphConstants.HOUR, 6, RrdGraphConstants.DAY, 1, 0, "yyyy-MM-dd"); graphDef.setFilename("-"); graphDef.setImageFormat("PNG"); ConsolFun consolFun; String description; if (showMax) { consolFun = ConsolFun.MAX; description = " (max.)"; } else { consolFun = ConsolFun.AVERAGE; description = " (avg.)"; } graphDef.setVerticalLabel("Events/s" + description); graphDef.datasource( RrdLoggingEventHandler.TRACE, absoluteRrdPath, RrdLoggingEventHandler.TRACE_DS_NAME, consolFun); graphDef.datasource( RrdLoggingEventHandler.DEBUG, absoluteRrdPath, RrdLoggingEventHandler.DEBUG_DS_NAME, consolFun); graphDef.datasource( RrdLoggingEventHandler.INFO, absoluteRrdPath, RrdLoggingEventHandler.INFO_DS_NAME, consolFun); graphDef.datasource( RrdLoggingEventHandler.WARN, absoluteRrdPath, RrdLoggingEventHandler.WARN_DS_NAME, consolFun); graphDef.datasource( RrdLoggingEventHandler.ERROR, absoluteRrdPath, RrdLoggingEventHandler.ERROR_DS_NAME, consolFun); graphDef.area( RrdLoggingEventHandler.TRACE, new Color(0x00, 0x00, 0xff), RrdLoggingEventHandler.TRACE); graphDef.stack( RrdLoggingEventHandler.DEBUG, new Color(0x00, 0xff, 0x00), RrdLoggingEventHandler.DEBUG); graphDef.stack( RrdLoggingEventHandler.INFO, new Color(0xff, 0xff, 0xff), RrdLoggingEventHandler.INFO); graphDef.stack( RrdLoggingEventHandler.WARN, new Color(0xff, 0xff, 0x00), RrdLoggingEventHandler.WARN); graphDef.stack( RrdLoggingEventHandler.ERROR, new Color(0xff, 0x00, 0x00), RrdLoggingEventHandler.ERROR); if (showMax) { graphDef.datasource( RrdLoggingEventHandler.TOTAL, absoluteRrdPath, RrdLoggingEventHandler.TOTAL_DS_NAME, consolFun); graphDef.line(RrdLoggingEventHandler.TOTAL, Color.BLACK, RrdLoggingEventHandler.TOTAL); } graphDef.setAntiAliasing(true); graphDef.setLazy(false); String sourceTitle = createGraphTitle(sourceIdentifier); long before = nowInSeconds - 7 * 24 * 60 * 60; graphDef.setTimeSpan(before, nowInSeconds); graphDef.setTitle(sourceTitle); graphDef.setWidth(graphSize.width); graphDef.setHeight(graphSize.height); return graphDef; }
@Override public byte[] renderUserMethodGraphForUser(long theUserPid, TimeRange theRange) throws IOException { ourLog.info("Rendering user method graph for user {}", theUserPid); myBroadcastSender.requestFlushQueuedStats(); PersUser user = myDao.getUser(theUserPid); Date start = theRange.getNoPresetFrom(); Date end = theRange.getNoPresetTo(); if (theRange.getWithPresetRange() != null) { start = new Date( System.currentTimeMillis() - (theRange.getWithPresetRange().getNumMins() * DateUtils.MILLIS_PER_MINUTE)); end = new Date(); } HashMap<Long, List<Double>> methods = new HashMap<>(); List<Long> timestamps = new ArrayList<>(); InvocationStatsIntervalEnum nextInterval = doWithStatsSupportFindInterval(myConfig.getConfig(), start); Date nextDate = nextInterval.truncate(start); Date nextDateEnd = null; List<PersInvocationMethodUserStats> stats = myDao.getUserStatsWithinTimeRange(user, start, end); Validate.notNull(stats); stats = new ArrayList<>(stats); Collections.sort( stats, new Comparator<PersInvocationMethodUserStats>() { @Override public int compare( PersInvocationMethodUserStats theO1, PersInvocationMethodUserStats theO2) { return theO1.getPk().getStartTime().compareTo(theO2.getPk().getStartTime()); } }); ourLog.debug( "Loaded {} user {} stats for range {} - {}", new Object[] {stats.size(), theUserPid, start, end}); if (stats.size() > 0) { ourLog.debug( "Found stats with range {} - {}", stats.get(0).getPk().getStartTime(), stats.get(stats.size() - 1).getPk().getStartTime()); } ourLog.debug("Looking for stats starting at {}", nextDate); Iterator<PersInvocationMethodUserStats> statIter = stats.iterator(); PersInvocationMethodUserStats nextStat = null; int timesPassed = 0; int foundEntries = 0; double grandTotal = 0; while (nextDate.after(end) == false) { double numMinutes = nextInterval.numMinutes(); nextDateEnd = DateUtils.addMinutes(nextDate, (int) nextInterval.numMinutes()); timestamps.add(nextDate.getTime()); int arrayIndex = timesPassed; timesPassed++; for (List<Double> next : methods.values()) { next.add(ZERO_DOUBLE); } while (nextStat == null || statIter.hasNext()) { if (nextStat == null && statIter.hasNext()) { nextStat = statIter.next(); foundEntries++; } if (nextStat != null && nextStat.getPk().getStartTime().before(nextDateEnd)) { long methodPid = nextStat.getPk().getMethod(); List<Double> newList = methods.get(methodPid); if (newList == null) { newList = new ArrayList<>(); for (int i = 0; i < timesPassed; i++) { newList.add(ZERO_DOUBLE); } methods.put(methodPid, newList); } // TODO: should we have an option to include fails/faults? double total = nextStat.getSuccessInvocationCount(); double minuteTotal = total / numMinutes; grandTotal += minuteTotal; newList.set(arrayIndex, newList.get(arrayIndex) + minuteTotal); nextStat = null; } else { break; } } nextDate = doWithStatsSupportIncrement(nextDate, nextInterval); nextInterval = doWithStatsSupportFindInterval(myConfig.getConfig(), nextDate); nextDate = nextInterval.truncate(nextDate); } ourLog.debug("Found {} entries for {} methods", new Object[] {foundEntries, methods.size()}); // Come up with a good order final Map<Long, PersMethod> pidToMethod = new HashMap<>(); for (long nextPid : methods.keySet()) { PersMethod method = myDao.getServiceVersionMethodByPid(nextPid); if (method != null) { pidToMethod.put(nextPid, method); } else { ourLog.debug("Discarding unknown method: {}", nextPid); } } ArrayList<Long> pids = new ArrayList<>(pidToMethod.keySet()); Collections.sort( pids, new Comparator<Long>() { @Override public int compare(Long theO1, Long theO2) { PersMethod m1 = pidToMethod.get(theO1); PersMethod m2 = pidToMethod.get(theO2); return MethodComparator.INSTANCE.compare(m1, m2); } }); RrdGraphDef graphDef = new RrdGraphDef(); graphDef.setWidth(600); graphDef.setHeight(200); long[] graphTimestamps = new long[timestamps.size()]; for (int i = 0; i < timestamps.size(); i++) { graphTimestamps[i] = timestamps.get(i) / 1000; } graphDef.setTimeSpan(graphTimestamps); graphDef.setVerticalLabel("Calls / Minute"); graphDef.setTextAntiAliasing(true); int longestName = 0; for (PersMethod next : pidToMethod.values()) { longestName = Math.max(longestName, next.getName().length()); } // Draw the methods String previousServiceDesc = null; List<Color> colours = createStackColours(pids.size()); for (int i = 0; i < pids.size(); i++) { Long nextPid = pids.get(i); PersMethod nextMethod = pidToMethod.get(nextPid); List<Double> values = methods.get(nextPid); LinearInterpolator avgPlot = new LinearInterpolator(graphTimestamps, toDoublesFromDoubles(values)); String srcName = "inv" + i; graphDef.datasource(srcName, avgPlot); String methodDesc = nextMethod.getServiceVersion().getService().getServiceId() + " " + nextMethod.getServiceVersion().getVersionId(); if (!StringUtils.equals(previousServiceDesc, methodDesc)) { graphDef.comment(methodDesc + "\\l"); previousServiceDesc = methodDesc; } double sumDoubles = sumDoubles(values); double pct = (sumDoubles / grandTotal); if (i == 0) { graphDef.area( srcName, colours.get(i), " " + StringUtils.rightPad(nextMethod.getName(), longestName)); } else { graphDef.stack( srcName, colours.get(i), " " + StringUtils.rightPad(nextMethod.getName(), longestName)); } graphDef.gprint(srcName, ConsolFun.AVERAGE, "Avg %5.1f "); graphDef.gprint(srcName, ConsolFun.MIN, "Min %5.1f "); graphDef.gprint(srcName, ConsolFun.MAX, "Max %5.1f "); String formattedPct = new DecimalFormat("0.0#%").format(pct); graphDef.comment("Pct: " + formattedPct + "\\l"); } if (pids.size() == 0) { double[] values = new double[timestamps.size()]; for (int j = 0; j < values.length; j++) { values[j] = 0.0; } LinearInterpolator avgPlot = new LinearInterpolator(graphTimestamps, values); String srcName = "inv"; graphDef.datasource(srcName, avgPlot); graphDef.area( srcName, Color.BLACK, StringUtils.rightPad("No activity during this range", 100)); } return render(graphDef); }
@Override public byte[] renderSvcVerUsageGraph(long theServiceVersionPid, TimeRange theRange) throws IOException { ourLog.info("Rendering latency graph for service version {}", theServiceVersionPid); myBroadcastSender.requestFlushQueuedStats(); final List<Double> invCount = new ArrayList<>(); final List<Double> invCountFault = new ArrayList<>(); final List<Double> invCountFail = new ArrayList<>(); final List<Double> invCountSecurityFail = new ArrayList<>(); final List<Long> timestamps = new ArrayList<>(); BasePersServiceVersion svcVer = myServiceRegistry.getServiceVersionByPid(theServiceVersionPid); for (PersMethod nextMethod : svcVer.getMethods()) { doWithStatsByMinute( myConfig.getConfig(), theRange, myStatus, nextMethod, new IWithStats<PersInvocationMethodSvcverStatsPk, PersInvocationMethodSvcverStats>() { @Override public void withStats(int theIndex, PersInvocationMethodSvcverStats theStats) { growToSizeDouble(invCount, theIndex); growToSizeDouble(invCountFault, theIndex); growToSizeDouble(invCountFail, theIndex); growToSizeDouble(invCountSecurityFail, theIndex); growToSizeLong(timestamps, theIndex); double numMinutes = theStats.getPk().getInterval().numMinutes(); invCount.set( theIndex, invCount.get(theIndex) + (theStats.getSuccessInvocationCount() / numMinutes)); invCountFault.set( theIndex, invCountFault.get(theIndex) + (theStats.getFaultInvocationCount() / numMinutes)); invCountFail.set( theIndex, invCountFail.get(theIndex) + (theStats.getFailInvocationCount() / numMinutes)); invCountSecurityFail.set( theIndex, invCountSecurityFail.get(theIndex) + (theStats.getServerSecurityFailures() / numMinutes)); timestamps.set(theIndex, theStats.getPk().getStartTime().getTime()); } }); } RrdGraphDef graphDef = new RrdGraphDef(); graphDef.setWidth(600); graphDef.setHeight(200); graphDef.setTitle( "Usage: " + svcVer.getService().getDomain().getDomainId() + " / " + svcVer.getService().getServiceId() + " / " + svcVer.getVersionId()); long[] timestamps1 = new long[invCount.size()]; for (int i = 0; i < invCount.size(); i++) { timestamps1[i] = timestamps.get(i) / 1000; } graphDef.setTimeSpan(timestamps1); graphDef.setVerticalLabel("Calls / Min"); graphDef.setTextAntiAliasing(true); LinearInterpolator avgPlot = new LinearInterpolator(timestamps1, toDoublesFromDoubles(invCount)); graphDef.datasource("inv", avgPlot); if (hasValues(invCount)) { graphDef.area("inv", Color.decode("#00C000"), StringUtils.rightPad("Successful Calls", 20)); graphDef.gprint("inv", ConsolFun.AVERAGE, "Average %8.1f "); graphDef.gprint("inv", ConsolFun.MIN, "Min %8.1f "); graphDef.gprint("inv", ConsolFun.MAX, "Max %8.1f\\l"); } else { graphDef.area( "inv", Color.decode("#00C000"), StringUtils.rightPad("No Successful calls during this time period\\l", 20)); } if (hasValues(invCountFault)) { LinearInterpolator avgFaultPlot = new LinearInterpolator(timestamps1, toDoublesFromDoubles(invCountFault)); graphDef.datasource("invfault", avgFaultPlot); graphDef.stack("invfault", Color.decode("#6060C0"), StringUtils.rightPad("Faults", 20)); graphDef.gprint("invfault", ConsolFun.AVERAGE, "Average %8.1f "); graphDef.gprint("invfault", ConsolFun.MIN, "Min %8.1f "); graphDef.gprint("invfault", ConsolFun.MAX, "Max %8.1f\\l"); } else { graphDef.comment("No Faults during this time period\\l"); } if (hasValues(invCountFail)) { LinearInterpolator avgFailPlot = new LinearInterpolator(timestamps1, toDoublesFromDoubles(invCountFail)); graphDef.datasource("invfail", avgFailPlot); graphDef.stack("invfail", Color.decode("#F00000"), StringUtils.rightPad("Fails", 20)); graphDef.gprint("invfail", ConsolFun.AVERAGE, "Average %8.1f "); graphDef.gprint("invfail", ConsolFun.MIN, "Min %8.1f "); graphDef.gprint("invfail", ConsolFun.MAX, "Max %8.1f\\l"); } else { graphDef.comment("No Failures during this time period\\l"); } if (hasValues(invCountSecurityFail)) { LinearInterpolator avgSecurityFailPlot = new LinearInterpolator(timestamps1, toDoublesFromDoubles(invCountSecurityFail)); graphDef.datasource("invSecurityFail", avgSecurityFailPlot); graphDef.stack( "invSecurityFail", Color.decode("#F0A000"), StringUtils.rightPad("Security Fails", 20)); graphDef.gprint("invSecurityFail", ConsolFun.AVERAGE, "Average %8.1f "); graphDef.gprint("invSecurityFail", ConsolFun.MIN, "Min %8.1f "); graphDef.gprint("invSecurityFail", ConsolFun.MAX, "Max %8.1f\\l"); } else { graphDef.comment("No Security Failures during this time period\\l"); } return render(graphDef); }
@Override public byte[] renderSvcVerThrottlingGraph(long theServiceVersionPid, TimeRange theRange) throws IOException { ourLog.info("Rendering throttling graph for service version {}", theServiceVersionPid); myBroadcastSender.requestFlushQueuedStats(); final List<Long> throttleAcceptCount = new ArrayList<>(); final List<Long> throttleRejectCount = new ArrayList<>(); final List<Long> timestamps = new ArrayList<>(); BasePersServiceVersion svcVer = myServiceRegistry.getServiceVersionByPid(theServiceVersionPid); for (PersMethod nextMethod : svcVer.getMethods()) { doWithStatsByMinute( myConfig.getConfig(), theRange, myStatus, nextMethod, new IWithStats<PersInvocationMethodSvcverStatsPk, PersInvocationMethodSvcverStats>() { @Override public void withStats(int theIndex, PersInvocationMethodSvcverStats theStats) { growToSizeLong(throttleAcceptCount, theIndex); growToSizeLong(throttleRejectCount, theIndex); growToSizeLong(timestamps, theIndex); double numMinutes = theStats.getPk().getInterval().numMinutes(); throttleAcceptCount.set( theIndex, throttleAcceptCount.get(theIndex) + (int) (theStats.getTotalThrottleAccepts() / numMinutes)); throttleRejectCount.set( theIndex, throttleRejectCount.get(theIndex) + (int) (theStats.getTotalThrottleRejections() / numMinutes)); timestamps.set(theIndex, theStats.getPk().getStartTime().getTime()); } }); } RrdGraphDef graphDef = new RrdGraphDef(); graphDef.setWidth(600); graphDef.setHeight(200); graphDef.setTitle( "Request Throttling: " + svcVer.getService().getDomain().getDomainId() + " / " + svcVer.getService().getServiceId() + " / " + svcVer.getVersionId()); long[] timestamps1 = new long[timestamps.size()]; for (int i = 0; i < timestamps.size(); i++) { timestamps1[i] = timestamps.get(i) / 1000; } graphDef.setTimeSpan(timestamps1); graphDef.setVerticalLabel("Throttled Calls / Min"); graphDef.setTextAntiAliasing(true); LinearInterpolator avgPlot = new LinearInterpolator(timestamps1, toDoublesFromLongs(throttleAcceptCount)); graphDef.datasource("inv", avgPlot); graphDef.area( "inv", Color.GREEN, "Accepted (Throttled but call was allowed to proceed after delay)\\l"); graphDef.gprint("inv", ConsolFun.AVERAGE, "Average %8.1f "); graphDef.gprint("inv", ConsolFun.MIN, "Min %8.1f "); graphDef.gprint("inv", ConsolFun.MAX, "Max %8.1f\\l"); LinearInterpolator avgFaultPlot = new LinearInterpolator(timestamps1, toDoublesFromLongs(throttleRejectCount)); graphDef.datasource("invfault", avgFaultPlot); graphDef.stack("invfault", Color.BLUE, "Rejected (Throttle queue was full or not allowed)\\l"); graphDef.gprint("invfault", ConsolFun.AVERAGE, "Average %8.1f "); graphDef.gprint("invfault", ConsolFun.MIN, "Min %8.1f "); graphDef.gprint("invfault", ConsolFun.MAX, "Max %8.1f\\l"); return render(graphDef); }
public void draw(RrdGraphDef rgd, String sn, Color color, String legend) { rgd.stack(sn, color, legend); };