Example #1
0
 public RrdGraphDef getEmptyGraphDef() {
   RrdGraphDef retValue = new RrdGraphDef();
   if (!Double.isNaN(lowerLimit)) retValue.setMinValue(lowerLimit);
   if (!Double.isNaN(upperLimit)) retValue.setMaxValue(upperLimit);
   if (verticalLabel != null) retValue.setVerticalLabel(verticalLabel);
   if (this.siUnit) retValue.setBase(1000);
   else retValue.setBase(1024);
   if (unitExponent != null) {
     retValue.setUnitsExponent(unitExponent);
   }
   retValue.setLogarithmic(logarithmic);
   retValue.setPoolUsed(true);
   retValue.setAntiAliasing(true);
   retValue.setTextAntiAliasing(true);
   retValue.setImageFormat("PNG");
   retValue.setWidth(getWidth());
   retValue.setHeight(getHeight());
   return retValue;
 }
Example #2
0
  Object execute() throws IOException {
    gdef = new RrdGraphDef();

    // OPTIONS

    // START, END
    String t1 = getOptionValue("s", "start", DEFAULT_START),
        t2 = getOptionValue("e", "end", DEFAULT_END);
    gdef.setTimeSpan(Util.getTimestamps(t1, t2));
    // X-GRID
    parseXGrid(getOptionValue("x", "x-grid"));
    // Y-GRID
    parseYGrid(getOptionValue("y", "y-grid"));
    // ALT-Y-GRID
    gdef.setAltYGrid(getBooleanOption("Y", "alt-y-grid"));
    // NO_MINOR
    gdef.setNoMinorGrid(getBooleanOption(null, "no-minor"));
    // ALT-Y-MRTG
    gdef.setAltYMrtg(getBooleanOption("R", "alt-y-mrtg"));
    // ALT-AUTOSCALE
    gdef.setAltAutoscale(getBooleanOption("A", "alt-autoscale"));
    // ALT-AUTOSCALE-MAX
    gdef.setAltAutoscaleMax(getBooleanOption("M", "alt-autoscale-max"));
    // UNITS-EXPONENT
    String opt = getOptionValue("X", "units-exponent");
    if (opt != null) {
      gdef.setUnitsExponent(parseInt(opt));
    }
    // UNITS-LENGTH
    opt = getOptionValue("L", "units-length");
    if (opt != null) {
      gdef.setUnitsLength(parseInt(opt));
    }
    // VERTICAL LABEL
    opt = getOptionValue("v", "vertical-label");
    if (opt != null) {
      gdef.setVerticalLabel(opt);
    }
    // WIDTH
    opt = getOptionValue("w", "width");
    if (opt != null) {
      gdef.setWidth(parseInt(opt));
    }
    // HEIGHT
    opt = getOptionValue("h", "height");
    if (opt != null) {
      gdef.setHeight(parseInt(opt));
    }
    // INTERLACED
    gdef.setInterlaced(getBooleanOption("i", "interlaced"));
    // IMGINFO
    opt = getOptionValue("f", "imginfo");
    if (opt != null) {
      gdef.setImageInfo(opt);
    }
    // IMGFORMAT
    opt = getOptionValue("a", "imgformat");
    if (opt != null) {
      gdef.setImageFormat(opt);
    }
    // BACKGROUND
    opt = getOptionValue("B", "background");
    if (opt != null) {
      gdef.setBackgroundImage(opt);
    }
    // OVERLAY
    opt = getOptionValue("O", "overlay");
    if (opt != null) {
      gdef.setOverlayImage(opt);
    }
    // UNIT
    opt = getOptionValue("U", "unit");
    if (opt != null) {
      gdef.setUnit(opt);
    }
    // LAZY
    gdef.setLazy(getBooleanOption("z", "lazy"));
    // UPPER-LIMIT
    opt = getOptionValue("u", "upper-limit");
    if (opt != null) {
      gdef.setMaxValue(parseDouble(opt));
    }
    // LOWER-LIMIT
    opt = getOptionValue("l", "lower-limit");
    if (opt != null) {
      gdef.setMinValue(parseDouble(opt));
    }
    // RIGID
    gdef.setRigid(getBooleanOption("r", "rigid"));
    // BASE
    opt = getOptionValue("b", "base");
    if (opt != null) {
      gdef.setBase(parseDouble(opt));
    }
    // LOGARITHMIC
    gdef.setLogarithmic(getBooleanOption("o", "logarithmic"));
    // COLORS
    parseColors(getMultipleOptionValues("c", "color"));
    // NO-LEGEND
    gdef.setNoLegend(getBooleanOption("g", "no-legend"));
    // ONLY_GRAPH
    gdef.setOnlyGraph(getBooleanOption("j", "only-graph"));
    // FORCE-RULES-LEGEND
    gdef.setForceRulesLegend(getBooleanOption("F", "force-rules-legend"));
    // TITLE
    opt = getOptionValue("t", "title");
    if (opt != null) {
      gdef.setTitle(opt);
    }
    // STEP
    opt = getOptionValue("S", "step");
    if (opt != null) {
      gdef.setStep(parseLong(opt));
    }

    // NON-OPTIONS

    String[] words = getRemainingWords();
    // the first word must be a filename
    if (words.length < 2) {
      throw new IllegalArgumentException("Image filename must be specified");
    }
    gdef.setFilename(words[1]);
    // parse remaining words, in no particular order
    for (int i = 2; i < words.length; i++) {
      if (words[i].startsWith("DEF:")) {
        parseDef(words[i]);
      } else if (words[i].startsWith("CDEF:")) {
        parseCDef(words[i]);
      } else if (words[i].startsWith("PRINT:")) {
        parsePrint(words[i]);
      } else if (words[i].startsWith("GPRINT:")) {
        parseGPrint(words[i]);
      } else if (words[i].startsWith("COMMENT:")) {
        parseComment(words[i]);
      } else if (words[i].startsWith("HRULE:")) {
        parseHRule(words[i]);
      } else if (words[i].startsWith("VRULE:")) {
        parseVRule(words[i]);
      } else if (words[i].startsWith("LINE1:")
          || words[i].startsWith("LINE2:")
          || words[i].startsWith("LINE3:")) {
        parseLine(words[i]);
      } else if (words[i].startsWith("AREA:")) {
        parseArea(words[i]);
      } else if (words[i].startsWith("STACK:")) {
        parseStack(words[i]);
      } else {
        throw new IllegalArgumentException("Unexpected GRAPH token encountered: " + words[i]);
      }
    }
    // create diagram finally
    RrdGraphInfo info = new RrdGraph(gdef).getRrdGraphInfo();
    if (info.getFilename().equals(RrdGraphConstants.IN_MEMORY_IMAGE)) {
      println(new String(info.getBytes()));
    } else {
      println(info.getWidth() + "x" + info.getHeight());
      String[] plines = info.getPrintLines();
      for (String pline : plines) {
        println(pline);
      }
      if (info.getImgInfo() != null && info.getImgInfo().length() > 0) {
        println(info.getImgInfo());
      }
    }
    return info;
  }
