use of org.opencastproject.serviceregistry.api.ServiceStatistics in project opencast by opencast.
the class ServicesEndpoint method getServices.
@GET
@Path("services.json")
@Produces(MediaType.APPLICATION_JSON)
@RestQuery(description = "Returns the list of services", name = "services", restParameters = { @RestParameter(name = "limit", description = "The maximum number of items to return per page", isRequired = false, type = RestParameter.Type.INTEGER), @RestParameter(name = "offset", description = "The offset", isRequired = false, type = RestParameter.Type.INTEGER), @RestParameter(name = "filter", description = "Filter results by name, host, actions, status or free text query", isRequired = false, type = STRING), @RestParameter(name = "sort", description = "The sort order. May include any " + "of the following: host, name, running, queued, completed, meanRunTime, meanQueueTime, " + "status. The sort suffix must be :asc for ascending sort order and :desc for descending.", isRequired = false, type = STRING) }, reponses = { @RestResponse(description = "Returns the list of services from Opencast", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "The list of services")
public Response getServices(@QueryParam("limit") final int limit, @QueryParam("offset") final int offset, @QueryParam("filter") String filter, @QueryParam("sort") String sort) throws Exception {
Option<String> sortOpt = Option.option(StringUtils.trimToNull(sort));
ServicesListQuery query = new ServicesListQuery();
EndpointUtil.addRequestFiltersToQuery(filter, query);
String fName = null;
if (query.getName().isSome())
fName = StringUtils.trimToNull(query.getName().get());
String fHostname = null;
if (query.getHostname().isSome())
fHostname = StringUtils.trimToNull(query.getHostname().get());
String fStatus = null;
if (query.getStatus().isSome())
fStatus = StringUtils.trimToNull(query.getStatus().get());
String fFreeText = null;
if (query.getFreeText().isSome())
fFreeText = StringUtils.trimToNull(query.getFreeText().get());
List<Service> services = new ArrayList<Service>();
for (ServiceStatistics stats : serviceRegistry.getServiceStatistics()) {
Service service = new Service(stats);
if (fName != null && !StringUtils.equalsIgnoreCase(service.getName(), fName))
continue;
if (fHostname != null && !StringUtils.equalsIgnoreCase(service.getHost(), fHostname))
continue;
if (fStatus != null && !StringUtils.equalsIgnoreCase(service.getStatus().toString(), fStatus))
continue;
if (query.getActions().isSome()) {
ServiceState serviceState = service.getStatus();
if (query.getActions().get()) {
if (ServiceState.NORMAL == serviceState)
continue;
} else {
if (ServiceState.NORMAL != serviceState)
continue;
}
}
if (fFreeText != null && !StringUtils.containsIgnoreCase(service.getName(), fFreeText) && !StringUtils.containsIgnoreCase(service.getHost(), fFreeText) && !StringUtils.containsIgnoreCase(service.getStatus().toString(), fFreeText))
continue;
services.add(service);
}
int total = services.size();
if (sortOpt.isSome()) {
Set<SortCriterion> sortCriteria = RestUtils.parseSortQueryParameter(sortOpt.get());
if (!sortCriteria.isEmpty()) {
try {
SortCriterion sortCriterion = sortCriteria.iterator().next();
Collections.sort(services, new ServiceStatisticsComparator(sortCriterion.getFieldName(), sortCriterion.getOrder() == SearchQuery.Order.Ascending));
} catch (Exception ex) {
logger.warn("Failed to sort services collection.", ex);
}
}
}
List<JValue> jsonList = new ArrayList<JValue>();
for (Service s : new SmartIterator<Service>(limit, offset).applyLimitAndOffset(services)) {
jsonList.add(s.toJSON());
}
return RestUtils.okJsonList(jsonList, offset, limit, total);
}
use of org.opencastproject.serviceregistry.api.ServiceStatistics in project opencast by opencast.
the class ServerEndpoint method getServers.
@GET
@Path("servers.json")
@Produces(MediaType.APPLICATION_JSON)
@RestQuery(description = "Returns the list of servers", name = "servers", restParameters = { @RestParameter(name = "limit", description = "The maximum number of items to return per page", isRequired = false, type = INTEGER), @RestParameter(name = "offset", description = "The offset", isRequired = false, type = INTEGER), @RestParameter(name = "filter", description = "Filter results by hostname, status or free text query", isRequired = false, type = STRING), @RestParameter(name = "sort", description = "The sort order. May include any " + "of the following: COMPLETED (jobs), CORES, HOSTNAME, MAINTENANCE, MEANQUEUETIME (mean for jobs), " + "MEANRUNTIME (mean for jobs), ONLINE, QUEUED (jobs), RUNNING (jobs)." + "The suffix must be :ASC for ascending or :DESC for descending sort order (e.g. HOSTNAME:DESC).", isRequired = false, type = STRING) }, reponses = { @RestResponse(description = "Returns the list of jobs from Opencast", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "The list of servers")
public Response getServers(@QueryParam("limit") final int limit, @QueryParam("offset") final int offset, @QueryParam("filter") String filter, @QueryParam("sort") String sort) throws Exception {
ServersListQuery query = new ServersListQuery();
EndpointUtil.addRequestFiltersToQuery(filter, query);
query.setLimit(limit);
query.setOffset(offset);
List<JSONObject> servers = new ArrayList<>();
// Get service statistics for all hosts and services
List<ServiceStatistics> servicesStatistics = serviceRegistry.getServiceStatistics();
for (HostRegistration server : serviceRegistry.getHostRegistrations()) {
// Calculate statistics per server
long jobsCompleted = 0;
int jobsRunning = 0;
int jobsQueued = 0;
long sumMeanRuntime = 0;
long sumMeanQueueTime = 0;
int totalServiceOnHost = 0;
int offlineJobProducerServices = 0;
int totalJobProducerServices = 0;
Set<String> serviceTypes = new HashSet<>();
for (ServiceStatistics serviceStat : servicesStatistics) {
if (server.getBaseUrl().equals(serviceStat.getServiceRegistration().getHost())) {
totalServiceOnHost++;
jobsCompleted += serviceStat.getFinishedJobs();
jobsRunning += serviceStat.getRunningJobs();
jobsQueued += serviceStat.getQueuedJobs();
// mean time values are given in milliseconds,
// we should convert them to seconds,
// because the adminNG UI expect it in this format
sumMeanRuntime += TimeUnit.MILLISECONDS.toSeconds(serviceStat.getMeanRunTime());
sumMeanQueueTime += TimeUnit.MILLISECONDS.toSeconds(serviceStat.getMeanQueueTime());
if (!serviceStat.getServiceRegistration().isOnline() && serviceStat.getServiceRegistration().isJobProducer()) {
offlineJobProducerServices++;
totalJobProducerServices++;
} else if (serviceStat.getServiceRegistration().isJobProducer()) {
totalJobProducerServices++;
}
serviceTypes.add(serviceStat.getServiceRegistration().getServiceType());
}
}
long meanRuntime = totalServiceOnHost > 0 ? Math.round((double) sumMeanRuntime / totalServiceOnHost) : 0L;
long meanQueueTime = totalServiceOnHost > 0 ? Math.round((double) sumMeanQueueTime / totalServiceOnHost) : 0L;
boolean vOnline = server.isOnline();
boolean vMaintenance = server.isMaintenanceMode();
String vHostname = server.getBaseUrl();
int vCores = server.getCores();
if (query.getHostname().isSome() && !StringUtils.equalsIgnoreCase(vHostname, query.getHostname().get()))
continue;
if (query.getStatus().isSome()) {
if (StringUtils.equalsIgnoreCase(ServersListProvider.SERVER_STATUS_ONLINE, query.getStatus().get()) && !vOnline)
continue;
if (StringUtils.equalsIgnoreCase(ServersListProvider.SERVER_STATUS_OFFLINE, query.getStatus().get()) && vOnline)
continue;
if (StringUtils.equalsIgnoreCase(ServersListProvider.SERVER_STATUS_MAINTENANCE, query.getStatus().get()) && !vMaintenance)
continue;
}
if (query.getFreeText().isSome() && !StringUtils.containsIgnoreCase(vHostname, query.getFreeText().get()) && !StringUtils.containsIgnoreCase(server.getIpAddress(), query.getFreeText().get()))
continue;
JSONObject jsonServer = new JSONObject();
jsonServer.put(KEY_ONLINE, vOnline && offlineJobProducerServices <= totalJobProducerServices / 2);
jsonServer.put(KEY_MAINTENANCE, vMaintenance);
jsonServer.put(KEY_HOSTNAME, vHostname);
jsonServer.put(KEY_CORES, vCores);
jsonServer.put(KEY_RUNNING, jobsRunning);
jsonServer.put(KEY_QUEUED, jobsQueued);
jsonServer.put(KEY_COMPLETED, jobsCompleted);
jsonServer.put(KEY_MEAN_RUN_TIME, meanRuntime);
jsonServer.put(KEY_MEAN_QUEUE_TIME, meanQueueTime);
servers.add(jsonServer);
}
// Sorting
Sort sortKey = Sort.HOSTNAME;
Boolean ascending = true;
if (StringUtils.isNotBlank(sort)) {
try {
SortCriterion sortCriterion = RestUtils.parseSortQueryParameter(sort).iterator().next();
sortKey = Sort.valueOf(sortCriterion.getFieldName().toUpperCase());
ascending = SearchQuery.Order.Ascending == sortCriterion.getOrder() || SearchQuery.Order.None == sortCriterion.getOrder();
} catch (WebApplicationException ex) {
logger.warn("Failed to parse sort criterion \"{}\", invalid format.", sort);
} catch (IllegalArgumentException ex) {
logger.warn("Can not apply sort criterion \"{}\", no field with this name.", sort);
}
}
JSONArray jsonList = new JSONArray();
if (!servers.isEmpty()) {
Collections.sort(servers, new ServerComparator(sortKey, ascending));
jsonList.addAll(new SmartIterator(query.getLimit().getOrElse(0), query.getOffset().getOrElse(0)).applyLimitAndOffset(servers));
}
return RestUtils.okJsonList(getServersListAsJson(jsonList), query.getOffset().getOrElse(0), query.getLimit().getOrElse(0), servers.size());
}
use of org.opencastproject.serviceregistry.api.ServiceStatistics in project opencast by opencast.
the class ServiceRegistryJpaImpl method getServiceStatistics.
/**
* Gets performance and runtime statistics for each known service registration.
* For the statistics, only jobs created within the time interval [startDate, endDate] are being considered
*
* @param startDate
* Only jobs created after this data are considered for statistics
* @param endDate
* Only jobs created before this data are considered for statistics
* @return the service statistics
* @throws ServiceRegistryException
* if there is a problem accessing the service registry
*/
private List<ServiceStatistics> getServiceStatistics(Date startDate, Date endDate) throws ServiceRegistryException {
EntityManager em = null;
try {
em = emf.createEntityManager();
Map<Long, JaxbServiceStatistics> statsMap = new HashMap<Long, JaxbServiceStatistics>();
// Make sure we also include the services that have no processing history so far
List<ServiceRegistrationJpaImpl> services = em.createNamedQuery("ServiceRegistration.getAll").getResultList();
for (ServiceRegistrationJpaImpl s : services) {
statsMap.put(s.getId(), new JaxbServiceStatistics(s));
}
Query query = em.createNamedQuery("ServiceRegistration.statistics");
query.setParameter("minDateCreated", startDate, TemporalType.TIMESTAMP);
query.setParameter("maxDateCreated", endDate, TemporalType.TIMESTAMP);
List queryResults = query.getResultList();
for (Object result : queryResults) {
Object[] oa = (Object[]) result;
Number serviceRegistrationId = ((Number) oa[0]);
if (serviceRegistrationId == null || serviceRegistrationId.longValue() == 0)
continue;
Status status = Status.values()[((Number) oa[1]).intValue()];
Number count = (Number) oa[2];
Number meanQueueTime = (Number) oa[3];
Number meanRunTime = (Number) oa[4];
// The statistics query returns a cartesian product, so we need to iterate over them to build up the objects
JaxbServiceStatistics stats = statsMap.get(serviceRegistrationId.longValue());
if (stats == null)
continue;
// the status will be null if there are no jobs at all associated with this service registration
if (status != null) {
switch(status) {
case RUNNING:
stats.setRunningJobs(count.intValue());
break;
case QUEUED:
case DISPATCHING:
stats.setQueuedJobs(count.intValue());
break;
case FINISHED:
stats.setMeanRunTime(meanRunTime.longValue());
stats.setMeanQueueTime(meanQueueTime.longValue());
stats.setFinishedJobs(count.intValue());
break;
default:
break;
}
}
}
List<ServiceStatistics> stats = new ArrayList<ServiceStatistics>(statsMap.values());
Collections.sort(stats, new Comparator<ServiceStatistics>() {
@Override
public int compare(ServiceStatistics o1, ServiceStatistics o2) {
ServiceRegistration reg1 = o1.getServiceRegistration();
ServiceRegistration reg2 = o2.getServiceRegistration();
int typeComparison = reg1.getServiceType().compareTo(reg2.getServiceType());
return typeComparison == 0 ? reg1.getHost().compareTo(reg2.getHost()) : typeComparison;
}
});
return stats;
} catch (Exception e) {
throw new ServiceRegistryException(e);
} finally {
if (em != null)
em.close();
}
}
use of org.opencastproject.serviceregistry.api.ServiceStatistics in project opencast by opencast.
the class ServiceRegistryJpaImpl method activate.
public void activate(ComponentContext cc) {
logger.info("Activate service registry");
// Find this host's url
if (cc == null || StringUtils.isBlank(cc.getBundleContext().getProperty(OpencastConstants.SERVER_URL_PROPERTY))) {
hostName = UrlSupport.DEFAULT_BASE_URL;
} else {
hostName = cc.getBundleContext().getProperty(OpencastConstants.SERVER_URL_PROPERTY);
}
// Check hostname for sanity. It should be the hosts URL with protocol but without any part of the service paths.
if (hostName.endsWith("/")) {
logger.warn("The configured value of {} ends with '/'. This is very likely a configuration error which could " + "lead to services not working properly. Note that this configuration should not contain any part of " + "the service paths.", OpencastConstants.SERVER_URL_PROPERTY);
}
// Clean all undispatchable jobs that were orphaned when this host was last deactivated
cleanUndispatchableJobs(hostName);
// Register JMX beans with statistics
try {
List<ServiceStatistics> serviceStatistics = getServiceStatistics();
hostsStatistics = new HostsStatistics(serviceStatistics);
servicesStatistics = new ServicesStatistics(hostName, serviceStatistics);
jobsStatistics = new JobsStatistics(hostName);
jmxBeans.add(JmxUtil.registerMXBean(hostsStatistics, JMX_HOSTS_STATISTICS_TYPE));
jmxBeans.add(JmxUtil.registerMXBean(servicesStatistics, JMX_SERVICES_STATISTICS_TYPE));
jmxBeans.add(JmxUtil.registerMXBean(jobsStatistics, JMX_JOBS_STATISTICS_TYPE));
} catch (ServiceRegistryException e) {
logger.error("Error registering JMX statistic beans", e);
}
// Find the jobs URL
if (cc == null || StringUtils.isBlank(cc.getBundleContext().getProperty("org.opencastproject.jobs.url"))) {
jobHost = hostName;
} else {
jobHost = cc.getBundleContext().getProperty("org.opencastproject.jobs.url");
}
// Register this host
try {
float maxLoad = Runtime.getRuntime().availableProcessors();
if (cc != null && StringUtils.isNotBlank(cc.getBundleContext().getProperty(OPT_MAXLOAD))) {
try {
maxLoad = Float.parseFloat(cc.getBundleContext().getProperty(OPT_MAXLOAD));
logger.info("Max load has been manually to {}", maxLoad);
} catch (NumberFormatException e) {
logger.warn("Configuration key '{}' is not an integer. Falling back to the number of cores ({})", OPT_MAXLOAD, maxLoad);
}
}
logger.info("Node maximum load set to {}", maxLoad);
String address = InetAddress.getByName(URI.create(hostName).getHost()).getHostAddress();
long maxMemory = Runtime.getRuntime().maxMemory();
int cores = Runtime.getRuntime().availableProcessors();
registerHost(hostName, address, maxMemory, cores, maxLoad);
} catch (Exception e) {
throw new IllegalStateException("Unable to register host " + hostName + " in the service registry", e);
}
// Track any services from this host that need to be added to the service registry
if (cc != null) {
try {
tracker = new RestServiceTracker(cc.getBundleContext());
tracker.open(true);
} catch (InvalidSyntaxException e) {
logger.error("Invalid filter syntax:", e);
throw new IllegalStateException(e);
}
}
// Whether a service accepts a job whose load exceeds the host’s max load
if (cc != null) {
acceptJobLoadsExeedingMaxLoad = getOptContextProperty(cc, ACCEPT_JOB_LOADS_EXCEEDING_PROPERTY).map(Strings.toBool).getOrElse(DEFAULT_ACCEPT_JOB_LOADS_EXCEEDING);
}
systemLoad = getHostLoads(emf.createEntityManager());
}
Aggregations