Skip to content
Snippets Groups Projects
Commit 20457eb7 authored by srosse's avatar srosse
Browse files

no-jira: add a status endpoint to check database, file availability and authenticated users

parent 42bce3f2
No related branches found
No related tags found
No related merge requests found
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
package org.olat.core.util; package org.olat.core.util;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
...@@ -101,4 +103,19 @@ public class WorkThreadInformations { ...@@ -101,4 +103,19 @@ public class WorkThreadInformations {
log.error("Cannot write info message about FolderIndexerWorker: " + filePath, e); log.error("Cannot write info message about FolderIndexerWorker: " + filePath, e);
} }
} }
/**
* The method return an exception if something happens.
*
* @param filePath
* @throws IOException
*/
public static void setInfoFiles(String filePath) throws IOException {
File file = new File(WebappHelper.getUserDataRoot(), "threadInfos");
if(!file.exists()) {
file.mkdirs();
}
File infoFile = new File(file, Thread.currentThread().getName());
FileUtils.save(new FileOutputStream(infoFile), filePath, "UTF-8");
}
} }
...@@ -49,6 +49,11 @@ public class MonitoringWebService { ...@@ -49,6 +49,11 @@ public class MonitoringWebService {
public MonitoringWebService() { public MonitoringWebService() {
//make Spring happy //make Spring happy
} }
@Path("status")
public StatusWebservice getStatus() {
return new StatusWebservice();
}
@Path("runtime") @Path("runtime")
public RuntimeWebService getCompilationXml() { public RuntimeWebService getCompilationXml() {
......
/**
* <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.List;
import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.admin.sysinfo.manager.SessionStatsManager;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.CodeHelper;
import org.olat.core.util.SessionInfo;
import org.olat.core.util.UserSession;
import org.olat.core.util.WorkThreadInformations;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.session.UserSessionManager;
import org.olat.group.BusinessGroup;
import org.olat.properties.Property;
import org.olat.properties.PropertyManager;
import org.olat.restapi.system.vo.StatusVO;
/**
*
* Initial date: 15.02.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class StatusWebservice {
private static final OLog log = Tracing.createLoggerFor(StatusWebservice.class);
private static final String PING_REF = "REST-Ping";
private static final OLATResourceable PING_RESOURCE = OresHelper.createOLATResourceableInstance(PING_REF, 42l);
/**
* Return the statistics about runtime: uptime, classes loaded, memory
* summary, threads count...
*
* @response.representation.200.qname {http://www.example.com}runtimeVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The version of the instance
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_RUNTIMEVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about runtime, uptime, classes loaded, memory summary...
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getSystemSummaryVO() {
StatusVO stats = new StatusVO();
//File
try {
stats.setWriteFile(true);
long startFile = System.nanoTime();
WorkThreadInformations.setInfoFiles("ping");
WorkThreadInformations.unset();
stats.setWriteFileInMilliseconds(CodeHelper.nanoToMilliTime(startFile));
} catch (Exception e) {
stats.setWriteFile(false);
stats.setWriteFileInMilliseconds(-1l);
log.error("", e);
}
//Datebase
try {
stats.setWriteDb(true);
PropertyManager propertyManager = CoreSpringFactory.getImpl(PropertyManager.class);
List<Property> props = propertyManager.findProperties((Identity)null, (BusinessGroup)null, PING_RESOURCE, PING_REF, PING_REF);
if(props != null && props.size() > 0) {
for(Property prop:props) {
propertyManager.deleteProperty(prop);
}
DBFactory.getInstance().commit();
}
long startDB = System.nanoTime();
Property prop = propertyManager.createPropertyInstance(null, null, PING_RESOURCE, PING_REF, PING_REF, 0f, 0l, "-", "-");
DBFactory.getInstance().commit();
stats.setWriteDbInMilliseconds(CodeHelper.nanoToMilliTime(startDB));
propertyManager.deleteProperty(prop);
DBFactory.getInstance().commit();
} catch (Exception e) {
stats.setWriteDb(false);
stats.setWriteDbInMilliseconds(-1l);
log.error("", e);
}
//Secure authenticated user
UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class);
Set<UserSession> userSessions = sessionManager.getAuthenticatedUserSessions();
int secureAuthenticatedCount = 0;
for (UserSession usess:userSessions) {
SessionInfo sessInfo = usess.getSessionInfo();
if (sessInfo.isWebDAV() || sessInfo.isREST()) {
//
} else if (sessInfo.isSecure()) {
secureAuthenticatedCount++;
}
}
stats.setSecureAuthenticatedCount(secureAuthenticatedCount);
//Concurrent dispatch threads
SessionStatsManager sessionStatsManager = CoreSpringFactory.getImpl(SessionStatsManager.class);
stats.setConcurrentDispatchThreads(sessionStatsManager.getConcurrentCounter());
return Response.ok(stats).build();
}
}
/**
* <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;
/**
*
* Initial date: 15.02.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "statusVO")
public class StatusVO {
@XmlAttribute(name="writeFile", required=true)
private boolean writeFile;
@XmlAttribute(name="writeFileInMilliseconds", required=true)
private long writeFileInMilliseconds;
@XmlAttribute(name="writeDb", required=true)
private boolean writeDb;
@XmlAttribute(name="writeDbInMilliseconds", required=true)
private long writeDbInMilliseconds;
@XmlAttribute(name="secureAuthenticatedCount", required=true)
private int secureAuthenticatedCount;
@XmlAttribute(name="concurrentDispatchThreads", required=true)
private long concurrentDispatchThreads;
public boolean isWriteFile() {
return writeFile;
}
public void setWriteFile(boolean writeFile) {
this.writeFile = writeFile;
}
public long getWriteFileInMilliseconds() {
return writeFileInMilliseconds;
}
public void setWriteFileInMilliseconds(long writeFileInMilliseconds) {
this.writeFileInMilliseconds = writeFileInMilliseconds;
}
public boolean isWriteDb() {
return writeDb;
}
public void setWriteDb(boolean writeDb) {
this.writeDb = writeDb;
}
public long getWriteDbInMilliseconds() {
return writeDbInMilliseconds;
}
public void setWriteDbInMilliseconds(long writeDbInMilliseconds) {
this.writeDbInMilliseconds = writeDbInMilliseconds;
}
public int getSecureAuthenticatedCount() {
return secureAuthenticatedCount;
}
public void setSecureAuthenticatedCount(int secureAuthenticatedCount) {
this.secureAuthenticatedCount = secureAuthenticatedCount;
}
public long getConcurrentDispatchThreads() {
return concurrentDispatchThreads;
}
public void setConcurrentDispatchThreads(long concurrentDispatchThreads) {
this.concurrentDispatchThreads = concurrentDispatchThreads;
}
}
...@@ -36,6 +36,7 @@ import org.olat.restapi.system.vo.MemoryStatisticsVO; ...@@ -36,6 +36,7 @@ import org.olat.restapi.system.vo.MemoryStatisticsVO;
import org.olat.restapi.system.vo.MemoryVO; import org.olat.restapi.system.vo.MemoryVO;
import org.olat.restapi.system.vo.MonitoringInfosVO; import org.olat.restapi.system.vo.MonitoringInfosVO;
import org.olat.restapi.system.vo.OpenOLATStatisticsVO; import org.olat.restapi.system.vo.OpenOLATStatisticsVO;
import org.olat.restapi.system.vo.StatusVO;
import org.olat.restapi.system.vo.ReleaseInfosVO; import org.olat.restapi.system.vo.ReleaseInfosVO;
import org.olat.restapi.system.vo.RepositoryStatisticsVO; import org.olat.restapi.system.vo.RepositoryStatisticsVO;
import org.olat.restapi.system.vo.RuntimeStatisticsVO; import org.olat.restapi.system.vo.RuntimeStatisticsVO;
...@@ -59,6 +60,21 @@ import org.olat.test.OlatJerseyTestCase; ...@@ -59,6 +60,21 @@ import org.olat.test.OlatJerseyTestCase;
*/ */
public class SystemTest extends OlatJerseyTestCase { public class SystemTest extends OlatJerseyTestCase {
@Test
public void testMonitoringStatus() throws IOException, URISyntaxException {
RestConnection conn = new RestConnection();
assertTrue(conn.login("administrator", "openolat"));
URI systemUri = conn.getContextURI().path("system").path("monitoring").path("status").build();
StatusVO stats = conn.get(systemUri, StatusVO.class);
Assert.assertNotNull(stats);
Assert.assertTrue(stats.isWriteDb());
Assert.assertTrue(stats.isWriteFile());
Assert.assertTrue(stats.getConcurrentDispatchThreads() >= 0l);
Assert.assertTrue(stats.getSecureAuthenticatedCount() >= 0l);
conn.shutdown();
}
@Test @Test
public void testRuntimeStatisticsInfos() throws IOException, URISyntaxException { public void testRuntimeStatisticsInfos() throws IOException, URISyntaxException {
RestConnection conn = new RestConnection(); RestConnection conn = new RestConnection();
......
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