1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package psiprobe.controllers.oshi;
36
37 import jakarta.servlet.http.HttpServletRequest;
38 import jakarta.servlet.http.HttpServletResponse;
39
40 import java.time.Instant;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.List;
44 import java.util.Map.Entry;
45
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Value;
49 import org.springframework.stereotype.Controller;
50 import org.springframework.web.bind.annotation.RequestMapping;
51 import org.springframework.web.servlet.ModelAndView;
52
53 import oshi.SystemInfo;
54 import oshi.hardware.CentralProcessor;
55 import oshi.hardware.CentralProcessor.PhysicalProcessor;
56 import oshi.hardware.CentralProcessor.TickType;
57 import oshi.hardware.ComputerSystem;
58 import oshi.hardware.Display;
59 import oshi.hardware.GlobalMemory;
60 import oshi.hardware.GraphicsCard;
61 import oshi.hardware.HWDiskStore;
62 import oshi.hardware.HWPartition;
63 import oshi.hardware.HardwareAbstractionLayer;
64 import oshi.hardware.LogicalVolumeGroup;
65 import oshi.hardware.NetworkIF;
66 import oshi.hardware.PhysicalMemory;
67 import oshi.hardware.PowerSource;
68 import oshi.hardware.Sensors;
69 import oshi.hardware.SoundCard;
70 import oshi.hardware.UsbDevice;
71 import oshi.hardware.VirtualMemory;
72 import oshi.software.os.FileSystem;
73 import oshi.software.os.InternetProtocolStats;
74 import oshi.software.os.NetworkParams;
75 import oshi.software.os.OSFileStore;
76 import oshi.software.os.OSProcess;
77 import oshi.software.os.OSService;
78 import oshi.software.os.OSSession;
79 import oshi.software.os.OperatingSystem;
80 import oshi.software.os.OperatingSystem.ProcessFiltering;
81 import oshi.software.os.OperatingSystem.ProcessSorting;
82 import oshi.util.FormatUtil;
83 import oshi.util.PlatformEnum;
84 import oshi.util.Util;
85
86 import psiprobe.controllers.AbstractTomcatContainerController;
87
88
89
90
91
92
93 @Controller
94 public class OshiController extends AbstractTomcatContainerController {
95
96
97 private static final Logger logger = LoggerFactory.getLogger(OshiController.class);
98
99
100 private static List<String> oshi = new ArrayList<>();
101
102 @RequestMapping(path = "/adm/oshi.htm")
103 @Override
104 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
105 throws Exception {
106 return super.handleRequest(request, response);
107 }
108
109 @Override
110 protected ModelAndView handleRequestInternal(HttpServletRequest request,
111 HttpServletResponse response) throws Exception {
112
113 if (!oshi.isEmpty()) {
114 ModelAndView mv = new ModelAndView(getViewName());
115 mv.addObject("oshi", oshi);
116 return mv;
117 }
118
119
120 oshi.add(
121 "Oshi results are performed as a system dump to screen here using Oshi SystemInfoTest logic.");
122 oshi.add(
123 "Please be advised this is experimental in use and is slow. Resulting data is entirely cached.");
124 oshi.add("Issues with library should be directed to https://github.com/oshi/oshi");
125 oshi.add("For issues with our library usage of Oshi, please submit pull requests");
126 oshi.add("");
127 oshi.add("");
128
129 this.initialize();
130
131 ModelAndView mv = new ModelAndView(getViewName());
132 mv.addObject("oshi", oshi);
133 return mv;
134 }
135
136 @Value("oshi")
137 @Override
138 public void setViewName(String viewName) {
139 super.setViewName(viewName);
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 private void initialize() {
160 logger.debug("Initializing System...");
161 SystemInfo si = new SystemInfo();
162
163
164 if (PlatformEnum.UNKNOWN.equals(PlatformEnum.getCurrentPlatform())) {
165 logger.error("Oshi not supported on current platform");
166 oshi.add("Oshi not supported on current platform");
167 oshi.add("");
168 return;
169 }
170
171 HardwareAbstractionLayer hal = si.getHardware();
172 OperatingSystem os = si.getOperatingSystem();
173
174 printOperatingSystem(os);
175
176 logger.debug("Checking computer system...");
177 printComputerSystem(hal.getComputerSystem());
178
179 logger.debug("Checking Processor...");
180 printProcessor(hal.getProcessor());
181
182 logger.debug("Checking Memory...");
183 printMemory(hal.getMemory());
184
185 logger.debug("Checking CPU...");
186 printCpu(hal.getProcessor());
187
188 logger.debug("Checking Processes...");
189 printProcesses(os, hal.getMemory());
190
191 logger.debug("Checking Services...");
192 printServices(os);
193
194 logger.debug("Checking Sensors...");
195 printSensors(hal.getSensors());
196
197 logger.debug("Checking Power sources...");
198 printPowerSources(hal.getPowerSources());
199
200 logger.debug("Checking Disks...");
201 printDisks(hal.getDiskStores());
202
203 logger.debug("Checking Logical Volume Groups ...");
204 printLogicalVolumegroups(hal.getLogicalVolumeGroups());
205
206 logger.debug("Checking File System...");
207 printFileSystem(os.getFileSystem());
208
209 logger.debug("Checking Network interfaces...");
210 printNetworkInterfaces(hal.getNetworkIFs());
211
212 logger.debug("Checking Network parameters...");
213 printNetworkParameters(os.getNetworkParams());
214
215 logger.debug("Checking IP statistics...");
216 printInternetProtocolStats(os.getInternetProtocolStats());
217
218 logger.debug("Checking Displays...");
219 printDisplays(hal.getDisplays());
220
221 logger.debug("Checking USB Devices...");
222 printUsbDevices(hal.getUsbDevices(true));
223
224 logger.debug("Checking Sound Cards...");
225 printSoundCards(hal.getSoundCards());
226
227 logger.debug("Checking Graphics Cards...");
228 printGraphicsCards(hal.getGraphicsCards());
229
230
231 oshi.add("Finished Operating System and Hardware Info Dump");
232
233 StringBuilder output = new StringBuilder();
234 for (String element : oshi) {
235 output.append(element);
236
237 if (!"\n".equals(element)) {
238 output.append('\n');
239 }
240 }
241 logger.info("Printing Operating System and Hardware Info:{}{}", '\n', output);
242 }
243
244
245
246
247
248
249 private static void printOperatingSystem(final OperatingSystem operatingSystem) {
250 oshi.add(String.valueOf(operatingSystem));
251 oshi.add("Booted: " + Instant.ofEpochSecond(operatingSystem.getSystemBootTime()));
252 oshi.add("Uptime: " + FormatUtil.formatElapsedSecs(operatingSystem.getSystemUptime()));
253 oshi.add(
254 "Running with" + (operatingSystem.isElevated() ? "" : "out") + " elevated permissions.");
255 oshi.add("Sessions:");
256 for (OSSession s : operatingSystem.getSessions()) {
257 oshi.add(" " + s.toString());
258 }
259 }
260
261
262
263
264
265
266 private static void printComputerSystem(final ComputerSystem computerSystem) {
267 oshi.add("System: " + computerSystem.toString());
268 oshi.add(" Firmware: " + computerSystem.getFirmware().toString());
269 oshi.add(" Baseboard: " + computerSystem.getBaseboard().toString());
270 }
271
272
273
274
275
276
277 private static void printProcessor(CentralProcessor processor) {
278 oshi.add(processor.toString());
279 oshi.add(" Cores:");
280 for (PhysicalProcessor p : processor.getPhysicalProcessors()) {
281 oshi.add(
282 " " + (processor.getPhysicalPackageCount() > 1 ? p.getPhysicalPackageNumber() + "," : "")
283 + p.getPhysicalProcessorNumber() + ": efficiency=" + p.getEfficiency() + ", id="
284 + p.getIdString());
285 }
286 }
287
288
289
290
291
292
293 private static void printMemory(GlobalMemory memory) {
294 oshi.add("Physical Memory: \n " + memory.toString());
295 VirtualMemory vm = memory.getVirtualMemory();
296 oshi.add("Virtual Memory: \n " + vm.toString());
297 List<PhysicalMemory> pmList = memory.getPhysicalMemory();
298 if (!pmList.isEmpty()) {
299 oshi.add("Physical Memory: ");
300 for (PhysicalMemory pm : pmList) {
301 oshi.add(" " + pm.toString());
302 }
303 }
304 }
305
306
307
308
309
310
311 private static void printCpu(CentralProcessor processor) {
312 oshi.add("Context Switches/Interrupts: " + processor.getContextSwitches() + " / "
313 + processor.getInterrupts());
314
315 long[] prevTicks = processor.getSystemCpuLoadTicks();
316 oshi.add("CPU, IOWait, and IRQ ticks @ 0 sec:" + Arrays.toString(prevTicks));
317
318 Util.sleep(1000);
319 long[] ticks = processor.getSystemCpuLoadTicks();
320 oshi.add("CPU, IOWait, and IRQ ticks @ 1 sec:" + Arrays.toString(ticks));
321 long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
322 long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
323 long sys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
324 long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
325 long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
326 long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
327 long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
328 long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
329 long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;
330
331 oshi.add(
332 "User: %.1f%% Nice: %.1f%% System: %.1f%% Idle: %.1f%% IOwait: %.1f%% IRQ: %.1f%% SoftIRQ: %.1f%% Steal: %.1f%%"
333 .formatted(100d * user / totalCpu, 100d * nice / totalCpu, 100d * sys / totalCpu,
334 100d * idle / totalCpu, 100d * iowait / totalCpu, 100d * irq / totalCpu,
335 100d * softirq / totalCpu, 100d * steal / totalCpu));
336 oshi.add("CPU load: %.1f%%".formatted(processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100));
337 double[] loadAverage = processor.getSystemLoadAverage(3);
338 oshi.add(
339 "CPU load averages:" + (loadAverage[0] < 0 ? " N/A" : " %.2f".formatted(loadAverage[0]))
340 + (loadAverage[1] < 0 ? " N/A" : " %.2f".formatted(loadAverage[1]))
341 + (loadAverage[2] < 0 ? " N/A" : " %.2f".formatted(loadAverage[2])));
342
343 StringBuilder procCpu = new StringBuilder("CPU load per processor:");
344 long[][] prevProcTicks = processor.getProcessorCpuLoadTicks();
345 double[] load = processor.getProcessorCpuLoadBetweenTicks(prevProcTicks);
346 for (double avg : load) {
347 procCpu.append(" %.1f%%".formatted(avg * 100));
348 }
349 oshi.add(procCpu.toString());
350 long freq = processor.getProcessorIdentifier().getVendorFreq();
351 if (freq > 0) {
352 oshi.add("Vendor Frequency: " + FormatUtil.formatHertz(freq));
353 }
354 freq = processor.getMaxFreq();
355 if (freq > 0) {
356 oshi.add("Max Frequency: " + FormatUtil.formatHertz(freq));
357 }
358 long[] freqs = processor.getCurrentFreq();
359 if (freqs[0] > 0) {
360 StringBuilder sb = new StringBuilder("Current Frequencies: ");
361 for (int i = 0; i < freqs.length; i++) {
362 if (i > 0) {
363 sb.append(", ");
364 }
365 sb.append(FormatUtil.formatHertz(freqs[i]));
366 }
367 oshi.add(sb.toString());
368 }
369 }
370
371
372
373
374
375
376
377 private static void printProcesses(OperatingSystem os, GlobalMemory memory) {
378 OSProcess myProc = os.getProcess(os.getProcessId());
379
380 oshi.add("My PID: " + myProc.getProcessID() + " with affinity "
381 + Long.toBinaryString(myProc.getAffinityMask()));
382 oshi.add("Processes: " + os.getProcessCount() + ", Threads: " + os.getThreadCount());
383
384 List<OSProcess> procs =
385 os.getProcesses(ProcessFiltering.ALL_PROCESSES, ProcessSorting.CPU_DESC, 5);
386 oshi.add(" PID %CPU %MEM VSZ RSS Name");
387 for (int i = 0; i < procs.size() && i < 5; i++) {
388 OSProcess p = procs.get(i);
389 oshi.add(" %5d %5.1f %4.1f %9s %9s %s".formatted(p.getProcessID(),
390 100d * (p.getKernelTime() + p.getUserTime()) / p.getUpTime(),
391 100d * p.getResidentMemory() / memory.getTotal(),
392 FormatUtil.formatBytes(p.getVirtualSize()), FormatUtil.formatBytes(p.getResidentMemory()),
393 p.getName()));
394 }
395 OSProcess p = os.getProcess(os.getProcessId());
396 oshi.add("Current process arguments: ");
397 for (String s : p.getArguments()) {
398 oshi.add(" " + s);
399 }
400 oshi.add("Current process environment: ");
401 for (Entry<String, String> e : p.getEnvironmentVariables().entrySet()) {
402 oshi.add(" " + e.getKey() + '=' + e.getValue());
403 }
404 }
405
406
407
408
409
410
411 private static void printServices(OperatingSystem os) {
412 oshi.add("Services: ");
413 oshi.add(" PID State Name");
414
415 int i = 0;
416 for (OSService s : os.getServices()) {
417 if (s.getState().equals(OSService.State.RUNNING) && i++ < 5) {
418 oshi.add(" %5d %7s %s".formatted(s.getProcessID(), s.getState(), s.getName()));
419 }
420 }
421 i = 0;
422 for (OSService s : os.getServices()) {
423 if (s.getState().equals(OSService.State.STOPPED) && i++ < 5) {
424 oshi.add(" %5d %7s %s".formatted(s.getProcessID(), s.getState(), s.getName()));
425 }
426 }
427 }
428
429
430
431
432
433
434 private static void printSensors(Sensors sensors) {
435 oshi.add("Sensors: " + sensors.toString());
436 }
437
438
439
440
441
442
443 private static void printPowerSources(List<PowerSource> list) {
444 StringBuilder sb = new StringBuilder("Power Sources: ");
445 if (list.isEmpty()) {
446 sb.append("Unknown");
447 }
448 for (PowerSource powerSource : list) {
449 sb.append("\n ").append(powerSource.toString());
450 }
451 oshi.add(sb.toString());
452 }
453
454
455
456
457
458
459 private static void printDisks(List<HWDiskStore> list) {
460 oshi.add("Disks:");
461 for (HWDiskStore disk : list) {
462 oshi.add(" " + disk.toString());
463
464 List<HWPartition> partitions = disk.getPartitions();
465 for (HWPartition part : partitions) {
466 oshi.add(" |-- " + part.toString());
467 }
468 }
469
470 }
471
472
473
474
475
476
477 private static void printLogicalVolumegroups(List<LogicalVolumeGroup> list) {
478 if (!list.isEmpty()) {
479 oshi.add("Logical Volume Groups:");
480 for (LogicalVolumeGroup lvg : list) {
481 oshi.add(" " + lvg.toString());
482 }
483 }
484 }
485
486
487
488
489
490
491 private static void printFileSystem(FileSystem fileSystem) {
492 oshi.add("File System:");
493
494 oshi.add(" File Descriptors: %d/%d".formatted(fileSystem.getOpenFileDescriptors(),
495 fileSystem.getMaxFileDescriptors()));
496
497 for (OSFileStore fs : fileSystem.getFileStores()) {
498 long usable = fs.getUsableSpace();
499 long total = fs.getTotalSpace();
500 oshi.add((" %s (%s) [%s] %s of %s free (%.1f%%), %s of %s files free (%.1f%%) is %s "
501 + (fs.getLogicalVolume() != null && !fs.getLogicalVolume().isEmpty() ? "[%s]" : "%s")
502 + " and is mounted at %s").formatted(fs.getName(),
503 fs.getDescription().isEmpty() ? "file system" : fs.getDescription(), fs.getType(),
504 FormatUtil.formatBytes(usable), FormatUtil.formatBytes(fs.getTotalSpace()),
505 100d * usable / total, FormatUtil.formatValue(fs.getFreeInodes(), ""),
506 FormatUtil.formatValue(fs.getTotalInodes(), ""),
507 100d * fs.getFreeInodes() / fs.getTotalInodes(), fs.getVolume(),
508 fs.getLogicalVolume(), fs.getMount()));
509 }
510 }
511
512
513
514
515
516
517 private static void printNetworkInterfaces(List<NetworkIF> list) {
518 StringBuilder sb = new StringBuilder("Network Interfaces:");
519 if (list.isEmpty()) {
520 sb.append(" Unknown");
521 } else {
522 for (NetworkIF net : list) {
523 sb.append("\n ").append(net.toString());
524 }
525 }
526 oshi.add(sb.toString());
527 }
528
529
530
531
532
533
534 private static void printNetworkParameters(NetworkParams networkParams) {
535 oshi.add("Network parameters:\n " + networkParams.toString());
536 }
537
538
539
540
541
542
543 private static void printInternetProtocolStats(InternetProtocolStats internetProtocolStats) {
544 oshi.add("Internet Protocol statistics:");
545 oshi.add(" TCPv4: " + internetProtocolStats.getTCPv4Stats());
546 oshi.add(" TCPv6: " + internetProtocolStats.getTCPv6Stats());
547 oshi.add(" UDPv4: " + internetProtocolStats.getUDPv4Stats());
548 oshi.add(" UDPv6: " + internetProtocolStats.getUDPv6Stats());
549 }
550
551
552
553
554
555
556 private static void printDisplays(List<Display> list) {
557 oshi.add("Displays:");
558 int i = 0;
559 for (Display display : list) {
560 oshi.add(" Display " + i + ":");
561 oshi.add(String.valueOf(display));
562 i++;
563 }
564 }
565
566
567
568
569
570
571 private static void printUsbDevices(List<UsbDevice> list) {
572 oshi.add("USB Devices:");
573 for (UsbDevice usbDevice : list) {
574 oshi.add(String.valueOf(usbDevice));
575 }
576 }
577
578
579
580
581
582
583 private static void printSoundCards(List<SoundCard> list) {
584 oshi.add("Sound Cards:");
585 for (SoundCard card : list) {
586 oshi.add(" " + String.valueOf(card));
587 }
588 }
589
590
591
592
593
594
595 private static void printGraphicsCards(List<GraphicsCard> list) {
596 oshi.add("Graphics Cards:");
597 if (list.isEmpty()) {
598 oshi.add(" None detected.");
599 } else {
600 for (GraphicsCard card : list) {
601 oshi.add(" " + String.valueOf(card));
602 }
603 }
604 }
605
606 }