Skip to content
Snippets Groups Projects
Commit 25cc8e37 authored by srosse's avatar srosse
Browse files

OO-340: backport and enhance the rest api to monitor OpenOLAT

parent aff58bb7
No related branches found
No related tags found
No related merge requests found
Showing
with 13128 additions and 11308 deletions
...@@ -853,7 +853,8 @@ ...@@ -853,7 +853,8 @@
<show>public</show> <show>public</show>
<subpackages> <subpackages>
org.olat.restapi,org.olat.catalog.restapi,org.olat.modules.fo.restapi, org.olat.restapi,org.olat.catalog.restapi,org.olat.modules.fo.restapi,
org.olat.notifications.restapi,org.olat.user.restapi,org.olat.course.nodes org.olat.notifications.restapi,org.olat.user.restapi,org.olat.course.nodes,
org.olat.restapi.system
</subpackages> </subpackages>
<doclet>com.sun.jersey.wadl.resourcedoc.ResourceDoclet</doclet> <doclet>com.sun.jersey.wadl.resourcedoc.ResourceDoclet</doclet>
......
...@@ -24,9 +24,9 @@ ...@@ -24,9 +24,9 @@
*/ */
package org.olat.admin.jmx; package org.olat.admin.jmx;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.scheduler.JobWithDB; import org.olat.core.commons.scheduler.JobWithDB;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; import org.quartz.JobExecutionException;
...@@ -43,27 +43,25 @@ public class DumpJMXJob extends JobWithDB { ...@@ -43,27 +43,25 @@ public class DumpJMXJob extends JobWithDB {
@Override @Override
public void executeWithDB(JobExecutionContext context) public void executeWithDB(JobExecutionContext context)
throws JobExecutionException { throws JobExecutionException {
boolean enabled = context.getMergedJobDataMap().getBooleanFromString("enabled"); boolean enabled = context.getMergedJobDataMap().getBooleanFromString("enabled");
String[] keys = context.getMergedJobDataMap().getKeys(); if (enabled) {
// loop over all JMXManager jmxManager = CoreSpringFactory.getImpl(JMXManager.class);
for (int i = 0; i < keys.length; i++) { String[] keys = context.getMergedJobDataMap().getKeys();
String key = keys[i]; // loop over all
if (key.endsWith("Bean")) { for (int i = 0; i < keys.length; i++) {
// ok, key is a bean name => dump this bean String key = keys[i];
String beanName = context.getMergedJobDataMap().getString(key); if (key.endsWith("Bean")) {
if (enabled) { // ok, key is a bean name => dump this bean
List<String> jmxDumpList = JMXManager.getInstance().dumpJmx(beanName); String beanName = context.getMergedJobDataMap().getString(key);
List<String> jmxDumpList = jmxManager.dumpJmx(beanName);
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
for (Iterator iterator = jmxDumpList.iterator(); iterator.hasNext();) { for (String jmxDump : jmxDumpList) {
String jmxDump = (String) iterator.next(); buf.append(jmxDump).append(";");
buf.append(jmxDump);
buf.append(";");
} }
log.info(key + ":" + buf.toString()); log.info(key + ":" + buf.toString());
} }
} }
} }
} }
} }
...@@ -26,6 +26,7 @@ package org.olat.admin.jmx; ...@@ -26,6 +26,7 @@ package org.olat.admin.jmx;
import java.util.List; import java.util.List;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.UserRequest; import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component; import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.components.panel.Panel;
...@@ -36,7 +37,7 @@ import org.olat.core.gui.control.controller.BasicController; ...@@ -36,7 +37,7 @@ import org.olat.core.gui.control.controller.BasicController;
/** /**
* Description:<br> * Description:<br>
* TODO: * Dump the JMX context and show the output
* *
* <P> * <P>
* Initial Date: 01.10.2007 <br> * Initial Date: 01.10.2007 <br>
...@@ -44,8 +45,7 @@ import org.olat.core.gui.control.controller.BasicController; ...@@ -44,8 +45,7 @@ import org.olat.core.gui.control.controller.BasicController;
*/ */
public class JMXInfoController extends BasicController { public class JMXInfoController extends BasicController {
private VelocityContainer mainVc; private final JMXManager jmxManager;
//private Link dumpAllLink;
/** /**
* @param ureq * @param ureq
...@@ -54,38 +54,29 @@ public class JMXInfoController extends BasicController { ...@@ -54,38 +54,29 @@ public class JMXInfoController extends BasicController {
public JMXInfoController(UserRequest ureq, WindowControl wControl) { public JMXInfoController(UserRequest ureq, WindowControl wControl) {
super(ureq, wControl); super(ureq, wControl);
if (!JMXManager.getInstance().isActive()) { jmxManager = CoreSpringFactory.getImpl(JMXManager.class);
if (!jmxManager.isActive()) {
showError("nojmx"); showError("nojmx");
putInitialPanel(new Panel("empty")); putInitialPanel(new Panel("empty"));
return; return;
} }
mainVc = createVelocityContainer("jmxmain"); VelocityContainer mainVc = createVelocityContainer("jmxmain");
//dumpAllLink = LinkFactory.createButton("dumpall", mainVc, this); List<String> jmxres = jmxManager.dumpJmx("org.olat.core.commons.modules.bc:name=FilesInfoMBean");
List<String> jmxres = JMXManager.getInstance().dumpJmx("org.olat.core.commons.modules.bc:name=FilesInfoMBean");
mainVc.contextPut("jmxlist", jmxres); mainVc.contextPut("jmxlist", jmxres);
String htmlRes = JMXManager.getInstance().dumpAll(); String htmlRes = jmxManager.dumpAll();
mainVc.contextPut("jmxdump", htmlRes); mainVc.contextPut("jmxdump", htmlRes);
putInitialPanel(mainVc); putInitialPanel(mainVc);
} }
/* (non-Javadoc)
* @see org.olat.core.gui.control.DefaultController#doDispose()
*/
@Override @Override
protected void doDispose() { protected void doDispose() {
// TODO Auto-generated method stub //
} }
/* (non-Javadoc)
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
*/
@Override @Override
@SuppressWarnings("unused")
protected void event(UserRequest ureq, Component source, Event event) { protected void event(UserRequest ureq, Component source, Event event) {
// //
} }
}
} \ No newline at end of file
...@@ -36,41 +36,33 @@ import javax.management.MBeanServer; ...@@ -36,41 +36,33 @@ import javax.management.MBeanServer;
import javax.management.ObjectInstance; import javax.management.ObjectInstance;
import javax.management.ObjectName; import javax.management.ObjectName;
import org.olat.core.CoreSpringFactory;
import org.olat.core.manager.BasicManager; import org.olat.core.manager.BasicManager;
import org.springframework.jmx.support.MBeanServerFactoryBean;
/** /**
* Description:<br> * Description:<br>
* TODO: * Manage the JMX beans
* *
* <P> * <P>
* Initial Date: 01.10.2007 <br> * Initial Date: 01.10.2007 <br>
* @author Felix Jost, http://www.goodsolutions.ch * @author Felix Jost, http://www.goodsolutions.ch
*/ */
public class JMXManager extends BasicManager { public class JMXManager extends BasicManager {
private static JMXManager INSTANCE;
private boolean initDone = true;
private MBeanServer mBeanServer; private MBeanServer mBeanServer;
public static JMXManager getInstance() {
return INSTANCE;
}
/** /**
* [spring] * [spring]
*/ */
private JMXManager(MBeanServer mBeanServer) { private JMXManager(MBeanServer mBeanServer) {
this.mBeanServer = mBeanServer; this.mBeanServer = mBeanServer;
INSTANCE = this;
} }
boolean isActive() { public boolean isActive() {
return initDone; return mBeanServer != null;
} }
void init() { public MBeanServer getMBeanServer() {
initDone = true; return mBeanServer;
} }
public List<String> dumpJmx(String objectName) { public List<String> dumpJmx(String objectName) {
...@@ -92,9 +84,8 @@ public class JMXManager extends BasicManager { ...@@ -92,9 +84,8 @@ public class JMXManager extends BasicManager {
} }
return l; return l;
} catch (Exception e) { } catch (Exception e) {
List l = new ArrayList(); List<String> l = new ArrayList<String>();
l.add("error while retrieving jmx values: "+e.getClass().getName()+":"+e.getMessage()); l.add("error while retrieving jmx values: "+e.getClass().getName()+":"+e.getMessage());
//TODO: this is just version 0.1 of dumping jmx values... need a better interface
return l; return l;
} }
} }
...@@ -102,8 +93,7 @@ public class JMXManager extends BasicManager { ...@@ -102,8 +93,7 @@ public class JMXManager extends BasicManager {
public String dumpAll() { public String dumpAll() {
try { try {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
MBeanServer server = (MBeanServer) CoreSpringFactory.getBean(MBeanServerFactoryBean.class); Set<ObjectInstance> mbeansset = mBeanServer.queryMBeans(null, null);
Set<ObjectInstance> mbeansset = server.queryMBeans(null, null);
List<ObjectInstance> mbeans = new ArrayList<ObjectInstance>(mbeansset); List<ObjectInstance> mbeans = new ArrayList<ObjectInstance>(mbeansset);
Collections.sort(mbeans, new Comparator<ObjectInstance>(){ Collections.sort(mbeans, new Comparator<ObjectInstance>(){
public int compare(ObjectInstance o1, ObjectInstance o2) { public int compare(ObjectInstance o1, ObjectInstance o2) {
...@@ -113,7 +103,7 @@ public class JMXManager extends BasicManager { ...@@ -113,7 +103,7 @@ public class JMXManager extends BasicManager {
for (ObjectInstance instance : mbeans) { for (ObjectInstance instance : mbeans) {
ObjectName on = instance.getObjectName(); ObjectName on = instance.getObjectName();
MBeanAttributeInfo[] ainfo = server.getMBeanInfo(on).getAttributes(); MBeanAttributeInfo[] ainfo = mBeanServer.getMBeanInfo(on).getAttributes();
List<MBeanAttributeInfo> mbal = Arrays.asList(ainfo); List<MBeanAttributeInfo> mbal = Arrays.asList(ainfo);
Collections.sort(mbal, new Comparator<MBeanAttributeInfo>(){ Collections.sort(mbal, new Comparator<MBeanAttributeInfo>(){
public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) { public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) {
...@@ -125,7 +115,7 @@ public class JMXManager extends BasicManager { ...@@ -125,7 +115,7 @@ public class JMXManager extends BasicManager {
for (MBeanAttributeInfo info : mbal) { for (MBeanAttributeInfo info : mbal) {
String name = info.getName(); String name = info.getName();
try { try {
Object res = server.getAttribute(on, name); Object res = mBeanServer.getAttribute(on, name);
sb.append("<br />"+oname+"-> "+name+"="+res); sb.append("<br />"+oname+"-> "+name+"="+res);
} catch (Exception e) { } catch (Exception e) {
sb.append("<br />ERROR: for attribute '"+name+"', exception:"+e+", message:"+e.getMessage()); sb.append("<br />ERROR: for attribute '"+name+"', exception:"+e+", message:"+e.getMessage());
...@@ -134,9 +124,8 @@ public class JMXManager extends BasicManager { ...@@ -134,9 +124,8 @@ public class JMXManager extends BasicManager {
} }
return sb.toString(); return sb.toString();
} catch (Exception e) { } catch (Exception e) {
logError("", e);
return "error:"+e.getMessage(); return "error:"+e.getMessage();
} }
} }
}
} \ No newline at end of file
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
<mapping-file>org/olat/core/logging/activity/LoggingObject.hbm.xml</mapping-file> <mapping-file>org/olat/core/logging/activity/LoggingObject.hbm.xml</mapping-file>
<mapping-file>org/olat/course/db/impl/CourseDBEntryImpl.hbm.xml</mapping-file> <mapping-file>org/olat/course/db/impl/CourseDBEntryImpl.hbm.xml</mapping-file>
<properties> <properties>
<property name="hibernate.generate_statistics" value="true"/>
<property name="hibernate.archive.autodetection" value=""/> <property name="hibernate.archive.autodetection" value=""/>
<property name="hibernate.ejb.interceptor" value="org.olat.core.commons.persistence.AuditInterceptor"/> <property name="hibernate.ejb.interceptor" value="org.olat.core.commons.persistence.AuditInterceptor"/>
</properties> </properties>
......
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
<!-- "validate, update, create, create-drop" are valid entries for hibernate.hbm2ddl.auto--> <!-- "validate, update, create, create-drop" are valid entries for hibernate.hbm2ddl.auto-->
<prop key="hibernate.hbm2ddl.auto">${db.hibernate.ddl.auto}</prop> <prop key="hibernate.hbm2ddl.auto">${db.hibernate.ddl.auto}</prop>
<prop key="hibernate.show_sql">${db.show_sql}</prop> <prop key="hibernate.show_sql">${db.show_sql}</prop>
<prop key="hibernate.generate_statistics">true</prop>
<!-- <entry key="hibernate.query.substitutions">true 1, false 0, yes 'Y', no 'N'</value></entry> --> <!-- <entry key="hibernate.query.substitutions">true 1, false 0, yes 'Y', no 'N'</value></entry> -->
<prop key="hibernate.query.substitutions">true 1, false 0, yes 'Y', no 'N'</prop> <prop key="hibernate.query.substitutions">true 1, false 0, yes 'Y', no 'N'</prop>
<!-- for development phase only: --> <!-- for development phase only: -->
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
<value>org.olat.notifications.restapi.NotificationsWebService</value> <value>org.olat.notifications.restapi.NotificationsWebService</value>
<value>org.olat.commons.calendar.restapi.CalendarWebService</value> <value>org.olat.commons.calendar.restapi.CalendarWebService</value>
<value>org.olat.restapi.log.LogWebService</value> <value>org.olat.restapi.log.LogWebService</value>
<value>org.olat.restapi.system.SystemWebService</value>
</list> </list>
</property> </property>
<!-- property name="singletonBeans"> <!-- property name="singletonBeans">
...@@ -57,6 +58,32 @@ ...@@ -57,6 +58,32 @@
</property --> </property -->
</bean> </bean>
<bean id="systemSamplerTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="systemSamplerJob" />
<!-- adjust cron style syntax for your needs
A "Cron-Expression" is a string comprised of 6 or 7 fields separated by white space. The 6 mandatory and 1 optional fields are as follows:
Field Name Allowed Values Allowed Special Characters
Seconds 0-59 , - * /
Minutes 0-59 , - * /
Hours 0-23 , - * /
Day-of-month 1-31 , - * ? / L W C
Month 1-12 or JAN-DEC , - * /
Day-of-Week 1-7 or SUN-SAT , - * ? / L C #
Year (Optional) empty, 1970-2099 , - * /
As of OLAT 6.3 it's best to let the cronjob run every two hours since users can now choose how often
they will get notified. The shortest interval is set to two hours.
-->
<property name="cronExpression" value="*/15 * * * * ?" />
<!-- OLAT-5093 start delay ensures there's no conflict with server startup and db not being ready yet -->
<property name="startDelay" value="0" />
</bean>
<bean id="systemSamplerJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="org.olat.restapi.system.SamplerJob" />
</bean>
<!-- Using singletons would be good for the future and prevent using CoreSpringFactory --> <!-- Using singletons would be good for the future and prevent using CoreSpringFactory -->
<!-- bean id="userWebService" class="org.olat.user.restapi.UserWebService"/ --> <!-- bean id="userWebService" class="org.olat.user.restapi.UserWebService"/ -->
......
This diff is collapsed.
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import java.util.Collection;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.hibernate.stat.Statistics;
import org.olat.admin.jmx.JMXManager;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.restapi.system.vo.DatabaseConnectionVO;
import org.olat.restapi.system.vo.DatabaseVO;
import org.olat.restapi.system.vo.HibernateStatisticsVO;
import com.mchange.v2.c3p0.PooledDataSource;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public class DatabaseWebService {
private static final OLog log = Tracing.createLoggerFor(DatabaseWebService.class);
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getDatabaseStatistics() {
DatabaseConnectionVO connections = getConnectionInfos();
HibernateStatisticsVO hibernateStats = getHibernateStatistics();
DatabaseVO vo = new DatabaseVO();
vo.setConnectionInfos(connections);
vo.setHibernateStatistics(hibernateStats);
return Response.ok(vo).build();
}
private HibernateStatisticsVO getHibernateStatistics() {
Statistics statistics = DBFactory.getInstance().getStatistics();
if(!statistics.isStatisticsEnabled()) {
return null;
}
HibernateStatisticsVO stats = new HibernateStatisticsVO();
stats.setOpenSessionsCount(statistics.getSessionOpenCount());
stats.setTransactionsCount(statistics.getTransactionCount());
stats.setSuccessfulTransactionCount(statistics.getSuccessfulTransactionCount());
stats.setFailedTransactionsCount(statistics.getTransactionCount() - statistics.getSuccessfulTransactionCount());
stats.setOptimisticFailureCount(statistics.getOptimisticFailureCount());
stats.setQueryExecutionCount(statistics.getQueryExecutionCount());
stats.setQueryExecutionMaxTime(statistics.getQueryExecutionMaxTime());
stats.setQueryExecutionMaxTimeQueryString(statistics.getQueryExecutionMaxTimeQueryString());
return stats;
}
private DatabaseConnectionVO getConnectionInfos() {
DatabaseConnectionVO vo = new DatabaseConnectionVO();
try {
int activeConnectionCount = 0;
int currentConnectionCount = 0;
JMXManager jmxManager = CoreSpringFactory.getImpl(JMXManager.class);
MBeanServer mBeanServer = jmxManager.getMBeanServer();
ObjectName c3p0ObjectName = new ObjectName("com.mchange.v2.c3p0:type=C3P0Registry");
Object attributes = mBeanServer.getAttribute(c3p0ObjectName, "AllPooledDataSources");
if(attributes instanceof Collection) {
@SuppressWarnings("unchecked")
Collection<Object> attributeCollection = (Collection<Object>)attributes;
for(Object attribute : attributeCollection) {
if(attribute instanceof PooledDataSource) {
PooledDataSource dataSource = (PooledDataSource)attribute;
activeConnectionCount += dataSource.getNumBusyConnectionsAllUsers();
currentConnectionCount += dataSource.getNumConnectionsAllUsers();
}
}
}
vo.setActiveConnectionCount(activeConnectionCount);
vo.setCurrentConnectionCount(currentConnectionCount);
} catch (Exception e) {
log.error("", e);
}
return vo;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;
import org.olat.core.util.WorkThreadInformations;
import org.olat.restapi.system.vo.DateParam;
import org.olat.restapi.system.vo.MemoryPoolVO;
import org.olat.restapi.system.vo.MemorySampleVO;
import org.olat.restapi.system.vo.MemoryVO;
/**
*
* <h3>Description:</h3>
* Initial Date: 21 juin 2010 <br>
* @author srosse, stephane.rosse@frentix.com, www.frentix.com
*/
public class MemoryWebService implements Sampler {
private static final OLog log = Tracing.createLoggerFor(MemoryWebService.class);
private List<MemorySampleVO> memorySamples = new ArrayList<MemorySampleVO>(1000);
public MemoryWebService() {
//start sampling
}
@Override
public void takeSample() {
MemorySampleVO sample = new MemorySampleVO();
sample.setDate(new Date());
sample.setMemory(createMemoryVO());
sample.setMemoryPools(createMemoryPools());
while(memorySamples.size() >= 1000) {
memorySamples.remove(0);
}
memorySamples.add(sample);
Runtime r = Runtime.getRuntime();
if(r.freeMemory() < 20000000) {
List<String> currentThreadNames = new ArrayList<String>();
WorkThreadInformations.currentThreadNames(currentThreadNames);
for(String currentThreadName:currentThreadNames) {
String currentWork = WorkThreadInformations.get(currentThreadName);
log.info("High memory usage:" + currentThreadName + " work at: " + currentWork);
}
}
}
/**
* Return informations about memory.
* @response.representation.200.mediaType text/plain
* @response.representation.200.doc Informations about memory
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about the memory
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public Response getMemory() {
MemoryVO vo = createMemoryVO();
return Response.ok(vo.toString()).build();
}
/**
* Return some informations about memory.
* @response.representation.200.qname {http://www.example.com}memoryVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc A short summary of the number of classes
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_MEMORYVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about the memory
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getMemoryXml() {
MemoryVO vo = createMemoryVO();
return Response.ok(vo).build();
}
private MemoryVO createMemoryVO() {
Runtime r = Runtime.getRuntime();
long totalMem = r.totalMemory();
// Total used memory in megabytes
long totalUsed = (totalMem - r.freeMemory()) / 1000000;
// Max available memory in VM in megabytes
long maxAvailable = r.maxMemory() / 1000000;
MemoryVO vo = new MemoryVO(totalMem/1000000, totalUsed, maxAvailable);
return vo;
}
@GET
@Path("pools")
@Produces(MediaType.TEXT_PLAIN)
public Response getMemoryPools() {
MemoryPoolVO[] voes = createMemoryPools();
StringBuilder sb = new StringBuilder();
for(MemoryPoolVO vo:voes) {
sb.append(vo.getName()).append(" - ").append(vo.getType()).append(" - ").append(vo.getUsage());
}
return Response.ok(sb.toString()).build();
}
@GET
@Path("pools")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getMemoryPoolsXml() {
MemoryPoolVO[] voes = createMemoryPools();
return Response.ok(voes).build();
}
@GET
@Path("samples")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getSamplesXml(@QueryParam("from") String from, @QueryParam("to") String to, @QueryParam("lastSamples") Integer maxResults) {
List<MemorySampleVO> samples = new ArrayList<MemorySampleVO>(memorySamples);
Date fromDate = null;
if(StringHelper.containsNonWhitespace(from)) {
fromDate = parseDate(from);
}
Date toDate = null;
if(StringHelper.containsNonWhitespace(to)) {
toDate = parseDate(to);
}
if(fromDate != null || toDate != null) {
for(Iterator<MemorySampleVO> sampleIt=samples.iterator(); sampleIt.hasNext();) {
MemorySampleVO sample = sampleIt.next();
if((fromDate != null && fromDate.compareTo(sample.getDate()) > 0) ||
(toDate != null && sample.getDate().compareTo(toDate) > 0)) {
sampleIt.remove();
}
}
}
if(maxResults != null) {
int fromIndex = Math.max(0, memorySamples.size() - maxResults);
samples = samples.subList(fromIndex, memorySamples.size());
}
MemorySampleVO[] voes = new MemorySampleVO[0];
voes = samples.toArray(voes);
return Response.ok(voes).build();
}
private static Date parseDate(String dateStr) {
return new DateParam(dateStr).getDate();
}
private MemoryPoolVO[] createMemoryPools() {
List<MemoryPoolMXBean> memoryPool = ManagementFactory.getMemoryPoolMXBeans();
MemoryPoolVO[] voes = new MemoryPoolVO[memoryPool.size()];
int count = 0;
for(MemoryPoolMXBean bean:memoryPool) {
if(bean.isValid()) {
voes[count++] = new MemoryPoolVO(bean);
}
}
return voes;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.basesecurity.BaseSecurity;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.services.search.SearchServiceStatus;
import org.olat.core.util.SessionInfo;
import org.olat.core.util.UserSession;
import org.olat.course.CourseModule;
import org.olat.group.BusinessGroupService;
import org.olat.instantMessaging.InstantMessagingModule;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryManager;
import org.olat.restapi.system.vo.IndexerStatisticsVO;
import org.olat.restapi.system.vo.OpenOLATStatisticsVO;
import org.olat.restapi.system.vo.RepositoryStatisticsVO;
import org.olat.restapi.system.vo.SessionsVO;
import org.olat.restapi.system.vo.UserStatisticsVO;
import org.olat.search.service.SearchServiceFactory;
import org.olat.search.service.SearchServiceStatusImpl;
import org.olat.search.service.indexer.FullIndexerStatus;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public class OpenOLATStatisticsWebService {
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getStatistics() {
OpenOLATStatisticsVO stats = new OpenOLATStatisticsVO();
stats.setSessions(getSessionsVO());
stats.setUserStatistics(getUserStatistics());
stats.setRepositoryStatistics(getRepositoryStatistics());
stats.setIndexerStatistics(getIndexerStatistics());
return Response.ok(stats).build();
}
@GET
@Path("users")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getUserStatistics(@Context HttpServletRequest request) {
UserStatisticsVO stats = getUserStatistics();
return Response.ok(stats).build();
}
@GET
@Path("repository")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getRepositoryStatistics(@Context HttpServletRequest request) {
RepositoryStatisticsVO stats = getRepositoryStatistics();
return Response.ok(stats).build();
}
@GET
@Path("indexer")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getIndexerStatistics(@Context HttpServletRequest request) {
IndexerStatisticsVO stats = getIndexerStatistics();
return Response.ok(stats).build();
}
/**
* Return some informations about session.
* @response.representation.200.qname {http://www.example.com}sessionVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc A short summary about sessions
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_SESSIONVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about sessions
*/
@GET
@Path("sessions")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getSessions(@Context HttpServletRequest request) {
SessionsVO vo = getSessionsVO();
return Response.ok(vo).build();
}
private UserStatisticsVO getUserStatistics() {
UserStatisticsVO stats = new UserStatisticsVO();
BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class);
long countUsers = securityManager.countIdentitiesByPowerSearch(null, null, false, null, null, null, null, null, null, null, null);
stats.setTotalUserCount(countUsers);
BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
long countGroups = bgs.countBusinessGroups(null, null);
stats.setTotalGroupCount(countGroups);
return stats;
}
private RepositoryStatisticsVO getRepositoryStatistics() {
RepositoryStatisticsVO stats = new RepositoryStatisticsVO();
RepositoryManager repoMgr = CoreSpringFactory.getImpl(RepositoryManager.class);
int allCourses = repoMgr.countByTypeLimitAccess(CourseModule.ORES_TYPE_COURSE, RepositoryEntry.ACC_OWNERS);
int publishedCourses = repoMgr.countByTypeLimitAccess(CourseModule.ORES_TYPE_COURSE, RepositoryEntry.ACC_USERS);
stats.setCoursesCount(allCourses);
stats.setPublishedCoursesCount(publishedCourses);
return stats;
}
private IndexerStatisticsVO getIndexerStatistics() {
IndexerStatisticsVO stats = new IndexerStatisticsVO();
SearchServiceStatus status = SearchServiceFactory.getService().getStatus();
if(status instanceof SearchServiceStatusImpl) {
SearchServiceStatusImpl statusImpl = (SearchServiceStatusImpl)status;
FullIndexerStatus fStatus = statusImpl.getFullIndexerStatus();
stats.setIndexedDocumentCount(fStatus.getDocumentCount());
stats.setExcludedDocumentCount(fStatus.getExcludedDocumentCount());
stats.setIndexSize(fStatus.getIndexSize());
stats.setIndexingTime(fStatus.getIndexingTime());
stats.setFullIndexStartedAt(fStatus.getFullIndexStartedAt());
stats.setDocumentQueueSize(fStatus.getDocumentQueueSize());
stats.setRunningFolderIndexerCount(fStatus.getNumberRunningFolderIndexer());
stats.setAvailableFolderIndexerCount(fStatus.getNumberAvailableFolderIndexer());
stats.setLastFullIndexTime(fStatus.getLastFullIndexTime());
}
stats.setStatus(status.getStatus());
return stats;
}
private SessionsVO getSessionsVO() {
SessionsVO vo = new SessionsVO();
vo.setCount(UserSession.getUserSessionsCnt());
Set<UserSession> userSessions = UserSession.getAuthenticatedUserSessions();
int webdavcount = 0;
int secureWebdavCount = 0;
int authenticatedcount = 0;
int secureAuthenticatedCount = 0;
int restCount = 0;
int secureRestCount = 0;
for (UserSession usess:userSessions) {
SessionInfo sessInfo = usess.getSessionInfo();
if (sessInfo.isWebDAV()) {
webdavcount++;
if (sessInfo.isSecure()) {
secureWebdavCount++;
}
} else if (sessInfo.isREST()) {
restCount++;
if (sessInfo.isSecure()) {
secureRestCount++;
}
} else {
authenticatedcount++;
if (sessInfo.isSecure()) {
secureAuthenticatedCount++;
}
}
}
vo.setAuthenticatedCount(authenticatedcount);
vo.setSecureAuthenticatedCount(secureAuthenticatedCount);
vo.setWebdavCount(webdavcount);
vo.setSecureWebdavCount(secureWebdavCount);
vo.setRestCount(restCount);
vo.setSecureRestCount(secureRestCount);
//Instant messaging
int imConnections = InstantMessagingModule.getAdapter().countConnectedUsers();
vo.setInstantMessagingCount(imConnections);
return vo;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import static org.olat.restapi.security.RestSecurityHelper.isAdmin;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.restapi.system.vo.ClasseStatisticsVO;
import org.olat.restapi.system.vo.MemoryStatisticsVO;
import org.olat.restapi.system.vo.RuntimeStatisticsVO;
import org.olat.restapi.system.vo.ThreadStatisticsVO;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public class RuntimeWebService {
private static final int mb = 1024*1024;
public RuntimeWebService() {
//make Spring happy
}
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getSystemSummaryVO(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
RuntimeStatisticsVO stats = new RuntimeStatisticsVO();
stats.setMemory(getMemoryStatistics());
stats.setThreads(getThreadStatistics());
stats.setClasses(getClasseStatistics());
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
stats.setSystemLoadAverage(os.getSystemLoadAverage());
stats.setStartTime(new Date(runtime.getStartTime()));
stats.setUpTime(runtime.getUptime());
return Response.ok(stats).build();
}
@GET
@Path("memory")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getMemoryStatistics(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
MemoryStatisticsVO stats = getMemoryStatistics();
return Response.ok(stats).build();
}
@GET
@Path("threads")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getThreadStatistics(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
ThreadStatisticsVO stats = getThreadStatistics();
return Response.ok(stats).build();
}
/**
* Return some informations about the number of Java classes...
* @response.representation.200.qname {http://www.example.com}classesVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc A short summary of the number of classes
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_CLASSESVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The information about the classes
*/
@GET
@Path("classes")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getCompilationXml(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
ClasseStatisticsVO stats = getClasseStatistics();
return Response.ok(stats).build();
}
private ThreadStatisticsVO getThreadStatistics() {
ThreadStatisticsVO stats = new ThreadStatisticsVO();
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
stats.setDaemonCount(threadBean.getDaemonThreadCount());
stats.setThreadCount(threadBean.getThreadCount());
stats.setPeakThreadCount(threadBean.getPeakThreadCount());
return stats;
}
private MemoryStatisticsVO getMemoryStatistics() {
MemoryStatisticsVO stats = new MemoryStatisticsVO();
Runtime runtime = Runtime.getRuntime();
stats.setUsedMemory((runtime.totalMemory() - runtime.freeMemory()) / mb);
stats.setFreeMemory(runtime.freeMemory() / mb);
stats.setTotalMemory(runtime.totalMemory() / mb);
return stats;
}
private ClasseStatisticsVO getClasseStatistics() {
ClasseStatisticsVO stats = new ClasseStatisticsVO();
ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
stats.setLoadedClassCount(bean.getLoadedClassCount());
stats.setTotalLoadedClassCount(bean.getTotalLoadedClassCount());
stats.setUnloadedClassCount(bean.getUnloadedClassCount());
return stats;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public interface Sampler {
public void takeSample();
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
*
* <h3>Description:</h3>
* <p>
* <p>
* Initial Date: 21 feb. 2011 <br>
* @author srosse, stephane.rosse@frentix.com, www.frentix.com
*/
public class SamplerJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
SystemWebService.takeSample();
}
}
\ No newline at end of file
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import static org.olat.restapi.security.RestSecurityHelper.isAdmin;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.core.helpers.Settings;
import org.olat.core.util.WebappHelper;
import org.olat.restapi.system.vo.EnvironmentInformationsVO;
import org.olat.restapi.system.vo.ReleaseInfosVO;
/**
*
* <h3>Description:</h3>
* FrentixSystemWebService
* <p>
* Initial Date: 18 jun. 2010 <br>
* @author srosse, stephane.rosse@frentix.com, www.frentix.com
*/
@Path("system")
public class SystemWebService {
private static final MemoryWebService memoryWebService = new MemoryWebService();
private static final ThreadsWebService threadsWebService = new ThreadsWebService();
public SystemWebService() {
//make Spring happy
}
@Path("runtime")
public RuntimeWebService getCompilationXml(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
return new RuntimeWebService();
}
@Path("database")
public DatabaseWebService getDatabaseWS(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
return new DatabaseWebService();
}
@Path("openolat")
public OpenOLATStatisticsWebService getSessionsWS(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
return new OpenOLATStatisticsWebService();
}
@Path("memory")
public MemoryWebService getMemoryWS(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
return memoryWebService;
}
@Path("threads")
public ThreadsWebService getThreadsWS(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
return threadsWebService;
}
/**
* Return some informations about the environment.
* @response.representation.200.qname {http://www.example.com}environmentVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc A short summary of the number of classes
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_ENVVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about the environment
*/
@GET
@Path("environment")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getEnvironnementXml(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
EnvironmentInformationsVO vo = new EnvironmentInformationsVO(os, runtime);
return Response.ok(vo).build();
}
/**
* Return the version of the instance.
* @response.representation.200.qname {http://www.example.com}releaseVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The verison of the instance
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_RELEASEVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about the memory
*/
@GET
@Path("release")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getReleaseInfos(@Context HttpServletRequest request) {
if(!isAdmin(request)) {
return null;
}
ReleaseInfosVO version = new ReleaseInfosVO();
version.setBuildVersion(Settings.getBuildIdentifier());
version.setOlatVersion(Settings.getVersion());
version.setInstanceID(WebappHelper.getInstanceId());
return Response.ok(version).build();
}
public static void takeSample() {
memoryWebService.takeSample();
threadsWebService.takeSample();
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.WorkThreadInformations;
import org.olat.restapi.system.vo.ThreadVO;
import org.olat.restapi.system.vo.ThreadsVO;
/**
*
* <h3>Description:</h3>
*
* Initial Date: 21 juin 2010 <br>
* @author srosse, stephane.rosse@frentix.com, www.frentix.com
*/
public class ThreadsWebService implements Sampler {
private static final OLog log = Tracing.createLoggerFor(ThreadsWebService.class);
private final static NumberFormat percentFormat = NumberFormat.getPercentInstance(Locale.ENGLISH);
private long prevUpTime;
private Map<Long,ThreadVO> threadMap = new HashMap<Long,ThreadVO>();
@GET
@Produces(MediaType.TEXT_PLAIN)
public Response getThreads() {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadsVO vo = new ThreadsVO(bean);
return Response.ok(vo.toString()).build();
}
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getThreadsXml() {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadsVO vo = new ThreadsVO(bean);
return Response.ok(vo).build();
}
@GET
@Path("cpu")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public synchronized Response getThreadsCpu() {
List<ThreadVO> threads = new ArrayList<ThreadVO>(threadMap.values());
Collections.sort(threads);
ThreadVO[] threadVos = threads.toArray(new ThreadVO[threads.size()]);
return Response.ok(threadVos).build();
}
@Override
public synchronized void takeSample() {
updateTimeSeries();
}
private void updateTimeSeries() {
ThreadMXBean threadProxy = ManagementFactory.getThreadMXBean();
RuntimeMXBean runtimeProxy = ManagementFactory.getRuntimeMXBean();
ThreadInfo tis[] = threadProxy.dumpAllThreads(false, false);
List<String> currentThreadNames = new ArrayList<String>();
Set<Long> currentThreadIds = new HashSet<Long>();
for (ThreadInfo ti : tis) {
if (!threadMap.containsKey(ti.getThreadId())) {
ThreadVO threadVO = new ThreadVO();
threadVO.setId(ti.getThreadId());
threadVO.setName(ti.getThreadName());
threadMap.put(ti.getThreadId(), threadVO);
}
currentThreadIds.add(ti.getThreadId());
}
WorkThreadInformations.currentThreadNames(currentThreadNames);
for (ThreadVO threadVO:threadMap.values()) {
threadVO.setPrevCpuTime(Math.max(0, threadVO.getCpuTime()));
threadVO.setCpuTime(Math.max(0, threadProxy.getThreadCpuTime(threadVO.getId())));
}
long upTime = runtimeProxy.getUptime();
if (prevUpTime > 0L && upTime > prevUpTime) {
// elapsedTime is in ms
long elapsedTime = upTime - prevUpTime;
for (ThreadVO threadVO:threadMap.values()) {
// elapsedCpu is in ns
long elapsedCpu = threadVO.getCpuTime() - threadVO.getPrevCpuTime();
// cpuUsage could go higher than 100% because elapsedTime
// and elapsedCpu are not fetched simultaneously. Limit to
// 99% to avoid Chart showing a scale from 0% to 200%.
float cpuUsage = Math.min(99f, elapsedCpu / (elapsedTime * 1000000F));
threadVO.setCpuUsage(cpuUsage);
threadVO.setCpuUsagePercent(percentFormat.format(cpuUsage));
if(cpuUsage > 0.8) {
threadVO.setWarningCounter(threadVO.getWarningCounter() + 1);
if(threadVO.getWarningCounter() >= 2) {
String currentWork = WorkThreadInformations.get(threadVO.getName());
if(currentWork == null) {
currentWork = "unkown";
}
log.info("High usage on thread:" + threadVO + " because thread work at: " + currentWork);
}
} else {
threadVO.setWarningCounter(0);
}
}
}
prevUpTime = upTime;
//clean-up closed threads
for (Iterator<Map.Entry<Long,ThreadVO>> it=threadMap.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<Long,ThreadVO> entry = it.next();
if(!currentThreadIds.contains(entry.getKey())) {
it.remove();
}
}
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system.vo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* Description:<br>
*
* <P>
* Initial Date: 20 déc. 2011 <br>
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "classeStatisticsVO")
public class ClasseStatisticsVO {
@XmlAttribute(name="loadedClassCount", required=true)
private int loadedClassCount;
@XmlAttribute(name="unloadedClassCount", required=true)
private long unloadedClassCount;
@XmlAttribute(name="totalLoadedClassCount", required=true)
private long totalLoadedClassCount;
public ClasseStatisticsVO() {
//make JAXB happy
}
public int getLoadedClassCount() {
return loadedClassCount;
}
public void setLoadedClassCount(int loadedClassCount) {
this.loadedClassCount = loadedClassCount;
}
public long getUnloadedClassCount() {
return unloadedClassCount;
}
public void setUnloadedClassCount(long unloadedClassCount) {
this.unloadedClassCount = unloadedClassCount;
}
public long getTotalLoadedClassCount() {
return totalLoadedClassCount;
}
public void setTotalLoadedClassCount(long totalLoadedClassCount) {
this.totalLoadedClassCount = totalLoadedClassCount;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system.vo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "connectionVO")
public class DatabaseConnectionVO {
@XmlAttribute(name="activeConnectionCount", required=true)
private int activeConnectionCount;
@XmlAttribute(name="currentConnectionCount", required=true)
private long currentConnectionCount;
public DatabaseConnectionVO() {
//make JAXB happy
}
public int getActiveConnectionCount() {
return activeConnectionCount;
}
public void setActiveConnectionCount(int activeConnectionCount) {
this.activeConnectionCount = activeConnectionCount;
}
public long getCurrentConnectionCount() {
return currentConnectionCount;
}
public void setCurrentConnectionCount(long currentConnectionCount) {
this.currentConnectionCount = currentConnectionCount;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system.vo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "databaseVO")
public class DatabaseVO {
private DatabaseConnectionVO connectionInfos;
private HibernateStatisticsVO hibernateStatistics;
public DatabaseVO() {
//make JAXB happy
}
public DatabaseConnectionVO getConnectionInfos() {
return connectionInfos;
}
public void setConnectionInfos(DatabaseConnectionVO connectionInfos) {
this.connectionInfos = connectionInfos;
}
public HibernateStatisticsVO getHibernateStatistics() {
return hibernateStatistics;
}
public void setHibernateStatistics(HibernateStatisticsVO hibernateStatistics) {
this.hibernateStatistics = hibernateStatistics;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system.vo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ws.rs.WebApplicationException;
public class DateParam {
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
private Date date;
public DateParam(String string) throws WebApplicationException {
try {
date = format.parse(string);
}
catch (ParseException exception) {
throw new WebApplicationException(400);
}
}
public Date getDate() {
return date;
}
public String format(Date value) {
return format.format(value.getTime());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment