Forgiving handling of buggy stats from oracle containers under stress
(causes negative deltas and incorrect high delta values). Also added support to get CPU Usage without Non Idle Wait Time in percent. Some optimizations in the code to minimize sql calls.
Showing
6 changed files
with
123 additions
and
38 deletions
LILJM/lib/jconsole_ZJwK21.bat
0 → 100644
1 | javaw.exe -Dcom.sun.management.jmxremote.ssl=false -cp "wls-10.3.6.0.161018.2/wljmxclient.jar;jconsole.1.8.0_91.jar" sun.tools.jconsole.JConsole "service:jmx:rmi:///jndi/iiop://u30001:17192/weblogic.management.mbeanservers.runtime" | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -58,6 +58,19 @@ class Collector { | ... | @@ -58,6 +58,19 @@ class Collector { |
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | public long getDelta(String name) throws Throwable { | ||
62 | LongDelta myDelta = null; | ||
63 | for(int x = 0; x<list.size() && myDelta == null; x++) { | ||
64 | if(name.equals(list.get(x).name)) { | ||
65 | myDelta = list.get(x); | ||
66 | } | ||
67 | } | ||
68 | if(myDelta != null) | ||
69 | return myDelta.getDelta(); | ||
70 | else | ||
71 | return 0; | ||
72 | } | ||
73 | |||
61 | public double getPerSecValue(String name) throws Throwable { | 74 | public double getPerSecValue(String name) throws Throwable { |
62 | LongDelta myDelta = null; | 75 | LongDelta myDelta = null; |
63 | for(int x = 0; x<list.size() && myDelta == null; x++) { | 76 | for(int x = 0; x<list.size() && myDelta == null; x++) { | ... | ... |
... | @@ -9,21 +9,46 @@ class LongDelta { | ... | @@ -9,21 +9,46 @@ class LongDelta { |
9 | public Long lastValue = null; | 9 | public Long lastValue = null; |
10 | public Timestamp lastFetch = null; | 10 | public Timestamp lastFetch = null; |
11 | public Timestamp curFetch = null; | 11 | public Timestamp curFetch = null; |
12 | boolean urProt = false; // Under-run protection | ||
13 | boolean lastUpdCausedUR = false; | ||
14 | |||
15 | public LongDelta() {}; | ||
16 | public LongDelta(boolean UnderrunProtection) { this.urProt = UnderrunProtection; } | ||
12 | 17 | ||
13 | public void update(ResultSet rset) throws Throwable{ | 18 | public void update(ResultSet rset) throws Throwable{ |
14 | update(rset, false); | 19 | update(rset, 2, false, true); |
15 | } | 20 | } |
16 | public void update(ResultSet rset, boolean convert) throws Throwable{ | 21 | public void update(ResultSet rset, boolean convert) throws Throwable{ |
22 | update(rset, 2, convert, true); | ||
23 | } | ||
24 | public void update(ResultSet rset, int pos, boolean convert) throws Throwable{ | ||
25 | update(rset, pos, convert, true); | ||
26 | } | ||
27 | public void update(ResultSet rset, int pos, boolean convert, boolean close) throws Throwable{ | ||
17 | rset.next(); | 28 | rset.next(); |
29 | long newval = rset.getLong(pos); | ||
30 | if(convert) newval = newval/1000; | ||
31 | if(urProt) { | ||
32 | if(this.curValue != null && this.curValue > newval) { | ||
33 | //This would be a negative delta. Ignore this data | ||
34 | //System.out.println("Underrunprotection on " + name + " New Val: " + newval + " Old Val: " + this.curValue); | ||
35 | lastUpdCausedUR = true; | ||
36 | if(close) rset.close(); | ||
37 | return; | ||
38 | } | ||
39 | } | ||
18 | this.lastFetch = this.curFetch; | 40 | this.lastFetch = this.curFetch; |
19 | this.curFetch = rset.getTimestamp(1); | 41 | this.curFetch = rset.getTimestamp(1); |
20 | this.lastValue = this.curValue; | 42 | this.lastValue = this.curValue; |
21 | if(convert) | 43 | this.curValue = newval; |
22 | this.curValue = rset.getLong(2)/1000; | 44 | lastUpdCausedUR = false; |
23 | else | 45 | if(close) rset.close(); |
24 | this.curValue = rset.getLong(2); | 46 | } |
25 | rset.close(); | 47 | |
48 | public boolean didLastUnderRun() { | ||
49 | return lastUpdCausedUR; | ||
26 | } | 50 | } |
51 | |||
27 | public double getPerSecondValue() throws Throwable { | 52 | public double getPerSecondValue() throws Throwable { |
28 | if(this.curValue != null && this.lastValue != null && this.lastFetch != null && this.curFetch != null) { | 53 | if(this.curValue != null && this.lastValue != null && this.lastFetch != null && this.curFetch != null) { |
29 | // We have values, calculate the number of gets per second | 54 | // We have values, calculate the number of gets per second |
... | @@ -52,4 +77,10 @@ class LongDelta { | ... | @@ -52,4 +77,10 @@ class LongDelta { |
52 | } | 77 | } |
53 | return 0; | 78 | return 0; |
54 | } | 79 | } |
80 | public long getDelta() throws Throwable { | ||
81 | if(this.lastValue != null && this.curValue != null) { | ||
82 | return this.curValue - this.lastValue; | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
55 | } | 86 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -44,13 +44,35 @@ public class OraMon { | ... | @@ -44,13 +44,35 @@ public class OraMon { |
44 | } | 44 | } |
45 | 45 | ||
46 | //DB CPU | 46 | //DB CPU |
47 | LongDelta cpuTime = new LongDelta(); | 47 | LongDelta cpuTime = new LongDelta(true); |
48 | public double getCPUPercent() throws Throwable { | 48 | LongDelta niwTime = new LongDelta(true); |
49 | public double getCPUPercent(boolean excludeNonIdleWaitTime) throws Throwable { | ||
49 | double perSec = cpuTime.getPerSecondValue(); | 50 | double perSec = cpuTime.getPerSecondValue(); |
51 | if(excludeNonIdleWaitTime) { | ||
52 | double newPerSec = perSec - (niwTime.getPerSecondValue() * 1000); | ||
53 | if(newPerSec > 0) perSec = newPerSec; else perSec = 0; | ||
54 | } | ||
50 | double totSec = numCpus * 1000 * 1000; | 55 | double totSec = numCpus * 1000 * 1000; |
51 | double percent = (perSec / totSec) * 100; | 56 | double percent = (perSec / totSec) * 100; |
57 | if(percent > 100D) percent=100D; | ||
58 | if(percent < 0D) percent=0D; | ||
52 | return percent; | 59 | return percent; |
53 | } | 60 | } |
61 | public double getCPUPercent() throws Throwable { | ||
62 | return getCPUPercent(false); | ||
63 | } | ||
64 | public double getCPUAvailableSeconds() throws Throwable { | ||
65 | return cpuTime.getSeconds()*numCpus; | ||
66 | } | ||
67 | public long getCPURawValue() throws Throwable { | ||
68 | return cpuTime.getCurrentValue(); | ||
69 | } | ||
70 | public long getCPURawDiff() { | ||
71 | if(cpuTime != null && cpuTime.lastValue != null) | ||
72 | return cpuTime.curValue - cpuTime.lastValue; | ||
73 | else | ||
74 | return 0; | ||
75 | } | ||
54 | 76 | ||
55 | public double getCPUTimePerSecond() throws Throwable { | 77 | public double getCPUTimePerSecond() throws Throwable { |
56 | return cpuTime.getPerSecondValue(); | 78 | return cpuTime.getPerSecondValue(); |
... | @@ -188,6 +210,7 @@ public class OraMon { | ... | @@ -188,6 +210,7 @@ public class OraMon { |
188 | open(); | 210 | open(); |
189 | } | 211 | } |
190 | Statement stmt = conn.createStatement(); | 212 | Statement stmt = conn.createStatement(); |
213 | Statement scrollStmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); | ||
191 | ResultSet rset = null; | 214 | ResultSet rset = null; |
192 | 215 | ||
193 | //Get the database name once | 216 | //Get the database name once |
... | @@ -205,7 +228,13 @@ public class OraMon { | ... | @@ -205,7 +228,13 @@ public class OraMon { |
205 | this.numCpus = (int) colOsStat.getCurrentValue("NUM_CPUS"); | 228 | this.numCpus = (int) colOsStat.getCurrentValue("NUM_CPUS"); |
206 | 229 | ||
207 | // Get DB CPU use time | 230 | // Get DB CPU use time |
208 | cpuTime.update(stmt.executeQuery("select systimestamp, value from V$SYS_TIME_MODEL where stat_name='DB CPU'")); | 231 | rset = scrollStmt.executeQuery("select systimestamp, s.value as NIWT, t.value as DBCPU from V$SYSSTAT s, V$SYS_TIME_MODEL t where s.name='non-idle wait time' and t.STAT_NAME='DB CPU'"); |
232 | cpuTime.update(rset, 3, false, false); | ||
233 | rset.beforeFirst(); | ||
234 | niwTime.update(rset, 2, false); | ||
235 | |||
236 | // cpuTime.update(stmt.executeQuery("select systimestamp, value from V$SYS_TIME_MODEL where stat_name='DB CPU'")); | ||
237 | // niwTime.update(stmt.executeQuery("select systimestamp, value from V$SYSSTAT where name='non-idle wait time'")); | ||
209 | 238 | ||
210 | // Get OS Load | 239 | // Get OS Load |
211 | osLoad.update(stmt.executeQuery("select systimestamp, value from V$OSSTAT where stat_name='LOAD'")); | 240 | osLoad.update(stmt.executeQuery("select systimestamp, value from V$OSSTAT where stat_name='LOAD'")); | ... | ... |
... | @@ -17,51 +17,60 @@ public class TestRunner { | ... | @@ -17,51 +17,60 @@ public class TestRunner { |
17 | //ArrayList<OraMon> oraList = new ArrayList<OraMon>(); | 17 | //ArrayList<OraMon> oraList = new ArrayList<OraMon>(); |
18 | ArrayList<OraMon> oraList = Registry.getList(); | 18 | ArrayList<OraMon> oraList = Registry.getList(); |
19 | 19 | ||
20 | OraMon mon1 = new OraMon("jdbc:oracle:thin:@//hostname:1521/SID1","system","passw0rd"); | 20 | OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u03292.kap.rsv.se:1526/AI1K001","dbsnmp","dbsnmp"); |
21 | OraMon mon2 = new OraMon("jdbc:oracle:thin:@//hostname:1521/SID1","system","passw0rd"); | 21 | OraMon mon2 = new OraMon("jdbc:oracle:thin:@u03292.kap.rsv.se:1526:DB1K09","dbsnmp","dbsnmp"); |
22 | mon1.open(); | 22 | mon1.open(); |
23 | mon2.open(); | 23 | mon2.open(); |
24 | oraList.add(mon1); | 24 | oraList.add(mon1); |
25 | oraList.add(mon2); | 25 | oraList.add(mon2); |
26 | 26 | ||
27 | int times = 10; | 27 | int times = 100; |
28 | while(times-- > 0) { | 28 | while(times-- > 0) { |
29 | int num = 0; | ||
29 | for(OraMon mon : oraList) { | 30 | for(OraMon mon : oraList) { |
31 | num++; | ||
30 | Long ts1 = System.currentTimeMillis(); | 32 | Long ts1 = System.currentTimeMillis(); |
31 | mon.getData(); | 33 | mon.getData(); |
32 | Long time = System.currentTimeMillis() - ts1; | 34 | Long time = System.currentTimeMillis() - ts1; |
33 | 35 | ||
34 | System.out.println( | 36 | System.out.println( |
35 | "Logical reads:" + mon.getLogicalReadsPerSecond() | 37 | // "Logical reads:" + mon.getLogicalReadsPerSecond() |
36 | + " Consistent gets: " + mon.getPerSecondValue("consistent gets") | 38 | // + " Consistent gets: " + mon.getPerSecondValue("consistent gets") |
37 | + " Block Gets: " + mon.getPerSecondValue("db block gets") | 39 | // + " Block Gets: " + mon.getPerSecondValue("db block gets") |
38 | + " Block Changes: " + mon.getPerSecondValue("db block changes") | 40 | // + " Block Changes: " + mon.getPerSecondValue("db block changes") |
39 | + "\n" | 41 | // + "\n" |
40 | + "CPUs: " + mon.getNumberOfCPUs() | 42 | "MON" + num + " CPUs: " + mon.getNumberOfCPUs() |
41 | + " CPU Time: " + mon.getCPUTimePerSecond() + "ms" | 43 | + " CPU Time: " + String.format("%1$,.2f", mon.getCPUTimePerSecond()/1000) + "ms/s" |
42 | + " CPU Usage: " + String.format("%1$,.2f", mon.getCPUPercent()) + "%" | 44 | + " CPU Usage: " + String.format("%1$,.2f", mon.getCPUPercent()) + "%" |
43 | + "\n" | 45 | + " CPU xNIWT: " + String.format("%1$,.2f", mon.getCPUPercent(true)) + "%" |
44 | + "Cache Hit Ratio: " + String.format("%1$,.2f", mon.getCacheHitRatioPercent()) + "%" | 46 | + " OS Busy: " + String.format("%1$,.2f", mon.getOsBusyPercent()) + "%" |
45 | + " Buffer Cache Hit Ratio: " + String.format("%1$,.2f", mon.getBufferCacheHitRatioPercent()) + "%" | 47 | // + " (Raw: " + mon.getCPURawValue() |
46 | + "\n" | 48 | // + " Diff: " + mon.getCPURawDiff() |
47 | + "Redo size: " + mon.getPerSecondValue("redo size") | 49 | // + " Available: " + String.format("%1$,.2f", mon.getCPUAvailableSeconds()*1000) + ")" |
48 | + " Phys Reads: " + mon.getPerSecondValue("physical reads") | 50 | + " NIWTime: " + String.format("%1$,.2f", mon.niwTime.getPerSecondValue()) + "ms/s" |
49 | + " Phys Writes: " + mon.getPerSecondValue("physical writes") | 51 | // + "\n" |
50 | + " Redo Writes: " + mon.getPerSecondValue("redo writes") | 52 | // + "Cache Hit Ratio: " + String.format("%1$,.2f", mon.getCacheHitRatioPercent()) + "%" |
51 | + "\n" | 53 | // + " Buffer Cache Hit Ratio: " + String.format("%1$,.2f", mon.getBufferCacheHitRatioPercent()) + "%" |
52 | + "Non Idle Wait: " + mon.getPerSecondValue("non-idle wait time") | 54 | // + "\n" |
53 | + " File IO Wait: " + mon.getPerSecondValue("file io wait time") | 55 | // + "Redo size: " + mon.getPerSecondValue("redo size") |
54 | + "\n" | 56 | // + " Phys Reads: " + mon.getPerSecondValue("physical reads") |
55 | + "Executes: " + mon.getPerSecondValue("execute count") | 57 | // + " Phys Writes: " + mon.getPerSecondValue("physical writes") |
56 | + " User calls: " + mon.getPerSecondValue("user calls") | 58 | // + " Redo Writes: " + mon.getPerSecondValue("redo writes") |
57 | + " Commits: " + mon.getPerSecondValue("user commits") | 59 | // + "\n" |
58 | + " Rollbacks: " + mon.getPerSecondValue("user rollbacks") | 60 | // + "Non Idle Wait: " + mon.getPerSecondValue("non-idle wait time") |
59 | + " Parse tot: " + mon.getPerSecondValue("parse count (total)") | 61 | // + " File IO Wait: " + mon.getPerSecondValue("file io wait time") |
60 | + " Parse hard: " + mon.getPerSecondValue("parse count (hard)") | 62 | // + "\n" |
61 | + "\nTime: " + time + "ms" | 63 | // + "Executes: " + mon.getPerSecondValue("execute count") |
64 | // + " User calls: " + mon.getPerSecondValue("user calls") | ||
65 | // + " Commits: " + mon.getPerSecondValue("user commits") | ||
66 | // + " Rollbacks: " + mon.getPerSecondValue("user rollbacks") | ||
67 | // + " Parse tot: " + mon.getPerSecondValue("parse count (total)") | ||
68 | // + " Parse hard: " + mon.getPerSecondValue("parse count (hard)") | ||
69 | // + "\nTime: " + time + "ms" | ||
62 | ); | 70 | ); |
63 | 71 | ||
64 | } | 72 | } |
73 | System.out.println("---------------------------------------------------------------------------------------------------------------"); | ||
65 | Thread.sleep(15000); | 74 | Thread.sleep(15000); |
66 | } | 75 | } |
67 | 76 | ... | ... |
-
Please register or sign in to post a comment