Example #3
0
  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);
  }
  @Override
  public byte[] renderSvcVerPayloadSizeGraph(long theServiceVersionPid, TimeRange theRange)
      throws IOException {
    ourLog.info("Rendering payload size graph for service version {}", theServiceVersionPid);

    myBroadcastSender.requestFlushQueuedStats();

    final List<Integer> invCount = new ArrayList<>();
    final List<Long> totalSuccessReqBytes = new ArrayList<>();
    final List<Long> totalSuccessRespBytes = 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) {
              growToSizeInt(invCount, theIndex);
              growToSizeLong(totalSuccessRespBytes, theIndex);
              growToSizeLong(totalSuccessReqBytes, theIndex);
              growToSizeLong(timestamps, theIndex);

              totalSuccessReqBytes.set(
                  theIndex,
                  addToLong(
                      totalSuccessReqBytes.get(theIndex),
                      theStats.getSuccessRequestMessageBytes()));
              totalSuccessRespBytes.set(
                  theIndex,
                  addToLong(
                      totalSuccessRespBytes.get(theIndex),
                      theStats.getSuccessResponseMessageBytes()));
              invCount.set(
                  theIndex, addToInt(invCount.get(theIndex), theStats.getSuccessInvocationCount()));
              timestamps.set(theIndex, theStats.getPk().getStartTime().getTime());
            }
          });
    }

    double[] avgSuccessReqSize = new double[invCount.size()];
    double[] avgSuccessRespSize = new double[invCount.size()];
    for (int i = 0; i < invCount.size(); i++) {
      avgSuccessReqSize[i] =
          invCount.get(i) == 0 ? 0 : totalSuccessReqBytes.get(i) / invCount.get(i);
      avgSuccessRespSize[i] =
          invCount.get(i) == 0 ? 0 : totalSuccessRespBytes.get(i) / invCount.get(i);
    }

    RrdGraphDef graphDef = new RrdGraphDef();
    graphDef.setWidth(600);
    graphDef.setHeight(200);
    graphDef.setTitle(
        "Message Payload Size: "
            + svcVer.getService().getDomain().getDomainId()
            + " / "
            + svcVer.getService().getServiceId()
            + " / "
            + svcVer.getVersionId());

    long[] timestamps1 = new long[invCount.size()];

    double prevReq = 0.0;
    double prevResp = 0.0;
    for (int i = 0; i < invCount.size(); i++) {
      timestamps1[i] = timestamps.get(i) / 1000;
      prevReq = avgSuccessReqSize[i] > 0 ? avgSuccessReqSize[i] : prevReq;
      avgSuccessReqSize[i] = prevReq;
      prevResp = avgSuccessRespSize[i] > 0 ? avgSuccessRespSize[i] : prevResp;
      avgSuccessRespSize[i] = prevResp;
    }

    for (int i = 0; i < avgSuccessReqSize.length; i++) {}

    graphDef.setTimeSpan(timestamps1);
    graphDef.setVerticalLabel("Bytes / Message");
    graphDef.setTextAntiAliasing(true);

    LinearInterpolator reqPlot = new LinearInterpolator(timestamps1, avgSuccessReqSize);
    graphDef.datasource("req", reqPlot);
    graphDef.line("req", Color.RED, "Requests  ", 2.0f);
    graphDef.gprint("req", ConsolFun.AVERAGE, "Average Size %8.1f   ");
    graphDef.gprint("req", ConsolFun.MIN, "Min %8.1f   ");
    graphDef.gprint("req", ConsolFun.MAX, "Max %8.1f\\l");

    LinearInterpolator respPlot = new LinearInterpolator(timestamps1, avgSuccessRespSize);
    graphDef.datasource("resp", respPlot);
    graphDef.line("resp", Color.GREEN, "Responses ", 2.0f);
    graphDef.gprint("resp", ConsolFun.AVERAGE, "Average Size %8.1f   ");
    graphDef.gprint("resp", ConsolFun.MIN, "Min %8.1f   ");
    graphDef.gprint("resp", ConsolFun.MAX, "Max %8.1f\\l");

    return render(graphDef);
  }
  @Override
  public byte[] renderSvcVerLatencyMethodGraph(
      long theSvcVerPid, TimeRange theRange, boolean theIndividualMethod) throws IOException {
    ourLog.info("Rendering user method graph for Service Version {}", theSvcVerPid);

    myBroadcastSender.requestFlushQueuedStats();

    BasePersServiceVersion svcVer = myServiceRegistry.getServiceVersionByPid(theSvcVerPid);

    /*
     * Init the graph
     */

    RrdGraphDef graphDef = new RrdGraphDef();
    graphDef.setWidth(600);
    graphDef.setHeight(200);

    graphDef.setTitle(
        "Backing Service Latency: "
            + svcVer.getService().getDomain().getDomainId()
            + " / "
            + svcVer.getService().getServiceId()
            + " / "
            + svcVer.getVersionId());
    graphDef.setVerticalLabel("Milliseconds / Call");
    graphDef.setTextAntiAliasing(true);
    graphDef.setMinValue(0.0);

    /*
     * Loop through each method and load the latency stats
     */
    final List<String> names = new ArrayList<>();
    final List<List<Long>> latencyLists = new ArrayList<>();
    final List<Long> timestamps = new ArrayList<>();

    for (PersMethod nextMethod : svcVer.getMethods()) {
      if (BaseDtoServiceVersion.METHOD_NAME_UNKNOWN.equals(nextMethod.getName())) {
        continue;
      }

      final List<Long> latencyMin;
      if (theIndividualMethod) {
        names.add(nextMethod.getName());
        latencyMin = new ArrayList<>();
        latencyLists.add(latencyMin);
      } else {
        if (names.isEmpty()) {
          names.add("All Methods");
          latencyMin = new ArrayList<>();
          latencyLists.add(latencyMin);
        } else {
          latencyMin = latencyLists.get(0);
        }
      }

      doWithStatsByMinute(
          myConfig.getConfig(),
          theRange,
          myStatus,
          nextMethod,
          new IWithStats<PersInvocationMethodSvcverStatsPk, PersInvocationMethodSvcverStats>() {
            @Override
            public void withStats(int theIndex, PersInvocationMethodSvcverStats theStats) {
              growToSizeLong(latencyMin, theIndex);
              growToSizeLong(timestamps, theIndex);
              long latency =
                  theStats.getSuccessInvocationTotalTime() > 0
                      ? theStats.getSuccessInvocationTotalTime()
                          / theStats.getSuccessInvocationCount()
                      : 0;
              latencyMin.set(theIndex, addToLong(latencyMin.get(theIndex), latency));
              timestamps.set(theIndex, theStats.getPk().getStartTime().getTime());
            }
          });
    }

    /*
     * Set time span
     */
    long[] graphTimestamps = new long[timestamps.size()];
    for (int i = 0; i < timestamps.size(); i++) {
      graphTimestamps[i] = timestamps.get(i) / 1000;
    }
    graphDef.setTimeSpan(graphTimestamps);

    /*
     * Figure out the longest name
     */
    int longestName = 0;
    for (String next : names) {
      longestName = Math.max(longestName, next.length());
    }

    /*
     * Straighten
     */
    int numWithValues = 0;
    List<Boolean> hasValuesList = new ArrayList<>();
    for (List<Long> nextList : latencyLists) {
      boolean hasValues = false;
      for (int i = 0; i < nextList.size(); i++) {
        long l = nextList.get(i);
        if (l == 0) {
          if (i > 0 && nextList.get(i - 1) > 0) {
            nextList.set(i, nextList.get(i - 1));
          }
        } else {
          hasValues = true;
        }
      }
      hasValuesList.add(hasValues);
      if (hasValues) {
        numWithValues++;
      }
    }

    /*
     * Figure out colours
     */
    List<Color> colours = new ArrayList<>();
    int colourIndex = 0;
    for (int i = 0; i < hasValuesList.size(); i++) {
      if (hasValuesList.get(i)) {
        colours.add(createStackColour(numWithValues, colourIndex++));
      } else {
        colours.add(Color.black);
      }
    }

    /*
     * Add the lines to the graph
     */

    for (int i = 0; i < names.size(); i++) {
      String name = names.get(i);
      List<Long> latencyMin = latencyLists.get(i);

      Plottable avgPlot = new LinearInterpolator(graphTimestamps, toDoublesFromLongs(latencyMin));
      String srcName = "inv" + i;
      graphDef.datasource(srcName, avgPlot);

      graphDef.line(srcName, colours.get(i), " " + StringUtils.rightPad(name, longestName), 2);
      if (hasValuesList.get(i)) {
        graphDef.gprint(srcName, ConsolFun.AVERAGE, "Avg %5.1f ");
        graphDef.gprint(srcName, ConsolFun.MIN, "Min %5.1f ");
        graphDef.gprint(srcName, ConsolFun.MAX, "Max %5.1f \\l");
      } else {
        graphDef.comment("No Invocations During This Period\\l");
      }
    }

    return render(graphDef);
  }
