View Javadoc
1   /*
2    * Copyright 2012-2025 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.app.web.api.admin.stats;
17  
18  import java.io.File;
19  import java.util.Arrays;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Locale;
23  
24  import org.codelibs.fess.app.web.api.ApiResult;
25  import org.codelibs.fess.app.web.api.ApiResult.ApiStatsResponse;
26  import org.codelibs.fess.app.web.api.admin.FessApiAdminAction;
27  import org.codelibs.fess.opensearch.client.SearchEngineClient;
28  import org.codelibs.fess.util.ComponentUtil;
29  import org.lastaflute.web.Execute;
30  import org.lastaflute.web.response.JsonResponse;
31  import org.opensearch.action.admin.cluster.health.ClusterHealthResponse;
32  import org.opensearch.monitor.jvm.JvmStats;
33  import org.opensearch.monitor.jvm.JvmStats.BufferPool;
34  import org.opensearch.monitor.jvm.JvmStats.Classes;
35  import org.opensearch.monitor.jvm.JvmStats.GarbageCollectors;
36  import org.opensearch.monitor.jvm.JvmStats.Mem;
37  import org.opensearch.monitor.jvm.JvmStats.Threads;
38  import org.opensearch.monitor.os.OsProbe;
39  import org.opensearch.monitor.os.OsStats;
40  import org.opensearch.monitor.process.ProcessProbe;
41  
42  /**
43   * API action for admin statistics management.
44   *
45   */
46  public class ApiAdminStatsAction extends FessApiAdminAction {
47  
48      // ===================================================================================
49      //                                                                           Constructor
50      //                                                                           ===========
51  
52      /**
53       * Default constructor.
54       */
55      public ApiAdminStatsAction() {
56          super();
57      }
58  
59      // ===================================================================================
60      //                                                                           Attribute
61      //                                                                           =========
62  
63      // ===================================================================================
64      //                                                                      Search Execute
65      //                                                                      ==============
66  
67      /**
68       * Retrieves system statistics including JVM, OS, process, engine, and filesystem information.
69       *
70       * @return JSON response containing system statistics
71       */
72      // GET /api/admin/stats
73      @Execute
74      public JsonResponse<ApiResult> index() {
75          final HashMap<String, Object> stats = new HashMap<>();
76          stats.put("jvm", getJvmObj());
77          stats.put("os", getOsObj());
78          stats.put("process", getProcessObj());
79          stats.put("engine", getEngineObj());
80          stats.put("fs", getFsObj());
81          return asJson(new ApiStatsResponse().stats(stats).status(ApiResult.Status.OK).result());
82      }
83  
84      private FsObj[] getFsObj() {
85          return Arrays.stream(File.listRoots()).map(f -> {
86              final FsObj fsObj = new FsObj();
87              fsObj.path = f.getAbsolutePath();
88              fsObj.free = f.getFreeSpace();
89              fsObj.total = f.getTotalSpace();
90              fsObj.usable = f.getUsableSpace();
91              fsObj.used = fsObj.total - fsObj.usable;
92              fsObj.percent = (short) (100 * fsObj.used / fsObj.total);
93              return fsObj;
94          }).toArray(n -> new FsObj[n]);
95      }
96  
97      private JvmObj getJvmObj() {
98          final JvmObj jvmObj = new JvmObj();
99          final JvmStats jvmStats = JvmStats.jvmStats();
100         final Mem mem = jvmStats.getMem();
101         final JvmMemoryObj jvmMemoryObj = new JvmMemoryObj();
102         jvmObj.memory = jvmMemoryObj;
103         final JvmMemoryHeapObj jvmMemoryHeapObj = new JvmMemoryHeapObj();
104         jvmMemoryObj.heap = jvmMemoryHeapObj;
105         jvmMemoryHeapObj.used = mem.getHeapUsed().getBytes();
106         jvmMemoryHeapObj.committed = mem.getHeapCommitted().getBytes();
107         jvmMemoryHeapObj.max = mem.getHeapMax().getBytes();
108         jvmMemoryHeapObj.percent = mem.getHeapUsedPercent();
109         final JvmMemoryNonHeapObj jvmMemoryNonHeapObj = new JvmMemoryNonHeapObj();
110         jvmMemoryObj.nonHeap = jvmMemoryNonHeapObj;
111         jvmMemoryNonHeapObj.used = mem.getNonHeapUsed().getBytes();
112         jvmMemoryNonHeapObj.committed = mem.getNonHeapCommitted().getBytes();
113         final List<BufferPool> bufferPools = jvmStats.getBufferPools();
114         jvmObj.pools = bufferPools.stream().map(p -> {
115             final JvmPoolObj jvmPoolObj = new JvmPoolObj();
116             jvmPoolObj.key = p.getName();
117             jvmPoolObj.count = p.getCount();
118             jvmPoolObj.used = p.getUsed().getBytes();
119             jvmPoolObj.capacity = p.getTotalCapacity().getBytes();
120             return jvmPoolObj;
121         }).toArray(n -> new JvmPoolObj[n]);
122         final GarbageCollectors gc = jvmStats.getGc();
123         jvmObj.gc = Arrays.stream(gc.getCollectors()).map(c -> {
124             final JvmGcObj jvmGcObj = new JvmGcObj();
125             jvmGcObj.key = c.getName();
126             jvmGcObj.count = c.getCollectionCount();
127             jvmGcObj.time = c.getCollectionTime().getMillis();
128             return jvmGcObj;
129         }).toArray(n -> new JvmGcObj[n]);
130         final Threads threads = jvmStats.getThreads();
131         final JvmThreadsObj jvmThreadsObj = new JvmThreadsObj();
132         jvmObj.threads = jvmThreadsObj;
133         jvmThreadsObj.count = threads.getCount();
134         jvmThreadsObj.peak = threads.getPeakCount();
135         final Classes classes = jvmStats.getClasses();
136         final JvmClassesObj jvmClassesObj = new JvmClassesObj();
137         jvmObj.classes = jvmClassesObj;
138         jvmClassesObj.loaded = classes.getLoadedClassCount();
139         jvmClassesObj.total_loaded = classes.getTotalLoadedClassCount();
140         jvmClassesObj.unloaded = classes.getUnloadedClassCount();
141         jvmObj.uptime = jvmStats.getUptime().getMillis();
142         return jvmObj;
143     }
144 
145     private ProcessObj getProcessObj() {
146         final ProcessObj processObj = new ProcessObj();
147         final ProcessProbe processProbe = ProcessProbe.getInstance();
148         final ProcessFileDescriptorObj processFileDescriptorObj = new ProcessFileDescriptorObj();
149         processObj.fileFescriptor = processFileDescriptorObj;
150         processFileDescriptorObj.open = processProbe.getOpenFileDescriptorCount();
151         processFileDescriptorObj.max = processProbe.getMaxFileDescriptorCount();
152         final ProcessCpuObj processCpuObj = new ProcessCpuObj();
153         processObj.cpu = processCpuObj;
154         processCpuObj.percent = processProbe.getProcessCpuPercent();
155         processCpuObj.total = processProbe.getProcessCpuTotalTime();
156         final ProcessVirtualMemoryObj processVirtualMemoryObj = new ProcessVirtualMemoryObj();
157         processObj.virtualMemory = processVirtualMemoryObj;
158         processVirtualMemoryObj.total = processProbe.getTotalVirtualMemorySize();
159         return processObj;
160     }
161 
162     private OsObj getOsObj() {
163         final OsObj osObj = new OsObj();
164         final OsProbe osProbe = OsProbe.getInstance();
165         final OsMemoryObj osMemoryObj = new OsMemoryObj();
166         osObj.memory = osMemoryObj;
167         final OsMemoryPhysicalObj osMemoryPhysicalObj = new OsMemoryPhysicalObj();
168         osMemoryObj.physical = osMemoryPhysicalObj;
169         osMemoryPhysicalObj.free = osProbe.getFreePhysicalMemorySize();
170         osMemoryPhysicalObj.total = osProbe.getTotalPhysicalMemorySize();
171         final OsMemorySwapSpaceObj osMemorySwapSpaceObj = new OsMemorySwapSpaceObj();
172         osMemoryObj.swapSpace = osMemorySwapSpaceObj;
173         osMemorySwapSpaceObj.free = osProbe.getFreeSwapSpaceSize();
174         osMemorySwapSpaceObj.total = osProbe.getTotalSwapSpaceSize();
175         final OsCpuObj osCpuObj = new OsCpuObj();
176         osObj.cpu = osCpuObj;
177         osCpuObj.percent = osProbe.getSystemCpuPercent();
178         final OsStats osStats = osProbe.osStats();
179         osObj.loadAverages = osStats.getCpu().getLoadAverage();
180         return osObj;
181     }
182 
183     private EngineObj getEngineObj() {
184         final EngineObj engineObj = new EngineObj();
185         try {
186             final SearchEngineClient esClient = ComponentUtil.getSearchEngineClient();
187             final ClusterHealthResponse response =
188                     esClient.admin().cluster().prepareHealth().execute().actionGet(fessConfig.getIndexHealthTimeout());
189             engineObj.clusterName = response.getClusterName();
190             engineObj.numberOfNodes = response.getNumberOfNodes();
191             engineObj.numberOfDataNodes = response.getNumberOfDataNodes();
192             engineObj.activePrimaryShards = response.getActivePrimaryShards();
193             engineObj.activeShards = response.getActiveShards();
194             engineObj.activeShardsPercent = response.getActiveShardsPercent();
195             engineObj.relocatingShards = response.getRelocatingShards();
196             engineObj.initializingShards = response.getInitializingShards();
197             engineObj.unassignedShards = response.getUnassignedShards();
198             engineObj.delayedUnassignedShards = response.getDelayedUnassignedShards();
199             engineObj.numberOfPendingTasks = response.getNumberOfPendingTasks();
200             engineObj.numberOfInFlightFetch = response.getNumberOfInFlightFetch();
201             engineObj.status = response.getStatus().name().toLowerCase(Locale.ROOT);
202         } catch (final Exception e) {
203             engineObj.status = "red";
204             engineObj.exception = e.getMessage();
205         }
206         return engineObj;
207     }
208 
209     /**
210      * Data transfer object representing filesystem statistics.
211      */
212     public static class FsObj {
213         /**
214          * Default constructor.
215          */
216         public FsObj() {
217             // Default constructor
218         }
219 
220         /** The percentage of used space on the filesystem. */
221         public short percent;
222         /** Used space in bytes */
223         public long used;
224         /** Filesystem path */
225         public String path;
226         /** Free space in bytes */
227         public long free;
228         /** Total space in bytes */
229         public long total;
230         /** Usable space in bytes */
231         public long usable;
232     }
233 
234     /**
235      * Data transfer object representing search engine cluster statistics.
236      */
237     public static class EngineObj {
238         /**
239          * Default constructor.
240          */
241         public EngineObj() {
242             // Default constructor
243         }
244 
245         /** Exception message if any error occurred */
246         public String exception;
247         /** Cluster health status */
248         public String status;
249         /** Number of in-flight fetch operations */
250         public int numberOfInFlightFetch;
251         /** Number of pending tasks */
252         public int numberOfPendingTasks;
253         /** Number of delayed unassigned shards */
254         public int delayedUnassignedShards;
255         /** Number of unassigned shards */
256         public int unassignedShards;
257         /** Number of initializing shards */
258         public int initializingShards;
259         /** Number of relocating shards */
260         public int relocatingShards;
261         /** Percentage of active shards */
262         public double activeShardsPercent;
263         /** Number of active shards */
264         public int activeShards;
265         /** Number of active primary shards */
266         public int activePrimaryShards;
267         /** Number of data nodes */
268         public int numberOfDataNodes;
269         /** Total number of nodes */
270         public int numberOfNodes;
271         /** Cluster name */
272         public String clusterName;
273     }
274 
275     /**
276      * Data transfer object representing JVM statistics.
277      */
278     public static class JvmObj {
279         /**
280          * Default constructor.
281          */
282         public JvmObj() {
283             // Default constructor
284         }
285 
286         /** JVM memory statistics */
287         public JvmMemoryObj memory;
288         /** JVM buffer pool statistics */
289         public JvmPoolObj[] pools;
290         /** JVM garbage collection statistics */
291         public JvmGcObj[] gc;
292         /** JVM thread statistics */
293         public JvmThreadsObj threads;
294         /** JVM class loading statistics */
295         public JvmClassesObj classes;
296         /** JVM uptime in milliseconds */
297         public long uptime;
298     }
299 
300     /**
301      * Data transfer object representing JVM memory statistics.
302      */
303     public static class JvmMemoryObj {
304         /**
305          * Default constructor.
306          */
307         public JvmMemoryObj() {
308             // Default constructor
309         }
310 
311         /** Heap memory statistics */
312         public JvmMemoryHeapObj heap;
313         /** Non-heap memory statistics */
314         public JvmMemoryNonHeapObj nonHeap;
315     }
316 
317     /**
318      * Data transfer object representing JVM heap memory statistics.
319      */
320     public static class JvmMemoryHeapObj {
321         /**
322          * Default constructor.
323          */
324         public JvmMemoryHeapObj() {
325             // Default constructor
326         }
327 
328         /** Used heap memory in bytes */
329         public long used;
330         /** Committed heap memory in bytes */
331         public long committed;
332         /** Maximum heap memory in bytes */
333         public long max;
334         /** Heap memory usage percentage */
335         public short percent;
336     }
337 
338     /**
339      * Data transfer object representing JVM non-heap memory statistics.
340      */
341     public static class JvmMemoryNonHeapObj {
342         /**
343          * Default constructor.
344          */
345         public JvmMemoryNonHeapObj() {
346             // Default constructor
347         }
348 
349         /** Used non-heap memory in bytes */
350         public long used;
351         /** Committed non-heap memory in bytes */
352         public long committed;
353         /** Maximum non-heap memory in bytes */
354         public long max;
355         /** The percentage of non-heap memory usage. */
356         public short percent;
357     }
358 
359     /**
360      * Data transfer object representing JVM buffer pool statistics.
361      */
362     public static class JvmPoolObj {
363         /**
364          * Default constructor.
365          */
366         public JvmPoolObj() {
367             // Default constructor
368         }
369 
370         /** Buffer pool name */
371         public String key;
372         /** Number of buffers */
373         public long count;
374         /** Used memory in bytes */
375         public long used;
376         /** Total capacity in bytes */
377         public long capacity;
378     }
379 
380     /**
381      * Data transfer object representing JVM garbage collection statistics.
382      */
383     public static class JvmGcObj {
384         /**
385          * Default constructor.
386          */
387         public JvmGcObj() {
388             // Default constructor
389         }
390 
391         /** Garbage collector name */
392         public String key;
393         /** Number of collections */
394         public long count;
395         /** Total collection time in milliseconds */
396         public long time;
397     }
398 
399     /**
400      * Data transfer object representing JVM thread statistics.
401      */
402     public static class JvmThreadsObj {
403         /**
404          * Default constructor.
405          */
406         public JvmThreadsObj() {
407             // Default constructor
408         }
409 
410         /** Current number of threads */
411         public int count;
412         /** Peak number of threads */
413         public int peak;
414     }
415 
416     /**
417      * Data transfer object representing JVM class loading statistics.
418      */
419     public static class JvmClassesObj {
420         /**
421          * Default constructor.
422          */
423         public JvmClassesObj() {
424             // Default constructor
425         }
426 
427         /** Currently loaded classes */
428         public long loaded;
429         /** Total classes loaded since JVM start */
430         public long total_loaded;
431         /** Total classes unloaded */
432         public long unloaded;
433     }
434 
435     /**
436      * Data transfer object representing process statistics.
437      */
438     public static class ProcessObj {
439         /**
440          * Default constructor.
441          */
442         public ProcessObj() {
443             // Default constructor
444         }
445 
446         /** File descriptor statistics for the process. */
447         public ProcessFileDescriptorObj fileFescriptor;
448         /** CPU statistics for the process. */
449         public ProcessCpuObj cpu;
450         /** Virtual memory statistics for the process. */
451         public ProcessVirtualMemoryObj virtualMemory;
452     }
453 
454     /**
455      * Data transfer object representing process file descriptor statistics.
456      */
457     public static class ProcessFileDescriptorObj {
458         /**
459          * Default constructor.
460          */
461         public ProcessFileDescriptorObj() {
462             // Default constructor
463         }
464 
465         /** Number of currently open file descriptors. */
466         public long open;
467         /** Maximum number of file descriptors that can be opened. */
468         public long max;
469     }
470 
471     /**
472      * Data transfer object representing process CPU statistics.
473      */
474     public static class ProcessCpuObj {
475         /**
476          * Default constructor.
477          */
478         public ProcessCpuObj() {
479             // Default constructor
480         }
481 
482         /** CPU usage percentage for the process. */
483         public short percent;
484         /** Total CPU time used by the process in milliseconds. */
485         public long total;
486     }
487 
488     /**
489      * Data transfer object representing process virtual memory statistics.
490      */
491     public static class ProcessVirtualMemoryObj {
492         /**
493          * Default constructor.
494          */
495         public ProcessVirtualMemoryObj() {
496             // Default constructor
497         }
498 
499         /** Total virtual memory size in bytes. */
500         public long total;
501     }
502 
503     /**
504      * Data transfer object representing operating system statistics.
505      */
506     public static class OsObj {
507         /**
508          * Default constructor.
509          */
510         public OsObj() {
511             // Default constructor
512         }
513 
514         /** Memory statistics for the operating system. */
515         public OsMemoryObj memory;
516         /** CPU statistics for the operating system. */
517         public OsCpuObj cpu;
518         /** System load averages. */
519         public double[] loadAverages;
520     }
521 
522     /**
523      * Data transfer object representing OS memory statistics.
524      */
525     public static class OsMemoryObj {
526         /**
527          * Default constructor.
528          */
529         public OsMemoryObj() {
530             // Default constructor
531         }
532 
533         /** Physical memory statistics. */
534         public OsMemoryPhysicalObj physical;
535         /** Swap space statistics. */
536         public OsMemorySwapSpaceObj swapSpace;
537     }
538 
539     /**
540      * Data transfer object representing OS physical memory statistics.
541      */
542     public static class OsMemoryPhysicalObj {
543         /**
544          * Default constructor.
545          */
546         public OsMemoryPhysicalObj() {
547             // Default constructor
548         }
549 
550         /** Free physical memory in bytes. */
551         public long free;
552         /** Total physical memory in bytes. */
553         public long total;
554     }
555 
556     /**
557      * Data transfer object representing OS swap space statistics.
558      */
559     public static class OsMemorySwapSpaceObj {
560         /**
561          * Default constructor.
562          */
563         public OsMemorySwapSpaceObj() {
564             // Default constructor
565         }
566 
567         /** Free swap space in bytes. */
568         public long free;
569         /** Total swap space in bytes. */
570         public long total;
571     }
572 
573     /**
574      * Data transfer object representing OS CPU statistics.
575      */
576     public static class OsCpuObj {
577         /**
578          * Default constructor.
579          */
580         public OsCpuObj() {
581             // Default constructor
582         }
583 
584         /** CPU usage percentage for the operating system. */
585         public short percent;
586     }
587 }