001/* 002 * Copyright 2015 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.runtime.plugins.admin.jvmstatus; 017 018import java.io.File; 019import java.io.IOException; 020import java.lang.management.ManagementFactory; 021import java.lang.management.MemoryMXBean; 022import java.lang.management.RuntimeMXBean; 023import java.lang.management.ThreadMXBean; 024import java.util.ArrayList; 025import java.util.Collections; 026import java.util.Date; 027import java.util.HashMap; 028import java.util.HashSet; 029import java.util.List; 030import java.util.Map; 031import java.util.Set; 032 033import org.apache.avalon.framework.activity.Initializable; 034import org.apache.avalon.framework.component.Component; 035import org.apache.avalon.framework.logger.AbstractLogEnabled; 036import org.apache.avalon.framework.service.ServiceException; 037import org.apache.avalon.framework.service.ServiceManager; 038import org.apache.avalon.framework.service.Serviceable; 039import org.apache.commons.io.FileUtils; 040import org.rrd4j.core.Archive; 041import org.rrd4j.core.RrdDb; 042 043import org.ametys.core.ui.Callable; 044import org.ametys.core.util.DateUtils; 045import org.ametys.core.util.I18nUtils; 046import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.MonitoringConstants; 047import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.MonitoringExtensionPoint; 048import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.SampleManager; 049import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.alerts.AlertSampleManager; 050import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.alerts.AlertSampleManager.Threshold; 051import org.ametys.runtime.servlet.RuntimeConfig; 052 053/** 054 * This helper allow to get information or runs some operations on JVM system 055 */ 056public class JVMStatusHelper extends AbstractLogEnabled implements Component, Serviceable, Initializable, MonitoringConstants 057{ 058 /** The monitoring extension point */ 059 private MonitoringExtensionPoint _monitoringExtensionPoint; 060 061 /** Component containing i18n utilitary methods */ 062 private I18nUtils _i18nUtils; 063 064 private String _rrdStoragePath; 065 066 @Override 067 public void service(ServiceManager manager) throws ServiceException 068 { 069 _monitoringExtensionPoint = (MonitoringExtensionPoint) manager.lookup(MonitoringExtensionPoint.ROLE); 070 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 071 } 072 073 public void initialize() throws Exception 074 { 075 _rrdStoragePath = FileUtils.getFile(RuntimeConfig.getInstance().getAmetysHome(), RRD_STORAGE_DIRECTORY).getPath(); 076 } 077 078 /** 079 * Runs a garbage collector. 080 * @return an empty map 081 */ 082 @Callable 083 public Map<String, Object> garbageCollect () 084 { 085 if (getLogger().isInfoEnabled()) 086 { 087 getLogger().info("Administrator is garbage collecting"); 088 } 089 090 System.gc(); 091 092 return Collections.EMPTY_MAP; 093 } 094 095 /** 096 * Retrieves information about the general status of the system 097 * @return a map containing the general status information 098 */ 099 @Callable 100 public Map<String, Object> getGeneralStatus() 101 { 102 Map<String, Object> result = new HashMap<>(); 103 104 result.put("osTime", DateUtils.dateToString(new Date())); 105 try 106 { 107 result.put("activeSessions", SessionCountListener.getSessionCount()); 108 } 109 catch (IllegalStateException e) 110 { 111 // empty : no value in activeSession means an error 112 } 113 114 try 115 { 116 result.put("activeRequests", RequestCountListener.getCurrentRequestCount()); 117 } 118 catch (IllegalStateException e) 119 { 120 // empty : no value in activeSession means an error 121 } 122 123 124 ThreadMXBean tBean = ManagementFactory.getThreadMXBean(); 125 MemoryMXBean mBean = ManagementFactory.getMemoryMXBean(); 126 RuntimeMXBean rBean = ManagementFactory.getRuntimeMXBean(); 127 128 result.put("activeThreads", tBean.getThreadCount()); 129 long[] lockedThreads = ManagementFactory.getThreadMXBean().findMonitorDeadlockedThreads(); 130 131 result.put("deadlockThreads", lockedThreads != null ? String.valueOf(lockedThreads.length) : "0"); 132 133 result.put("heap-memory-max", mBean.getHeapMemoryUsage().getMax()); 134 result.put("heap-memory-used", mBean.getHeapMemoryUsage().getUsed()); 135 result.put("heap-memory-commited", mBean.getHeapMemoryUsage().getCommitted()); 136 137 138 result.put("startTime", DateUtils.dateToString(new Date(rBean.getStartTime()))); 139 140 return result; 141 } 142 143 /** 144 * Retrieves the monitoring data 145 * @return a map containing the monitoring data 146 */ 147 @Callable 148 public Map<String, Object> getMonitoringData() 149 { 150 Map<String, Object> result = new HashMap<> (); 151 152 Map<String, Object> samples = new HashMap<> (); 153 List<String> periods = new ArrayList<> (); 154 155 for (Period period : Period.values()) 156 { 157 periods.add(period.toString()); 158 } 159 160 samples.put("periods", periods); 161 162 List<Map<String, Object>> sampleList = new ArrayList<> (); 163 for (String extensionId : _monitoringExtensionPoint.getExtensionsIds()) 164 { 165 Map<String, Object> sample = new HashMap<> (); 166 SampleManager sampleManager = _monitoringExtensionPoint.getExtension(extensionId); 167 168 sample.put("id", sampleManager.getId()); 169 sample.put("label", _i18nUtils.translate(sampleManager.getLabel())); 170 sample.put("description", _i18nUtils.translate(sampleManager.getDescription())); 171 if (sampleManager instanceof AlertSampleManager) 172 { 173 Map<String, Object> thresholdValues = new HashMap<>(); 174 175 Map<String, Threshold> thresholds = ((AlertSampleManager) sampleManager).getThresholdValues(); 176 for (String datasourceName : thresholds.keySet()) 177 { 178 thresholdValues.put(datasourceName, thresholds.get(datasourceName).getValue()); 179 } 180 181 sample.put("thresholds", thresholdValues); 182 } 183 184 File rrdFile = new File(_rrdStoragePath, sampleManager.getId() + RRD_EXT); 185 if (getLogger().isDebugEnabled()) 186 { 187 getLogger().debug("Using RRD file: " + rrdFile); 188 } 189 190 RrdDb rrdDb = null; 191 try 192 { 193 rrdDb = new RrdDb(rrdFile.getPath()); 194 195 sample.put("ds", rrdDb.getDsNames()); 196 197 Set<String> consolidationFunction = new HashSet<>(); 198 for (int i = 0; i < rrdDb.getArcCount(); i++) 199 { 200 Archive archive = rrdDb.getArchive(i); 201 consolidationFunction.add(archive.getConsolFun().toString()); 202 } 203 sample.put("consolFun", consolidationFunction); 204 } 205 catch (Exception e) 206 { 207 getLogger().error("Unable to collect sample for: " + sampleManager.getId(), e); 208 } 209 finally 210 { 211 if (rrdDb != null) 212 { 213 try 214 { 215 rrdDb.close(); 216 } 217 catch (IOException e) 218 { 219 getLogger().warn("Unable to close RRD file: " + rrdFile, e); 220 } 221 } 222 } 223 224 sampleList.add(sample); 225 } 226 227 samples.put("sampleList", sampleList); 228 result.put("samples", samples); 229 return result; 230 } 231}