Example #9
0
  @Override
  public byte[] createGraph(
      String metricName,
      String rrdFilename,
      long startTime,
      long endTime,
      String verticalAxisLabel,
      String title)
      throws IOException, MetricsGraphException {
    // Create RRD DB in read-only mode for the specified RRD file
    RrdDb rrdDb = new RrdDb(rrdFilename, true);

    // Extract the data source (should always only be one data source per RRD file - otherwise we
    // have a problem)
    if (rrdDb.getDsCount() != 1) {
      throw new MetricsGraphException(
          "Only one data source per RRD file is supported - RRD file "
              + rrdFilename
              + " has "
              + rrdDb.getDsCount()
              + " data sources.");
    }

    // Define attributes of the graph to be created for this metric
    RrdGraphDef graphDef = new RrdGraphDef();
    graphDef.setTimeSpan(startTime, endTime);
    graphDef.setImageFormat("PNG");
    graphDef.setShowSignature(false);
    graphDef.setStep(60);
    graphDef.setVerticalLabel(verticalAxisLabel);
    graphDef.setHeight(500);
    graphDef.setWidth(1000);
    graphDef.setTitle(title);

    DsType dataSourceType = rrdDb.getDatasource(0).getType();

    // Determine if the Data Source for this RRD file is a COUNTER or GAUGE
    // (Need to know this because COUNTER data is averaged across samples and the vertical axis of
    // the
    // generated graph by default will show data per rrdStep interval)
    if (dataSourceType == DsType.COUNTER) {
      // If we ever needed to adjust the metric's data collected by RRD by the archive step
      // (which is the rrdStep * archiveSampleCount) this is how to do it.
      //            FetchRequest fetchRequest = rrdDb.createFetchRequest(ConsolFun.AVERAGE,
      // startTime, endTime);
      //            Archive archive = rrdDb.findMatchingArchive(fetchRequest);
      //            long archiveStep = archive.getArcStep();
      //            LOGGER.debug("archiveStep = " + archiveStep);
      long rrdStep = rrdDb.getRrdDef().getStep();
      LOGGER.debug("rrdStep = " + rrdStep);

      // Still TBD if we want to graph the AVERAGE data on the same graph
      //            graphDef.comment(metricName + "   ");
      //            graphDef.datasource("myAverage", rrdFilename, "data", ConsolFun.AVERAGE);
      //            graphDef.datasource("realAverage", "myAverage," + rrdStep + ",*");
      //            graphDef.line("realAverage", Color.GREEN, "Average", 2);

      // Multiplied by the rrdStep to "undo" the automatic averaging that RRD does
      // when it collects TOTAL data - we want the actual totals for the step, not
      // the average of the totals.
      graphDef.datasource("myTotal", rrdFilename, "data", ConsolFun.TOTAL);
      graphDef.datasource("realTotal", "myTotal," + rrdStep + ",*");
      graphDef.line("realTotal", Color.BLUE, convertCamelCase(metricName), 2);

      // Add some spacing between the graph and the summary stats shown beneath the graph
      graphDef.comment("\\s");
      graphDef.comment("\\s");
      graphDef.comment("\\c");

      // Average, Min, and Max over all of the TOTAL data - displayed at bottom of the graph
      graphDef.gprint("realTotal", ConsolFun.AVERAGE, "Average = %.3f%s");
      graphDef.gprint("realTotal", ConsolFun.MIN, "Min = %.3f%s");
      graphDef.gprint("realTotal", ConsolFun.MAX, "Max = %.3f%s");
    } else if (dataSourceType == DsType.GAUGE) {
      graphDef.datasource("myAverage", rrdFilename, "data", ConsolFun.AVERAGE);
      graphDef.line("myAverage", Color.RED, convertCamelCase(metricName), 2);

      // Add some spacing between the graph and the summary stats shown beneath the graph
      graphDef.comment("\\s");
      graphDef.comment("\\s");
      graphDef.comment("\\c");

      // Average, Min, and Max over all of the AVERAGE data - displayed at bottom of the graph
      graphDef.gprint("myAverage", ConsolFun.AVERAGE, "Average = %.3f%s");
      graphDef.gprint("myAverage", ConsolFun.MIN, "Min = %.3f%s");
      graphDef.gprint("myAverage", ConsolFun.MAX, "Max = %.3f%s");
    } else {
      rrdDb.close();
      throw new MetricsGraphException(
          "Unsupported data source type "
              + dataSourceType.name()
              + " in RRD file "
              + rrdFilename
              + ", only COUNTER and GAUGE data source types supported.");
    }

    rrdDb.close();

    // Use "-" as filename so that RRD creates the graph only in memory (no file is
    // created, hence no file locking problems due to race conditions between multiple clients)
    graphDef.setFilename("-");
    RrdGraph graph = new RrdGraph(graphDef);

    return graph.getRrdGraphInfo().getBytes();
  }