View Javadoc
1   /*
2    * Copyright 2016-2024 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi;
6   
7   import static org.hamcrest.MatcherAssert.assertThat;
8   import static org.hamcrest.Matchers.is;
9   import static org.hamcrest.Matchers.not;
10  
11  import java.time.Instant;
12  import java.util.ArrayList;
13  import java.util.Arrays;
14  import java.util.HashMap;
15  import java.util.List;
16  import java.util.Locale;
17  import java.util.Map;
18  import java.util.Map.Entry;
19  import java.util.stream.Collectors;
20  
21  import org.junit.jupiter.api.Test;
22  import org.slf4j.Logger;
23  import org.slf4j.LoggerFactory;
24  
25  import oshi.hardware.CentralProcessor;
26  import oshi.hardware.CentralProcessor.PhysicalProcessor;
27  import oshi.hardware.CentralProcessor.ProcessorCache;
28  import oshi.hardware.CentralProcessor.TickType;
29  import oshi.hardware.ComputerSystem;
30  import oshi.hardware.Display;
31  import oshi.hardware.GlobalMemory;
32  import oshi.hardware.GraphicsCard;
33  import oshi.hardware.HWDiskStore;
34  import oshi.hardware.HWPartition;
35  import oshi.hardware.HardwareAbstractionLayer;
36  import oshi.hardware.LogicalVolumeGroup;
37  import oshi.hardware.NetworkIF;
38  import oshi.hardware.PhysicalMemory;
39  import oshi.hardware.PowerSource;
40  import oshi.hardware.Sensors;
41  import oshi.hardware.SoundCard;
42  import oshi.hardware.UsbDevice;
43  import oshi.hardware.VirtualMemory;
44  import oshi.software.os.FileSystem;
45  import oshi.software.os.InternetProtocolStats;
46  import oshi.software.os.NetworkParams;
47  import oshi.software.os.OSFileStore;
48  import oshi.software.os.OSProcess;
49  import oshi.software.os.OSService;
50  import oshi.software.os.OSSession;
51  import oshi.software.os.OperatingSystem;
52  import oshi.software.os.OperatingSystem.ProcessFiltering;
53  import oshi.software.os.OperatingSystem.ProcessSorting;
54  import oshi.util.FormatUtil;
55  import oshi.util.Util;
56  
57  /**
58   * A demonstration of access to many of OSHI's capabilities
59   */
60  public class SystemInfoTest { // NOSONAR squid:S5786
61  
62      private static final Logger logger = LoggerFactory.getLogger(SystemInfoTest.class);
63  
64      static List<String> oshi = new ArrayList<>();
65  
66      /**
67       * Test that this platform is implemented..
68       */
69      @Test
70      void testPlatformEnum() {
71          assertThat("Unsupported OS", SystemInfo.getCurrentPlatform(), is(not(PlatformEnum.UNKNOWN)));
72          // Exercise the main method
73          main(null);
74      }
75  
76      /**
77       * The main method, demonstrating use of classes.
78       *
79       * @param args the arguments (unused)
80       */
81      public static void main(String[] args) {
82  
83          logger.info("Initializing System...");
84          SystemInfo si = new SystemInfo();
85  
86          HardwareAbstractionLayer hal = si.getHardware();
87          OperatingSystem os = si.getOperatingSystem();
88  
89          printOperatingSystem(os);
90  
91          logger.info("Checking computer system...");
92          printComputerSystem(hal.getComputerSystem());
93  
94          logger.info("Checking Processor...");
95          printProcessor(hal.getProcessor());
96  
97          logger.info("Checking Memory...");
98          printMemory(hal.getMemory());
99  
100         logger.info("Checking CPU...");
101         printCpu(hal.getProcessor());
102 
103         logger.info("Checking Processes...");
104         printProcesses(os, hal.getMemory());
105 
106         logger.info("Checking Services...");
107         printServices(os);
108 
109         logger.info("Checking Sensors...");
110         printSensors(hal.getSensors());
111 
112         logger.info("Checking Power sources...");
113         printPowerSources(hal.getPowerSources());
114 
115         logger.info("Checking Disks...");
116         printDisks(hal.getDiskStores());
117 
118         logger.info("Checking Logical Volume Groups ...");
119         printLVgroups(hal.getLogicalVolumeGroups());
120 
121         logger.info("Checking File System...");
122         printFileSystem(os.getFileSystem());
123 
124         logger.info("Checking Network interfaces...");
125         printNetworkInterfaces(hal.getNetworkIFs());
126 
127         logger.info("Checking Network parameters...");
128         printNetworkParameters(os.getNetworkParams());
129 
130         logger.info("Checking IP statistics...");
131         printInternetProtocolStats(os.getInternetProtocolStats());
132 
133         logger.info("Checking Displays...");
134         printDisplays(hal.getDisplays());
135 
136         logger.info("Checking USB Devices...");
137         printUsbDevices(hal.getUsbDevices(true));
138 
139         logger.info("Checking Sound Cards...");
140         printSoundCards(hal.getSoundCards());
141 
142         logger.info("Checking Graphics Cards...");
143         printGraphicsCards(hal.getGraphicsCards());
144 
145         StringBuilder output = new StringBuilder();
146         for (String line : oshi) {
147             output.append(line);
148             if (line != null && !line.endsWith("\n")) {
149                 output.append('\n');
150             }
151         }
152         logger.info("Printing Operating System and Hardware Info:{}{}", '\n', output);
153     }
154 
155     private static void printOperatingSystem(final OperatingSystem os) {
156         oshi.add(String.valueOf(os));
157         oshi.add("Booted: " + Instant.ofEpochSecond(os.getSystemBootTime()));
158         oshi.add("Uptime: " + FormatUtil.formatElapsedSecs(os.getSystemUptime()));
159         oshi.add("Running with" + (os.isElevated() ? "" : "out") + " elevated permissions.");
160         oshi.add("Sessions:");
161         for (OSSession s : os.getSessions()) {
162             oshi.add(" " + s.toString());
163         }
164     }
165 
166     private static void printComputerSystem(final ComputerSystem computerSystem) {
167         oshi.add("System: " + computerSystem.toString());
168         oshi.add(" Firmware: " + computerSystem.getFirmware().toString());
169         oshi.add(" Baseboard: " + computerSystem.getBaseboard().toString());
170     }
171 
172     private static void printProcessor(CentralProcessor processor) {
173         oshi.add(processor.toString());
174 
175         Map<Integer, Integer> efficiencyCount = new HashMap<>();
176         int maxEfficiency = 0;
177         for (PhysicalProcessor cpu : processor.getPhysicalProcessors()) {
178             int eff = cpu.getEfficiency();
179             efficiencyCount.merge(eff, 1, Integer::sum);
180             if (eff > maxEfficiency) {
181                 maxEfficiency = eff;
182             }
183         }
184         oshi.add(" Topology:");
185         oshi.add(String.format(Locale.ROOT, "  %7s %4s %4s %4s %4s %4s", "LogProc", "P/E", "Proc", "Pkg", "NUMA",
186                 "PGrp"));
187         for (PhysicalProcessor cpu : processor.getPhysicalProcessors()) {
188             oshi.add(String.format(Locale.ROOT, "  %7s %4s %4d %4s %4d %4d",
189                     processor.getLogicalProcessors().stream()
190                             .filter(p -> p.getPhysicalProcessorNumber() == cpu.getPhysicalProcessorNumber())
191                             .filter(p -> p.getPhysicalPackageNumber() == cpu.getPhysicalPackageNumber())
192                             .map(p -> Integer.toString(p.getProcessorNumber())).collect(Collectors.joining(",")),
193                     cpu.getEfficiency() == maxEfficiency ? "P" : "E", cpu.getPhysicalProcessorNumber(),
194                     cpu.getPhysicalPackageNumber(),
195                     processor.getLogicalProcessors().stream()
196                             .filter(p -> p.getPhysicalProcessorNumber() == cpu.getPhysicalProcessorNumber())
197                             .filter(p -> p.getPhysicalPackageNumber() == cpu.getPhysicalPackageNumber())
198                             .mapToInt(p -> p.getNumaNode()).findFirst().orElse(0),
199                     processor.getLogicalProcessors().stream()
200                             .filter(p -> p.getPhysicalProcessorNumber() == cpu.getPhysicalProcessorNumber())
201                             .filter(p -> p.getPhysicalPackageNumber() == cpu.getPhysicalPackageNumber())
202                             .mapToInt(p -> p.getProcessorGroup()).findFirst().orElse(0)));
203         }
204         List<ProcessorCache> caches = processor.getProcessorCaches();
205         if (!caches.isEmpty()) {
206             oshi.add(" Caches:");
207         }
208         for (int i = 0; i < caches.size(); i++) {
209             ProcessorCache cache = caches.get(i);
210             boolean perCore = cache.getLevel() < 3;
211             boolean pCore = perCore && i < caches.size() - 1 && cache.getLevel() == caches.get(i + 1).getLevel()
212                     && cache.getType() == caches.get(i + 1).getType();
213             boolean eCore = perCore && i > 0 && cache.getLevel() == caches.get(i - 1).getLevel()
214                     && cache.getType() == caches.get(i - 1).getType();
215             StringBuilder sb = new StringBuilder("  ").append(cache);
216             if (perCore) {
217                 sb.append(" (per ");
218                 if (pCore) {
219                     sb.append("P-");
220                 } else if (eCore) {
221                     sb.append("E-");
222                 }
223                 sb.append("core)");
224             }
225             oshi.add(sb.toString());
226         }
227     }
228 
229     private static void printMemory(GlobalMemory memory) {
230         oshi.add("Physical Memory: \n " + memory.toString());
231         VirtualMemory vm = memory.getVirtualMemory();
232         oshi.add("Virtual Memory: \n " + vm.toString());
233         List<PhysicalMemory> pmList = memory.getPhysicalMemory();
234         if (!pmList.isEmpty()) {
235             oshi.add("Physical Memory: ");
236             for (PhysicalMemory pm : pmList) {
237                 oshi.add(" " + pm.toString());
238             }
239         }
240     }
241 
242     private static void printCpu(CentralProcessor processor) {
243         oshi.add("Context Switches/Interrupts: " + processor.getContextSwitches() + " / " + processor.getInterrupts());
244 
245         long[] prevTicks = processor.getSystemCpuLoadTicks();
246         long[][] prevProcTicks = processor.getProcessorCpuLoadTicks();
247         oshi.add("CPU, IOWait, and IRQ ticks @ 0 sec:" + Arrays.toString(prevTicks));
248         // Wait a second...
249         Util.sleep(1000);
250         long[] ticks = processor.getSystemCpuLoadTicks();
251         oshi.add("CPU, IOWait, and IRQ ticks @ 1 sec:" + Arrays.toString(ticks));
252         long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
253         long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
254         long sys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
255         long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
256         long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
257         long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
258         long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
259         long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
260         long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;
261 
262         oshi.add(String.format(Locale.ROOT,
263                 "User: %.1f%% Nice: %.1f%% System: %.1f%% Idle: %.1f%% IOwait: %.1f%% IRQ: %.1f%% SoftIRQ: %.1f%% Steal: %.1f%%",
264                 100d * user / totalCpu, 100d * nice / totalCpu, 100d * sys / totalCpu, 100d * idle / totalCpu,
265                 100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu));
266         oshi.add(String.format(Locale.ROOT, "CPU load: %.1f%%",
267                 processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100));
268         double[] loadAverage = processor.getSystemLoadAverage(3);
269         oshi.add("CPU load averages:"
270                 + (loadAverage[0] < 0 ? " N/A" : String.format(Locale.ROOT, " %.2f", loadAverage[0]))
271                 + (loadAverage[1] < 0 ? " N/A" : String.format(Locale.ROOT, " %.2f", loadAverage[1]))
272                 + (loadAverage[2] < 0 ? " N/A" : String.format(Locale.ROOT, " %.2f", loadAverage[2])));
273         // per core CPU
274         StringBuilder procCpu = new StringBuilder("CPU load per processor:");
275         double[] load = processor.getProcessorCpuLoadBetweenTicks(prevProcTicks);
276         for (double avg : load) {
277             procCpu.append(String.format(Locale.ROOT, " %.1f%%", avg * 100));
278         }
279         oshi.add(procCpu.toString());
280         long freq = processor.getProcessorIdentifier().getVendorFreq();
281         if (freq > 0) {
282             oshi.add("Vendor Frequency: " + FormatUtil.formatHertz(freq));
283         }
284         freq = processor.getMaxFreq();
285         if (freq > 0) {
286             oshi.add("Max Frequency: " + FormatUtil.formatHertz(freq));
287         }
288         long[] freqs = processor.getCurrentFreq();
289         if (freqs[0] > 0) {
290             StringBuilder sb = new StringBuilder("Current Frequencies: ");
291             for (int i = 0; i < freqs.length; i++) {
292                 if (i > 0) {
293                     sb.append(", ");
294                 }
295                 sb.append(FormatUtil.formatHertz(freqs[i]));
296             }
297             oshi.add(sb.toString());
298         }
299         if (!processor.getFeatureFlags().isEmpty()) {
300             oshi.add("CPU Features:");
301             for (String features : processor.getFeatureFlags()) {
302                 oshi.add("  " + features);
303             }
304         }
305     }
306 
307     private static void printProcesses(OperatingSystem os, GlobalMemory memory) {
308         OSProcess myProc = os.getProcess(os.getProcessId());
309         // current process will never be null. Other code should check for null here
310         oshi.add(
311                 "My PID: " + myProc.getProcessID() + " with affinity " + Long.toBinaryString(myProc.getAffinityMask()));
312         oshi.add("My TID: " + os.getThreadId() + " with details " + os.getCurrentThread());
313 
314         oshi.add("Processes: " + os.getProcessCount() + ", Threads: " + os.getThreadCount());
315         // Sort by highest CPU
316         List<OSProcess> procs = os.getProcesses(ProcessFiltering.ALL_PROCESSES, ProcessSorting.CPU_DESC, 5);
317         oshi.add("   PID  %CPU %MEM       VSZ       RSS Name");
318         for (int i = 0; i < procs.size(); i++) {
319             OSProcess p = procs.get(i);
320             oshi.add(String.format(Locale.ROOT, " %5d %5.1f %4.1f %9s %9s %s", p.getProcessID(),
321                     100d * (p.getKernelTime() + p.getUserTime()) / p.getUpTime(),
322                     100d * p.getResidentSetSize() / memory.getTotal(), FormatUtil.formatBytes(p.getVirtualSize()),
323                     FormatUtil.formatBytes(p.getResidentSetSize()), p.getName()));
324         }
325         OSProcess p = os.getProcess(os.getProcessId());
326         oshi.add("Current process arguments: ");
327         for (String s : p.getArguments()) {
328             oshi.add("  " + s);
329         }
330         oshi.add("Current process environment: ");
331         for (Entry<String, String> e : p.getEnvironmentVariables().entrySet()) {
332             oshi.add("  " + e.getKey() + "=" + e.getValue());
333         }
334     }
335 
336     private static void printServices(OperatingSystem os) {
337         oshi.add("Services: ");
338         oshi.add("   PID   State   Name");
339         // DO 5 each of running and stopped
340         int i = 0;
341         for (OSService s : os.getServices()) {
342             if (s.getState().equals(OSService.State.RUNNING) && i++ < 5) {
343                 oshi.add(String.format(Locale.ROOT, " %5d  %7s  %s", s.getProcessID(), s.getState(), s.getName()));
344             }
345         }
346         i = 0;
347         for (OSService s : os.getServices()) {
348             if (s.getState().equals(OSService.State.STOPPED) && i++ < 5) {
349                 oshi.add(String.format(Locale.ROOT, " %5d  %7s  %s", s.getProcessID(), s.getState(), s.getName()));
350             }
351         }
352     }
353 
354     private static void printSensors(Sensors sensors) {
355         oshi.add("Sensors: " + sensors.toString());
356     }
357 
358     private static void printPowerSources(List<PowerSource> list) {
359         StringBuilder sb = new StringBuilder("Power Sources: ");
360         if (list.isEmpty()) {
361             sb.append("Unknown");
362         }
363         for (PowerSource powerSource : list) {
364             sb.append("\n ").append(powerSource.toString());
365         }
366         oshi.add(sb.toString());
367     }
368 
369     private static void printDisks(List<HWDiskStore> list) {
370         oshi.add("Disks:");
371         for (HWDiskStore disk : list) {
372             oshi.add(" " + disk.toString());
373 
374             List<HWPartition> partitions = disk.getPartitions();
375             for (HWPartition part : partitions) {
376                 oshi.add(" |-- " + part.toString());
377             }
378         }
379 
380     }
381 
382     private static void printLVgroups(List<LogicalVolumeGroup> list) {
383         if (!list.isEmpty()) {
384             oshi.add("Logical Volume Groups:");
385             for (LogicalVolumeGroup lvg : list) {
386                 oshi.add(" " + lvg.toString());
387             }
388         }
389     }
390 
391     private static void printFileSystem(FileSystem fileSystem) {
392         oshi.add("File System:");
393 
394         oshi.add(String.format(Locale.ROOT, " File Descriptors: %d/%d", fileSystem.getOpenFileDescriptors(),
395                 fileSystem.getMaxFileDescriptors()));
396 
397         for (OSFileStore fs : fileSystem.getFileStores()) {
398             long usable = fs.getUsableSpace();
399             long total = fs.getTotalSpace();
400             oshi.add(String.format(Locale.ROOT,
401                     " %s (%s) [%s] %s of %s free (%.1f%%), %s of %s files free (%.1f%%) is %s "
402                             + (fs.getLogicalVolume() != null && fs.getLogicalVolume().length() > 0 ? "[%s]" : "%s")
403                             + " and is mounted at %s",
404                     fs.getName(), fs.getDescription().isEmpty() ? "file system" : fs.getDescription(), fs.getType(),
405                     FormatUtil.formatBytes(usable), FormatUtil.formatBytes(fs.getTotalSpace()), 100d * usable / total,
406                     FormatUtil.formatValue(fs.getFreeInodes(), ""), FormatUtil.formatValue(fs.getTotalInodes(), ""),
407                     100d * fs.getFreeInodes() / fs.getTotalInodes(), fs.getVolume(), fs.getLogicalVolume(),
408                     fs.getMount()));
409         }
410     }
411 
412     private static void printNetworkInterfaces(List<NetworkIF> list) {
413         StringBuilder sb = new StringBuilder("Network Interfaces:");
414         if (list.isEmpty()) {
415             sb.append(" Unknown");
416         } else {
417             for (NetworkIF net : list) {
418                 sb.append("\n ").append(net.toString());
419             }
420         }
421         oshi.add(sb.toString());
422     }
423 
424     private static void printNetworkParameters(NetworkParams networkParams) {
425         oshi.add("Network parameters:\n " + networkParams.toString());
426     }
427 
428     private static void printInternetProtocolStats(InternetProtocolStats ip) {
429         oshi.add("Internet Protocol statistics:");
430         oshi.add(" TCPv4: " + ip.getTCPv4Stats());
431         oshi.add(" TCPv6: " + ip.getTCPv6Stats());
432         oshi.add(" UDPv4: " + ip.getUDPv4Stats());
433         oshi.add(" UDPv6: " + ip.getUDPv6Stats());
434     }
435 
436     private static void printDisplays(List<Display> list) {
437         oshi.add("Displays:");
438         int i = 0;
439         for (Display display : list) {
440             oshi.add(" Display " + i + ":");
441             oshi.add(String.valueOf(display));
442             i++;
443         }
444     }
445 
446     private static void printUsbDevices(List<UsbDevice> list) {
447         oshi.add("USB Devices:");
448         for (UsbDevice usbDevice : list) {
449             oshi.add(String.valueOf(usbDevice));
450         }
451     }
452 
453     private static void printSoundCards(List<SoundCard> list) {
454         oshi.add("Sound Cards:");
455         for (SoundCard card : list) {
456             oshi.add(" " + String.valueOf(card));
457         }
458     }
459 
460     private static void printGraphicsCards(List<GraphicsCard> list) {
461         oshi.add("Graphics Cards:");
462         if (list.isEmpty()) {
463             oshi.add(" None detected.");
464         } else {
465             for (GraphicsCard card : list) {
466                 oshi.add(" " + String.valueOf(card));
467             }
468         }
469     }
470 }