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.I18nUtils; 045import org.ametys.runtime.parameter.ParameterHelper; 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", ParameterHelper.valueToString(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 result.put("startTime", ParameterHelper.valueToString(new Date(rBean.getStartTime()))); 138 139 return result; 140 } 141 142 /** 143 * Retrieves the monitoring data 144 * @return a map containing the monitoring data 145 */ 146 @Callable 147 public Map<String, Object> getMonitoringData() 148 { 149 Map<String, Object> result = new HashMap<> (); 150 151 Map<String, Object> samples = new HashMap<> (); 152 List<String> periods = new ArrayList<> (); 153 154 for (Period period : Period.values()) 155 { 156 periods.add(period.toString()); 157 } 158 159 samples.put("periods", periods); 160 161 List<Map<String, Object>> sampleList = new ArrayList<> (); 162 for (String extensionId : _monitoringExtensionPoint.getExtensionsIds()) 163 { 164 Map<String, Object> sample = new HashMap<> (); 165 SampleManager sampleManager = _monitoringExtensionPoint.getExtension(extensionId); 166 167 sample.put("id", sampleManager.getId()); 168 sample.put("label", _i18nUtils.translate(sampleManager.getLabel())); 169 sample.put("description", _i18nUtils.translate(sampleManager.getDescription())); 170 if (sampleManager instanceof AlertSampleManager) 171 { 172 Map<String, Object> thresholdValues = new HashMap<>(); 173 174 Map<String, Threshold> thresholds = ((AlertSampleManager) sampleManager).getThresholdValues(); 175 for (String datasourceName : thresholds.keySet()) 176 { 177 thresholdValues.put(datasourceName, thresholds.get(datasourceName).getValue()); 178 } 179 180 sample.put("thresholds", thresholdValues); 181 } 182 183 File rrdFile = new File(_rrdStoragePath, sampleManager.getId() + RRD_EXT); 184 if (getLogger().isDebugEnabled()) 185 { 186 getLogger().debug("Using RRD file: " + rrdFile); 187 } 188 189 RrdDb rrdDb = null; 190 try 191 { 192 rrdDb = new RrdDb(rrdFile.getPath()); 193 194 sample.put("ds", rrdDb.getDsNames()); 195 196 Set<String> consolidationFunction = new HashSet<>(); 197 for (int i = 0; i < rrdDb.getArcCount(); i++) 198 { 199 Archive archive = rrdDb.getArchive(i); 200 consolidationFunction.add(archive.getConsolFun().toString()); 201 } 202 sample.put("consolFun", consolidationFunction); 203 } 204 catch (Exception e) 205 { 206 getLogger().error("Unable to collect sample for: " + sampleManager.getId(), e); 207 } 208 finally 209 { 210 if (rrdDb != null) 211 { 212 try 213 { 214 rrdDb.close(); 215 } 216 catch (IOException e) 217 { 218 getLogger().warn("Unable to close RRD file: " + rrdFile, e); 219 } 220 } 221 } 222 223 sampleList.add(sample); 224 } 225 226 samples.put("sampleList", sampleList); 227 result.put("samples", samples); 228 return result; 229 } 230}