You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2020/04/19 05:36:48 UTC

[karaf-decanter] branch master updated: [KARAF-6671] Add oshi collector

This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf-decanter.git


The following commit(s) were added to refs/heads/master by this push:
     new 2a3d07d  [KARAF-6671] Add oshi collector
     new 7d0786e  Merge pull request #155 from jbonofre/KARAF-6671
2a3d07d is described below

commit 2a3d07da01ba9e9ea2d9bf28534409ccf5d16b5a
Author: jbonofre <jb...@apache.org>
AuthorDate: Fri Apr 17 08:44:52 2020 +0200

    [KARAF-6671] Add oshi collector
---
 assembly/src/main/feature/feature.xml              |   7 +
 collector/oshi/pom.xml                             |  98 ++++++
 .../org.apache.karaf.decanter.collector.oshi.cfg   |  43 +++
 .../decanter/collector/oshi/OshiCollector.java     | 379 +++++++++++++++++++++
 .../decanter/collector/oshi/OshiCollectorTest.java |  64 ++++
 collector/pom.xml                                  |   1 +
 .../src/main/asciidoc/user-guide/collectors.adoc   |  64 +++-
 7 files changed, 655 insertions(+), 1 deletion(-)

diff --git a/assembly/src/main/feature/feature.xml b/assembly/src/main/feature/feature.xml
index 5ad11e7..e2b63b2 100644
--- a/assembly/src/main/feature/feature.xml
+++ b/assembly/src/main/feature/feature.xml
@@ -123,6 +123,13 @@ org.apache.felix.eventadmin.IgnoreTimeout=org.apache.karaf.decanter.
         <feature>decanter-collector-soap-core</feature>
     </feature>
 
+    <feature name="decanter-collector-oshi" version="${project.version}" description="Karaf Decanter oshi (system) collector">
+        <feature>decanter-common</feature>
+        <feature>scheduler</feature>
+        <configfile finalname="/etc/org.apache.karaf.decanter.collector.oshi.cfg">mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.oshi/${project.version}/cfg</configfile>
+        <bundle>mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.oshi/${project.version}</bundle>
+    </feature>
+
     <feature name="decanter-collector-system" version="${project.version}" description="Karaf Decanter OS Collector">
         <feature>decanter-common</feature>
         <feature>scheduler</feature>
