[KARAF-7000] Add System-Wide CPU Load to the oshi collector (#224)

diff --git a/collector/oshi/src/main/java/org/apache/karaf/decanter/collector/oshi/OshiCollector.java b/collector/oshi/src/main/java/org/apache/karaf/decanter/collector/oshi/OshiCollector.java
index 3ea7a4f..e725fe3 100644
--- a/collector/oshi/src/main/java/org/apache/karaf/decanter/collector/oshi/OshiCollector.java
+++ b/collector/oshi/src/main/java/org/apache/karaf/decanter/collector/oshi/OshiCollector.java
@@ -51,6 +51,8 @@
 
     private Dictionary<String, Object> properties;
 
+    long[] lastSystemCpuLoadTicks = null;
+
     @Activate
     public void activate(ComponentContext componentContext) {
         activate(componentContext.getProperties());
@@ -58,6 +60,7 @@
 
     public void activate(Dictionary<String, Object> properties) {
         this.properties = properties;
+        this.lastSystemCpuLoadTicks = null;
     }
 
     @Override
@@ -110,6 +113,8 @@
                 data.put("processor.interrupts", hardwareAbstractionLayer.getProcessor().getInterrupts());
                 data.put("processor.logicalProcessorCount", hardwareAbstractionLayer.getProcessor().getLogicalProcessorCount());
                 data.put("processor.maxFreq", hardwareAbstractionLayer.getProcessor().getMaxFreq());
+                data.put("processor.systemCpuLoadBetweenTicks", lastSystemCpuLoadTicks != null ? hardwareAbstractionLayer.getProcessor().getSystemCpuLoadBetweenTicks(lastSystemCpuLoadTicks) : null);
+                lastSystemCpuLoadTicks = hardwareAbstractionLayer.getProcessor().getSystemCpuLoadTicks();
                 boolean processorsLogical = properties.get("processors.logical") != null ? Boolean.parseBoolean(properties.get("processors.logical").toString()) : true;
                 if (processorsLogical) {
                     int i = 0;
diff --git a/collector/oshi/src/test/java/org/apache/karaf/decanter/collector/oshi/OshiCollectorTest.java b/collector/oshi/src/test/java/org/apache/karaf/decanter/collector/oshi/OshiCollectorTest.java
index 8936848..c2c5473 100644
--- a/collector/oshi/src/test/java/org/apache/karaf/decanter/collector/oshi/OshiCollectorTest.java
+++ b/collector/oshi/src/test/java/org/apache/karaf/decanter/collector/oshi/OshiCollectorTest.java
@@ -27,6 +27,8 @@
 
 public class OshiCollectorTest {
 
+    static final String SYSTEM_CPU_LOAD_PROPERTY = "processor.systemCpuLoadBetweenTicks";
+
     @Test
     public void test() throws Exception {
         DispatcherMock dispatcherMock = new DispatcherMock();
@@ -45,6 +47,29 @@
         }
     }
 
+   /**
+    * Verify the SYSTEM_CPU_LOAD_PROPERTY is null on the initial collector run
+    * and not null on subsequent collector runs.
+    */
+   @Test
+   public void testSystemCpuLoad() throws Exception {
+        DispatcherMock dispatcherMock = new DispatcherMock();
+
+        OshiCollector collector = new OshiCollector();
+        collector.setDispatcher(dispatcherMock);
+        collector.activate(new Hashtable<>());
+
+        collector.run();
+        collector.run();
+
+        Assert.assertEquals(2, dispatcherMock.postedEvents.size());
+        Event firstEvent = dispatcherMock.postedEvents.get(0);
+        Assert.assertNull("Initial systemCpuLoadBetweenTicks is null", firstEvent.getProperty(SYSTEM_CPU_LOAD_PROPERTY));
+        Event secondEvent = dispatcherMock.postedEvents.get(1);
+        Assert.assertNotNull("Second systemCpuLoadBetweenTicks is not null", secondEvent.getProperty(SYSTEM_CPU_LOAD_PROPERTY));
+        System.out.println(SYSTEM_CPU_LOAD_PROPERTY + ":" + secondEvent.getProperty(SYSTEM_CPU_LOAD_PROPERTY));
+    }
+
     class DispatcherMock implements EventAdmin {
 
         public List<Event> postedEvents = new ArrayList<>();