Commit 0d4a053f 0d4a053ff1c1f5f222f6710a9f06d62d985fde5d by Christian Gerdes

First working fix of the OraBug issue #8

We now keep 3 measurements internaly. If a delta is calculated and is
negative, it is ignored. If no delta can be calculated between the
3 last measurements, the last valid response is returned instead, until
a new delta can be calculated. When a cached response is reported, it 
will be logged with a timestamp, name of the counter and all 3
measurements ordered by age (youngest first).
Improved logging with timestamps also for exceptions.
1 parent 89849623
No preview for this file type
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.remote.JMXServiceURL;
import javax.servlet.ServletException;
......@@ -18,7 +20,7 @@ import se.lil.jm.Registry;
@WebServlet(description = "Calls getData on an existing JmxMon object or creates and calls it", urlPatterns = { "/JmxMonREST/getData" })
public class JmxMonRESTgetData extends HttpServlet {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger(JmxMonRESTgetData.class.getName());
/**
* @see HttpServlet#HttpServlet()
*/
......@@ -90,6 +92,7 @@ public class JmxMonRESTgetData extends HttpServlet {
String rst = "{\"error\":true,\"msg\":\"" + e.toString() + ". Caused by: " + thisCause.toString() + "\"}";
rst.replace("\n"," ").replace("\"","\\\"").trim();
response.getWriter().println(rst);
LOGGER.log(Level.SEVERE, e.toString());
e.printStackTrace();
}
}
......
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.remote.JMXServiceURL;
import javax.servlet.ServletException;
......@@ -18,7 +20,7 @@ import se.lil.jm.Registry;
@WebServlet(description = "Gets JMX Monitors metrics", urlPatterns = { "/JmxMonREST/getMetrics" })
public class JmxMonRESTgetMetrics extends HttpServlet {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger(JmxMonRESTgetMetrics.class.getName());
/**
* @see HttpServlet#HttpServlet()
*/
......@@ -97,6 +99,7 @@ public class JmxMonRESTgetMetrics extends HttpServlet {
} catch (Throwable e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().println("{\"error\":true,\"msg\":\""+e.toString().replace("\n"," ").trim()+"\"}");
LOGGER.log(Level.SEVERE, e.toString());
e.printStackTrace();
}
}
......
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
......@@ -17,7 +19,7 @@ import se.lil.om.Registry;
@WebServlet(description = "REST API for OraMon", urlPatterns = { "/OraMonREST/getData" })
public class OraMonRESTgetData extends HttpServlet {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger(OraMonRESTgetData.class.getName());
/**
* @see HttpServlet#HttpServlet()
*/
......@@ -159,6 +161,7 @@ public class OraMonRESTgetData extends HttpServlet {
} catch (Throwable e) {
response.setStatus(500);
response.getWriter().println("{\"error\":true,\"msg\":\""+e.toString().replace("\n"," ").replace("\"","\\\"").trim()+"\"}");
LOGGER.log(Level.SEVERE, e.toString());
e.printStackTrace();
}
}
......
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
......@@ -17,7 +19,7 @@ import se.lil.om.Registry;
@WebServlet(description = "Gets a default set of metrics from an existing monitor", urlPatterns = { "/OraMonREST/getMetrics" })
public class OraMonRESTgetMetrics extends HttpServlet {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger(OraMonRESTgetMetrics.class.getName());
/**
* @see HttpServlet#HttpServlet()
*/
......@@ -167,6 +169,7 @@ public class OraMonRESTgetMetrics extends HttpServlet {
} catch (Throwable e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().println("{\"error\":true,\"msg\":\""+e.toString().replace("\n"," ").trim()+"\"}");
LOGGER.log(Level.SEVERE, e.toString());
e.printStackTrace();
}
}
......
......@@ -76,3 +76,15 @@ Istället måste detta detekteras när man läser av ett delta i någon av delta
Innan trodde jag att problemet alltid inleds med ett negativt delta, sedan en spik, sedan normalt. Men så är inte fallet, jag har sett idag tvärtom, det inleds med en spik och sedan
en rättning (vilket känns konstigt) men så blev det på tex file io wait time. Så jag tror tyvärr att enda rätta lösningen på problemet är att spara minst 3 mätningar innan ett delta rapporteras,
samt att man då kan upptäcka ett negativt delta, och i så fall ignorera värdet innan.
2019-02-13
Måste se över logiken med att hoppa över negativa deltan. De kommer fram i alla fall i guit. Kanske sker 2 på raken? Eller så funkar inte logiken. Behöver börja med att logga.
Kom på ett alternativ idag med, en parameter i varje long delta som är "senast rapporterade värdet" och sedan en enkel kontroll, om inte alla 3 senaste mätningarna är "i rad"
så rapportera senaste/föregående delta igen. Detta för att undvika att påverka medelvärden som beräknas på rapporterade deltan.
2019-02-20
Har nu skrivit om logiken så att vi kollar om vi kan hitta ett positivt delta bland de 3 mätvärden som finns, om vi gör det returnerar vi detta med det senaste mest aktuella
värdet först. Lyckas vi inte med det, returnerar vi det cachade värdet vi returnerade förra gången. Om det senare sker loggas detta tillsammans med namn på räknaren samt
alla aktuella värden samt det cachade resultatet som returnerades.
......
......@@ -3,8 +3,11 @@ package se.lil.om;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.logging.Level;
import java.util.logging.Logger;
class LongDelta {
private final static Logger LOGGER = Logger.getLogger(LongDelta.class.getName());
private String name = null;
private BigDecimal curValue = null;
......@@ -19,6 +22,8 @@ class LongDelta {
private double numMilliSeconds;
private double delta;
private double lastGoodDelta = 0;
private double lastGoodMilliseconds = 0;
private boolean haveGoodDelta = false;
public LongDelta(String name) {
......@@ -64,17 +69,30 @@ class LongDelta {
if(this.curValue != null && this.lastValue != null && this.last2Value != null
&& this.lastFetch != null && this.last2Fetch != null && this.curFetch != null) {
// We have values, calculate the number of gets per second
// We have values, calculate the deltas
// Handle the Oracle Bug (ref needed)
if(curValue.compareTo(lastValue) >= 0 && lastValue.compareTo(last2Value) >= 0) {
// All seems fine, no negative deltas, return the delta for last and last2
if(curValue.compareTo(lastValue) >= 0) {
numMilliSeconds = this.curFetch.getTime() - this.lastFetch.getTime();
delta = this.curValue.subtract(this.lastValue).doubleValue();
lastGoodMilliseconds = numMilliSeconds;
lastGoodDelta = delta;
} else if(curValue.compareTo(last2Value) >= 0) {
numMilliSeconds = this.curFetch.getTime() - this.last2Fetch.getTime();
delta = this.curValue.subtract(this.last2Value).doubleValue();
lastGoodMilliseconds = numMilliSeconds;
lastGoodDelta = delta;
} else if (lastValue.compareTo(last2Value) >= 0) {
numMilliSeconds = this.lastFetch.getTime() - this.last2Fetch.getTime();
delta = this.lastValue.subtract(this.last2Value).doubleValue();
lastGoodMilliseconds = numMilliSeconds;
lastGoodDelta = delta;
} else {
// negative delta between current and last, or last and last2, return current and last2 instead
numMilliSeconds = this.curFetch.getTime() - this.last2Fetch.getTime();
delta = this.curValue.subtract(this.last2Value).doubleValue();
// None of the 2 last measurements give a positive delta. Log this and return the last calculated delta.
numMilliSeconds = lastGoodMilliseconds;
delta = lastGoodDelta;
LOGGER.log(Level.WARNING, "No positive deltas to calculate, returning cached value:["+lastGoodDelta+"]. Name: "
+ this.name + " Values:["+curValue+"]["+lastValue+"]["+last2Value+"]");
}
haveGoodDelta = true;
......
......@@ -146,16 +146,6 @@ public class OraMon {
return getCPURawValue();
}
// public long getCPURawDiff() throws Throwable {
// return cpuTime.getDelta();
// }
// public long getCPURawDiff(String pdbName) throws Throwable {
// if(pdbName != null)
// return colPdbCPU.getDelta(pdbName + strCpuTime);
// else
// return getCPURawDiff();
// }
public double getCPUTimePerSecond() throws Throwable {
return cpuTime.getPerSecondValue();
}
......