diff --git a/collector/oshi/pom.xml b/collector/oshi/pom.xml
new file mode 100644
index 0000000..a150419
--- /dev/null
+++ b/collector/oshi/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        Licensed to the Apache Software Foundation (ASF) under one or more
+        contributor license agreements.  See the NOTICE file distributed with
+        this work for additional information regarding copyright ownership.
+        The ASF licenses this file to You under the Apache License, Version 2.0
+        (the "License"); you may not use this file except in compliance with
+        the License.  You may obtain a copy of the License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software
+        distributed under the License is distributed on an "AS IS" BASIS,
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+        See the License for the specific language governing permissions and
+        limitations under the License.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.decanter</groupId>
+        <artifactId>collector</artifactId>
+        <version>2.4.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.karaf.decanter.collector</groupId>
+    <artifactId>org.apache.karaf.decanter.collector.oshi</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Decanter :: Collector :: OSHI</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.decanter.collector</groupId>
+            <artifactId>org.apache.karaf.decanter.collector.utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+            <version>4.6.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    <file>src/main/cfg/org.apache.karaf.decanter.collector.oshi.cfg</file>
+                                    <type>cfg</type>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <extensions>true</extensions>
+                <configuration>
+                    <obrRepository>NONE</obrRepository>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Export-Package>!*</Export-Package>
+                        <Import-Package>
+                            !oshi*,
+                            !com.sun.jna*,
+                            *
+                        </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.decanter.collector.oshi,
+                            org.apache.karaf.decanter.collector.utils,
+                            com.sun.jna*,
+                            oshi*
+                        </Private-Package>
+                        <_dsannotations>*</_dsannotations>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/collector/oshi/src/main/cfg/org.apache.karaf.decanter.collector.oshi.cfg b/collector/oshi/src/main/cfg/org.apache.karaf.decanter.collector.oshi.cfg
new file mode 100644
index 0000000..8502d4a
--- /dev/null
+++ b/collector/oshi/src/main/cfg/org.apache.karaf.decanter.collector.oshi.cfg
@@ -0,0 +1,43 @@
+################################################################################
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+################################################################################
+
+#
+# Decanter oshi (system) collector
+#
+
+# computerSystem=true
+# computerSystem.baseboard=true
+# computerSystem.firmware=true
+# memory=true
+# processors=true
+# processors.logical=true
+# displays=true
+# disks=true
+# disks.partitions=true
+# graphicsCards=true
+# networkIFs=true
+# powerSources=true
+# soundCards=true
+# sensors=true
+# usbDevices=true
+# operatingSystem=true
+# operatingSystem.fileSystems=true
+# operatingSystem.networkParams=true
+# operatingSystem.processes=true
+# operatingSystem.services=true
\ No newline at end of file
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
new file mode 100644
index 0000000..c019fee
--- /dev/null
+++ b/collector/oshi/src/main/java/org/apache/karaf/decanter/collector/oshi/OshiCollector.java
@@ -0,0 +1,379 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.decanter.collector.oshi;
+
+import org.apache.karaf.decanter.collector.utils.PropertiesPreparator;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import oshi.SystemInfo;
+import oshi.hardware.*;
+import oshi.software.os.*;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component(
+        name = "org.apache.karaf.decanter.collector.oshi",
+        immediate = true,
+        property = { "decanter.collector.name=oshi",
+                "scheduler.period:Long=60",
+                "scheduler.concurrent:Boolean=false",
+                "scheduler.name=decanter-collector-oshi"}
+)
+public class OshiCollector implements Runnable {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(OshiCollector.class);
+
+    @Reference
+    EventAdmin dispatcher;
+
+    private Dictionary<String, Object> properties;
+
+    @Activate
+    public void activate(ComponentContext componentContext) {
+        activate(componentContext.getProperties());
+    }
+
+    public void activate(Dictionary<String, Object> properties) {
+        this.properties = properties;
+    }
+
+    @Override
+    public void run() {
+        try {
+            Map<String, Object> data = new HashMap<>();
+            data.put("type", "oshi");
+
+            SystemInfo systemInfo = new SystemInfo();
+
+            HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware();
+            // * computer system
+            boolean computerSystem = properties.get("computerSystem") != null ? Boolean.parseBoolean(properties.get("computerSystem").toString()) : true;
+            if (computerSystem) {
+                data.put("computerSystem.manufacturer", hardwareAbstractionLayer.getComputerSystem().getManufacturer());
+                data.put("computerSystem.model", hardwareAbstractionLayer.getComputerSystem().getModel());
+                data.put("computerSystem.serialNumber", hardwareAbstractionLayer.getComputerSystem().getSerialNumber());
+                // ** baseboard
+                boolean computerSystemBaseboard = properties.get("computerSystem.baseboard") != null  ? Boolean.parseBoolean(properties.get("computerSystem.baseboard").toString()) : true;
+                if (computerSystemBaseboard) {
+                    data.put("computerSystem.baseboard.manufacturer", hardwareAbstractionLayer.getComputerSystem().getBaseboard().getManufacturer());
+                    data.put("computerSystem.baseboard.model", hardwareAbstractionLayer.getComputerSystem().getBaseboard().getModel());
+                    data.put("computerSystem.baseboard.serialNumber", hardwareAbstractionLayer.getComputerSystem().getBaseboard().getSerialNumber());
+                    data.put("computerSystem.baseboard.version", hardwareAbstractionLayer.getComputerSystem().getBaseboard().getVersion());
+                }
+                // ** firmware
+                boolean computerSystemFirmware = properties.get("computerSystem.firmware") != null ? Boolean.parseBoolean(properties.get("computerSystem.firmware").toString()) : true;
+                if (computerSystemFirmware) {
+                    data.put("computerSystem.firmware.description", hardwareAbstractionLayer.getComputerSystem().getFirmware().getDescription());
+                    data.put("computerSystem.firmware.manufacturer", hardwareAbstractionLayer.getComputerSystem().getFirmware().getManufacturer());
+                    data.put("computerSystem.firmware.name", hardwareAbstractionLayer.getComputerSystem().getFirmware().getName());
+                    data.put("computerSystem.firmware.releaseDate", hardwareAbstractionLayer.getComputerSystem().getFirmware().getReleaseDate());
+                    data.put("computerSystem.firmware.version", hardwareAbstractionLayer.getComputerSystem().getFirmware().getVersion());
+                }
+            }
+            // * memory
+            boolean memory = properties.get("memory") != null ? Boolean.parseBoolean(properties.get("memory").toString()) : true;
+            if (memory) {
+                data.put("memory.available", hardwareAbstractionLayer.getMemory().getAvailable());
+                data.put("memory.pageSize", hardwareAbstractionLayer.getMemory().getPageSize());
+                data.put("memory.physicalMemory", hardwareAbstractionLayer.getMemory().getPhysicalMemory());
+                data.put("memory.total", hardwareAbstractionLayer.getMemory().getTotal());
+                data.put("memory.virtualMemory", hardwareAbstractionLayer.getMemory().getVirtualMemory());
+            }
+            // * processor
+            boolean processors = properties.get("processors") != null ? Boolean.parseBoolean(properties.get("processors").toString()) : true;
+            if (processors) {
+                data.put("processor.contextSwitched", hardwareAbstractionLayer.getProcessor().getContextSwitches());
+                data.put("processor.currentFreq", Arrays.toString(hardwareAbstractionLayer.getProcessor().getCurrentFreq()));
+                data.put("processor.interrupts", hardwareAbstractionLayer.getProcessor().getInterrupts());
+                data.put("processor.logicalProcessorCount", hardwareAbstractionLayer.getProcessor().getLogicalProcessorCount());
+                data.put("processor.maxFreq", hardwareAbstractionLayer.getProcessor().getMaxFreq());
+                boolean processorsLogical = properties.get("processors.logical") != null ? Boolean.parseBoolean(properties.get("processors.logical").toString()) : true;
+                if (processorsLogical) {
+                    int i = 0;
+                    for (CentralProcessor.LogicalProcessor processor : hardwareAbstractionLayer.getProcessor().getLogicalProcessors()) {
+                        data.put("processor.logical." + i + ".numaNode", processor.getNumaNode());
+                        data.put("processor.logical." + i + ".physicalPackageNumber", processor.getPhysicalPackageNumber());
+                        data.put("processor.logical." + i + ".physicalProcessorNumber", processor.getPhysicalProcessorNumber());
+                        data.put("processor.logical." + i + ".processorGroup", processor.getProcessorGroup());
+                        data.put("processor.logical." + i + ".processorNumber", processor.getProcessorNumber());
+                        i++;
+                    }
+                }
+            }
+            // * displays
+            boolean displays = properties.get("displays") != null ? Boolean.parseBoolean(properties.get("displays").toString()) : true;
+            if (displays) {
+                int i = 0;
+                for (Display display : hardwareAbstractionLayer.getDisplays()) {
+                    data.put("display." + i + ".edid", display.getEdid());
+                    i++;
+                }
+            }
+            boolean disks = properties.get("disks") != null ? Boolean.parseBoolean(properties.get("disks").toString()) : true;
+            if (disks) {
+                // * disk stores
+                int i = 0;
+                for (HWDiskStore diskStore : hardwareAbstractionLayer.getDiskStores()) {
+                    data.put("diskStore." + i + ".name", diskStore.getName());
+                    data.put("diskStore." + i + ".model", diskStore.getModel());
+                    data.put("diskStore." + i + ".currentQueueLength", diskStore.getCurrentQueueLength());
+                    data.put("diskStore." + i + ".readBytes", diskStore.getReadBytes());
+                    data.put("diskStore." + i + ".reads", diskStore.getReads());
+                    data.put("diskStore." + i + ".serial", diskStore.getSerial());
+                    data.put("diskStore." + i + ".size", diskStore.getSize());
+                    data.put("diskStore." + i + ".timeStamp", diskStore.getTimeStamp());
+                    data.put("diskStore." + i + ".transferTime", diskStore.getTransferTime());
+                    data.put("diskStore." + i + ".writeBytes", diskStore.getWriteBytes());
+                    data.put("diskStore." + i + ".writes", diskStore.getWrites());
+                    // partitions
+                    boolean disksPartitions = properties.get("disks.partitions") != null ? Boolean.parseBoolean(properties.get("disks.partitions").toString()) : true;
+                    if (disksPartitions) {
+                        int j = 0;
+                        for (HWPartition partition : diskStore.getPartitions()) {
+                            data.put("diskStore." + i + ".partition." + j + ".name", partition.getName());
+                            data.put("diskStore." + i + ".partition." + j + ".identification", partition.getIdentification());
+                            data.put("diskStore." + i + ".partition." + j + ".major", partition.getMajor());
+                            data.put("diskStore." + i + ".partition." + j + ".minor", partition.getMinor());
+                            data.put("diskStore." + i + ".partition." + j + ".mountPoint", partition.getMountPoint());
+                            data.put("diskStore." + i + ".partition." + j + ".size", partition.getSize());
+                            data.put("diskStore." + i + ".partition." + j + ".type", partition.getType());
+                            data.put("diskStore." + i + ".partition." + j + ".uuid", partition.getUuid());
+                            j++;
+                        }
+                    }
+                    i++;
+                }
+            }
+            // * graphics cards
+            boolean graphicsCards = properties.get("graphicsCards") != null ? Boolean.parseBoolean(properties.get("graphicsCards").toString()) : true;
+            if (graphicsCards) {
+                int i = 0;
+                for (GraphicsCard graphicsCard : hardwareAbstractionLayer.getGraphicsCards()) {
+                    data.put("graphicsCard." + i + ".deviceId", graphicsCard.getDeviceId());
+                    data.put("graphicsCard." + i + ".name", graphicsCard.getName());
+                    data.put("graphicsCard." + i + ".vendor", graphicsCard.getVendor());
+                    data.put("graphicsCard." + i + ".versionInfo", graphicsCard.getVersionInfo());
+                    data.put("graphicsCard." + i + ".vram", graphicsCard.getVRam());
+                    i++;
+                }
+            }
+            boolean networkIFs = properties.get("networkIFs") != null ? Boolean.parseBoolean(properties.get("networkIFs").toString()) : true;
+            if (networkIFs) {
+                // * network interfaces
+                int i = 0;
+                for (NetworkIF networkIF : hardwareAbstractionLayer.getNetworkIFs()) {
+                    data.put("networkIF." + i + ".bytesRecv", networkIF.getBytesRecv());
+                    data.put("networkIF." + i + ".bytesSent", networkIF.getBytesSent());
+                    data.put("networkIF." + i + ".collisions", networkIF.getCollisions());
+                    data.put("networkIF." + i + ".displayName", networkIF.getDisplayName());
+                    data.put("networkIF." + i + ".ifType", networkIF.getIfType());
+                    data.put("networkIF." + i + ".inDrops", networkIF.getInDrops());
+                    data.put("networkIF." + i + ".inErrors", networkIF.getInErrors());
+                    data.put("networkIF." + i + ".IPv4addr", Arrays.toString(networkIF.getIPv4addr()));
+                    data.put("networkIF." + i + ".IPv6addr", Arrays.toString(networkIF.getIPv6addr()));
+                    data.put("networkIF." + i + ".MACaddr", networkIF.getMacaddr());
+                    data.put("networkIF." + i + ".MTU", networkIF.getMTU());
+                    data.put("networkIF." + i + ".name", networkIF.getName());
+                    data.put("networkIF." + i + ".ndisPhysicalMediumType", networkIF.getNdisPhysicalMediumType());
+                    data.put("networkIF." + i + ".outErrors", networkIF.getOutErrors());
+                    data.put("networkIF." + i + ".packetsRecv", networkIF.getPacketsRecv());
+                    data.put("networkIF." + i + ".packetsSent", networkIF.getPacketsSent());
+                    data.put("networkIF." + i + ".speed", networkIF.getSpeed());
+                    data.put("networkIF." + i + ".prefixLengths", Arrays.toString(networkIF.getPrefixLengths()));
+                    data.put("networkIF." + i + ".subnetMasks", Arrays.toString(networkIF.getSubnetMasks()));
+                    data.put("networkIF." + i + ".timeStamp", networkIF.getTimeStamp());
+                    i++;
+                }
+            }
+            // * power sources
+            boolean powerSources = properties.get("powerSources") != null ? Boolean.parseBoolean(properties.get("powerSources").toString()) : true;
+            if (powerSources) {
+                int i = 0;
+                for (PowerSource powerSource : hardwareAbstractionLayer.getPowerSources()) {
+                    data.put("powerSource." + i + ".amperage", powerSource.getAmperage());
+                    data.put("powerSource." + i + ".capacityUnits", powerSource.getCapacityUnits());
+                    data.put("powerSource." + i + ".chemistry", powerSource.getChemistry());
+                    data.put("powerSource." + i + ".currentCapacity", powerSource.getCurrentCapacity());
+                    data.put("powerSource." + i + ".cycleCount", powerSource.getCycleCount());
+                    data.put("powerSource." + i + ".designCapacity", powerSource.getDesignCapacity());
+                    data.put("powerSource." + i + ".deviceName", powerSource.getDeviceName());
+                    data.put("powerSource." + i + ".manufactureDate", powerSource.getManufactureDate());
+                    data.put("powerSource." + i + ".manufacturer", powerSource.getManufacturer());
+                    data.put("powerSource." + i + ".maxCapacity", powerSource.getMaxCapacity());
+                    data.put("powerSource." + i + ".name", powerSource.getName());
+                    data.put("powerSource." + i + ".powerUsageRate", powerSource.getPowerUsageRate());
+                    data.put("powerSource." + i + ".remainingCapacityPercent", powerSource.getRemainingCapacityPercent());
+                    data.put("powerSource." + i + ".serialNumber", powerSource.getSerialNumber());
+                    data.put("powerSource." + i + ".temperature", powerSource.getTemperature());
+                    data.put("powerSource." + i + ".timeRemainingEstimated", powerSource.getTimeRemainingEstimated());
+                    data.put("powerSource." + i + ".powerUsageRate", powerSource.getPowerUsageRate());
+                    data.put("powerSource." + i + ".timeRemainingInstance", powerSource.getTimeRemainingInstant());
+                    data.put("powerSource." + i + ".voltage", powerSource.getVoltage());
+                    i++;
+                }
+            }
+            // * sound cards
+            boolean soundCards = properties.get("soundCards") != null ? Boolean.parseBoolean(properties.get("soundCards").toString()) : true;
+            if (soundCards) {
+                int i = 0;
+                for (SoundCard soundCard : hardwareAbstractionLayer.getSoundCards()) {
+                    data.put("soundCard." + i + ".codec", soundCard.getCodec());
+                    data.put("soundCard." + i + ".driverVersion", soundCard.getDriverVersion());
+                    data.put("soundCard." + i + ".name", soundCard.getName());
+                    i++;
+                }
+            }
+            // * sensors
+            boolean sensors = properties.get("sensors") != null ? Boolean.parseBoolean(properties.get("sensors").toString()) : true;
+            if (sensors) {
+                data.put("sensors.cpuTemperature", hardwareAbstractionLayer.getSensors().getCpuTemperature());
+                data.put("sensors.cpuVoltage", hardwareAbstractionLayer.getSensors().getCpuVoltage());
+                data.put("sensors.fanSpeeds", Arrays.toString(hardwareAbstractionLayer.getSensors().getFanSpeeds()));
+            }
+            // * USB
+            boolean usbDevices = properties.get("usbDevices") != null ? Boolean.parseBoolean(properties.get("usbDevices").toString()) : true;
+            if (usbDevices) {
+                int i = 0;
+                for (UsbDevice usbDevice : hardwareAbstractionLayer.getUsbDevices(false)) {
+                    data.put("usbDevice." + i + ".name", usbDevice.getName());
+                    data.put("usbDevice." + i + ".productId", usbDevice.getProductId());
+                    data.put("usbDevice." + i + ".serialNumber", usbDevice.getSerialNumber());
+                    data.put("usbDevice." + i + ".uniqueDeviceId", usbDevice.getUniqueDeviceId());
+                    data.put("usbDevice." + i + ".vendor", usbDevice.getVendor());
+                    data.put("usbDevice." + i + ".vendorId", usbDevice.getVendorId());
+                    i++;
+                }
+            }
+
+            // OS
+            boolean operatingSystem = properties.get("operatingSystem") != null ? Boolean.parseBoolean(properties.get("operatingSystem").toString()) : true;
+            if (operatingSystem) {
+                OperatingSystem os = systemInfo.getOperatingSystem();
+                data.put("operatingSystem.bitness", os.getBitness());
+                data.put("operatingSystem.family", os.getFamily());
+                data.put("operatingSystem.manufacturer", os.getManufacturer());
+                data.put("operatingSystem.processCount", os.getProcessCount());
+                data.put("operatingSystem.processId", os.getProcessId());
+                data.put("operatingSystem.systemBootTime", os.getSystemBootTime());
+                data.put("operatingSystem.systemUptime", os.getSystemUptime());
+                data.put("operatingSystem.threadCount", os.getThreadCount());
+                data.put("operatingSystem.versionInfo", os.getVersionInfo());
+                data.put("operatingSystem.elevated", os.isElevated());
+                data.put("operatingSystem.versionInfo.codeName", os.getVersionInfo().getCodeName());
+                data.put("operatingSystem.versionInfo.buildNumber", os.getVersionInfo().getBuildNumber());
+                data.put("operatingSystem.versionInfo.version", os.getVersionInfo().getVersion());
+                // filesystem
+                boolean fileSystems = properties.get("operatingSystem.fileSystems") != null ? Boolean.parseBoolean(properties.get("operatingSystem.fileSystems").toString()) : true;
+                if (fileSystems) {
+                    data.put("operatingSystem.fileSystem.maxFileDescriptors", os.getFileSystem().getMaxFileDescriptors());
+                    data.put("operatingSystem.fileSystem.openFileDescriptors", os.getFileSystem().getOpenFileDescriptors());
+                    int i = 0;
+                    for (OSFileStore fileStore : os.getFileSystem().getFileStores()) {
+                        data.put("operatingSystem.fileSystem." + i + ".description", fileStore.getDescription());
+                        data.put("operatingSystem.fileSystem." + i + ".freeInodes", fileStore.getFreeInodes());
+                        data.put("operatingSystem.fileSystem." + i + ".freeSpace", fileStore.getFreeSpace());
+                        data.put("operatingSystem.fileSystem." + i + ".label", fileStore.getLabel());
+                        data.put("operatingSystem.fileSystem." + i + ".logicalVolume", fileStore.getLogicalVolume());
+                        data.put("operatingSystem.fileSystem." + i + ".mount", fileStore.getMount());
+                        data.put("operatingSystem.fileSystem." + i + ".name", fileStore.getName());
+                        data.put("operatingSystem.fileSystem." + i + ".options", fileStore.getOptions());
+                        data.put("operatingSystem.fileSystem." + i + ".totalInodes", fileStore.getTotalInodes());
+                        data.put("operatingSystem.fileSystem." + i + ".totalSpace", fileStore.getTotalSpace());
+                        data.put("operatingSystem.fileSystem." + i + ".type", fileStore.getType());
+                        data.put("operatingSystem.fileSystem." + i + ".usableSpace", fileStore.getUsableSpace());
+                        data.put("operatingSystem.fileSystem." + i + ".uuid", fileStore.getUUID());
+                        data.put("operatingSystem.fileSystem." + i + ".volume", fileStore.getVolume());
+                        i++;
+                    }
+                }
+                // network params
+                boolean networkParams = properties.get("operatingSystem.networkParams") != null ? Boolean.parseBoolean(properties.get("operatingSystem.networkParams").toString()) : true;
+                if (networkParams) {
+                    data.put("operatingSystem.networkParams.dnsServers", Arrays.toString(os.getNetworkParams().getDnsServers()));
+                    data.put("operatingSystem.networkParams.domainName", os.getNetworkParams().getDomainName());
+                    data.put("operatingSystem.networkParams.hostName", os.getNetworkParams().getHostName());
+                    data.put("operatingSystem.networkParams.IPv4DefaultGateway", os.getNetworkParams().getIpv4DefaultGateway());
+                    data.put("operatingSystem.networkParams.IPv6DefaultGateway", os.getNetworkParams().getIpv6DefaultGateway());
+                }
+                // processes
+                boolean processes = properties.get("operatingSystem.processes") != null ? Boolean.parseBoolean(properties.get("operatingSystem.processes").toString()) : true;
+                if (processes) {
+                    for (OSProcess process : os.getProcesses()) {
+                        int pid = process.getProcessID();
+                        data.put("operatingSystem.process." + pid + ".pid", pid);
+                        data.put("operatingSystem.process." + pid + ".bitness", process.getBitness());
+                        data.put("operatingSystem.process." + pid + ".bytesRead", process.getBytesRead());
+                        data.put("operatingSystem.process." + pid + ".bytesWritten", process.getBytesWritten());
+                        data.put("operatingSystem.process." + pid + ".commandLine", process.getCommandLine());
+                        data.put("operatingSystem.process." + pid + ".currentWorkingDirectory", process.getCurrentWorkingDirectory());
+                        data.put("operatingSystem.process." + pid + ".group", process.getGroup());
+                        data.put("operatingSystem.process." + pid + ".groupID", process.getGroupID());
+                        data.put("operatingSystem.process." + pid + ".kernelTime", process.getKernelTime());
+                        data.put("operatingSystem.process." + pid + ".name", process.getName());
+                        data.put("operatingSystem.process." + pid + ".openFiles", process.getOpenFiles());
+                        data.put("operatingSystem.process." + pid + ".parentProcessID", process.getParentProcessID());
+                        data.put("operatingSystem.process." + pid + ".path", process.getPath());
+                        data.put("operatingSystem.process." + pid + ".priority", process.getPriority());
+                        data.put("operatingSystem.process." + pid + ".processCpuLoadCumulative", process.getProcessCpuLoadCumulative());
+                        data.put("operatingSystem.process." + pid + ".residentSetSize", process.getResidentSetSize());
+                        data.put("operatingSystem.process." + pid + ".startTime", process.getStartTime());
+                        data.put("operatingSystem.process." + pid + ".state", process.getState());
+                        data.put("operatingSystem.process." + pid + ".threadCount", process.getThreadCount());
+                        data.put("operatingSystem.process." + pid + ".upTime", process.getUpTime());
+                        data.put("operatingSystem.process." + pid + ".user", process.getUser());
+                        data.put("operatingSystem.process." + pid + ".userID", process.getUserID());
+                        data.put("operatingSystem.process." + pid + ".userTime", process.getUserTime());
+                        data.put("operatingSystem.process." + pid + ".virtualSize", process.getVirtualSize());
+                    }
+                }
+                // services
+                boolean services = properties.get("operatingSystem.services") != null ? Boolean.parseBoolean(properties.get("operatingSystem.services").toString()) : true;
+                if (services) {
+                    for (OSService service : os.getServices()) {
+                        int pid = service.getProcessID();
+                        data.put("operatingSystem.service." + pid + ".pid", pid);
+                        data.put("operatingSystem.service." + pid + ".name", service.getName());
+                        data.put("operatingSystem.service." + pid + ".state", service.getState());
+                    }
+                }
+            }
+
+            PropertiesPreparator.prepare(data, properties);
+
+            dispatcher.postEvent(new Event("decanter/collect/ohsi", data));
+        } catch (Exception e) {
+            LOGGER.warn("Can't get oshi system metrics", e);
+        }
+    }
+
+    /**
+     * Visible for testing.
+     */
+    public void setDispatcher(EventAdmin dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+}
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
new file mode 100644
index 0000000..8936848
--- /dev/null
+++ b/collector/oshi/src/test/java/org/apache/karaf/decanter/collector/oshi/OshiCollectorTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.decanter.collector.oshi;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+public class OshiCollectorTest {
+
+    @Test
+    public void test() throws Exception {
+        DispatcherMock dispatcherMock = new DispatcherMock();
+
+        OshiCollector collector = new OshiCollector();
+        collector.setDispatcher(dispatcherMock);
+        collector.activate(new Hashtable<>());
+
+        collector.run();
+
+        Assert.assertEquals(1, dispatcherMock.postedEvents.size());
+
+        Event event = dispatcherMock.postedEvents.get(0);
+        for (String property : event.getPropertyNames()) {
+            System.out.println(property + ":" + event.getProperty(property));
+        }
+    }
+
+    class DispatcherMock implements EventAdmin {
+
+        public List<Event> postedEvents = new ArrayList<>();
+        public List<Event> sentEvents = new ArrayList<>();
+
+        @Override
+        public void postEvent(Event event) {
+            this.postedEvents.add(event);
+        }
+
+        @Override
+        public void sendEvent(Event event) {
+            this.sentEvents.add(event);
+        }
+    }
+
+}
diff --git a/collector/pom.xml b/collector/pom.xml
index 0b426bf..f494c23 100644
--- a/collector/pom.xml
+++ b/collector/pom.xml
@@ -45,6 +45,7 @@
         <module>log</module>
         <module>log4j-socket</module>
         <module>mqtt</module>
+        <module>oshi</module>
         <module>process</module>
         <module>rest</module>
         <module>rest-servlet</module>
diff --git a/manual/src/main/asciidoc/user-guide/collectors.adoc b/manual/src/main/asciidoc/user-guide/collectors.adoc
index 72ac320..a7a0aa2 100644
--- a/manual/src/main/asciidoc/user-guide/collectors.adoc
+++ b/manual/src/main/asciidoc/user-guide/collectors.adoc
@@ -528,7 +528,69 @@ Decanter also provides `DecanterEventNotifier` implementing a Camel event notifi
 
 It's very similar to the Decanter Camel Tracer. You can control the camel contexts and routes to which you want to trap events.
 
-==== System
+==== System (oshi)
+
+The oshi collector is a system collector (polled) that periodically retrieve all details about the hardware and the operating system.
+
+This collector gets lot of details about the machine.
+
+The `decanter-collector-oshi` feature installs the oshi system collector:
+
+----
+karaf@root()> feature:install decanter-collector-oshi
+----
+
+This feature installs a default `etc/org.apache.karaf.decanter.collector.oshi.cfg` configuration file containing:
+
+----
+################################################################################
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+################################################################################
+
+#
+# Decanter oshi (system) collector
+#
+
+# computerSystem=true
+# computerSystem.baseboard=true
+# computerSystem.firmware=true
+# memory=true
+# processors=true
+# processors.logical=true
+# displays=true
+# disks=true
+# disks.partitions=true
+# graphicsCards=true
+# networkIFs=true
+# powerSources=true
+# soundCards=true
+# sensors=true
+# usbDevices=true
+# operatingSystem=true
+# operatingSystem.fileSystems=true
+# operatingSystem.networkParams=true
+# operatingSystem.processes=true
+# operatingSystem.services=true
+----
+
+By default, the oshi collector gets all details about the machine. You can filter what you want to harvest in this configuration file.
+
+==== System (script)
 
 The system collector is a polled collector (periodically executed by the Decanter Scheduler).