All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencastproject.statistics.endpoint.StatisticsRestService Maven / Gradle / Ivy

There is a newer version: 16.7
Show newest version
/**
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License
 * at:
 *
 *   http://opensource.org/licenses/ecl2.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package org.opencastproject.statistics.endpoint;

import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.opencastproject.util.doc.rest.RestParameter.Type.STRING;

import org.opencastproject.statistics.api.DataResolution;
import org.opencastproject.statistics.api.StatisticsProvider;
import org.opencastproject.statistics.api.StatisticsService;
import org.opencastproject.statistics.api.TimeSeries;
import org.opencastproject.statistics.api.TimeSeriesProvider;
import org.opencastproject.util.NotFoundException;
import org.opencastproject.util.doc.rest.RestParameter;
import org.opencastproject.util.doc.rest.RestQuery;
import org.opencastproject.util.doc.rest.RestResponse;
import org.opencastproject.util.doc.rest.RestService;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * REST endpoint for Statistics Service.
 *
 */
@Path("/")
@RestService(
    name = "statisticsservice",
    title = "Statistics Service",
    abstractText = "This service provides statistics.",
    notes = {
        "All paths above are relative to the REST endpoint base (something like http://your.server/files)",
        "If the service is down or not working it will return a status 503, this means the the "
            + "underlying service is not working and is either restarting or has failed",
        "A status code 500 means a general failure has occurred which is not recoverable and was "
            + "not anticipated. In other words, there is a bug! You should file an error report "
            + "with your server logs from the time when the error occurred: "
            + "Opencast Issue Tracker"
    }
)
public class StatisticsRestService {

  /** Logging utility */
  private static final Logger logger = LoggerFactory.getLogger(StatisticsRestService.class);

  /** Statistics Service */
  private StatisticsService statisticsService;

  /**
   * OSGi callback for setting statistics service.
   *
   * @param statisticsService
   */
  public void setService(StatisticsService statisticsService) {
    this.statisticsService = statisticsService;
  }

  /**
   * Activates REST service (needed by OSGi)
   *
   * @param cc
   *          ComponentContext
   */
  public void activate(ComponentContext cc) {
  }

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @Path("writeDuration")
  @RestQuery(
      name = "writeDuration",
      description = "Writes a duration",
      returnDescription = "",
      responses = {
          @RestResponse(responseCode = SC_NO_CONTENT, description = "Writing worked")
      }
  )
  public Response writeDuration(
      @QueryParam("organizationId") final String organizationId,
      @QueryParam("measurementName") final String measurementName,
      @QueryParam("retentionPolicy") final String retentionPolicy,
      @QueryParam("organizationIdResourceName") final String organizationIdResourceName,
      @QueryParam("fieldName") final String fieldName,
      @QueryParam("temporalResolution") final String temporalResolution,
      @QueryParam("duration") final String duration) {
    try {
      statisticsService
              .writeDuration(organizationId, measurementName, retentionPolicy, organizationIdResourceName, fieldName,
                      TimeUnit.valueOf(temporalResolution), Duration.parse(duration));
      return Response.ok(Response.Status.NO_CONTENT).build();
    } catch (Exception e) {
      logger.error("Could not retrieve providers: {}", e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    }
  }

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @Path("providers.json")
  @RestQuery(
      name = "getAllAsJson",
      description = "Returns active providers",
      returnDescription = "Returns the active providers JSON document",
      responses = {
          @RestResponse(responseCode = SC_OK, description = "The active providers.")
      }
  )
  public Response getProviders() {
    try {
      return Response.ok(providersToJson(statisticsService.getProviders()).toJSONString()).build();
    } catch (Exception e) {
      logger.error("Could not retrieve providers: {}", e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    }
  }

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @Path("timeseries/{providerId:.+}.json")
  @RestQuery(
      name = "getTimeSeriesAsJson",
      description = "Returns the time series data for the given providerId",
      returnDescription = "Returns the time series data JSON document",
      pathParameters = {
          @RestParameter(name = "providerId", isRequired = true, description = "The provider identifier", type = STRING)
      },
      restParameters = {
          @RestParameter(
              name = "resourceId",
              description = "The id of the resource to get the data for. E.g. episode id.",
              isRequired = true,
              type = STRING
          ),
          @RestParameter(
              name = "from",
              description = "Start of the time series as ISO 8601 UTC date string",
              isRequired = true,
              type = STRING
          ),
          @RestParameter(
              name = "to",
              description = "End of the time series as ISO 8601 UTC date string",
              isRequired = true,
              type = STRING
          ),
          @RestParameter(
              name = "resolution",
              description = "Data aggregation level. Must be one of 'daily', 'weekly', 'monthly', 'yearly'",
              isRequired = true,
              type = STRING
          ),
          @RestParameter(
              name = "zoneId",
              description = "The time zone id to use for calculations",
              isRequired = true,
              type = STRING
          ),
      },
      responses = {
          @RestResponse(responseCode = SC_OK, description = "The time series data.")
      }
  )
  public Response getTimeSeriesData(
      @PathParam("providerId") final String providerId,
      @QueryParam("resourceId") final String resourceId,
      @QueryParam("from") final String from,
      @QueryParam("to") final String to,
      @QueryParam("resolution") final String resolution,
      @QueryParam("zoneId") final String zoneId
  ) {
    try {
      final TimeSeries timeSeries = statisticsService.getTimeSeriesData(
          statisticsService.getProvider(providerId).orElseThrow(NotFoundException::new),
          resourceId,
          Instant.parse(from),
          Instant.parse(to),
          DataResolution.fromString(resolution),
          ZoneId.of(zoneId)
      );
      return Response.ok(timeSeriesToJson(timeSeries).toJSONString()).build();
    } catch (Exception e) {
      logger.error("Could not retrieve time series data for provider {}: {}", providerId, e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    }
  }

  @SuppressWarnings("unchecked")
  private static JSONObject timeSeriesToJson(final TimeSeries timeSeries) {
    final JSONObject json = new JSONObject();
    final JSONArray jsonLabels = new JSONArray();
    final JSONArray jsonValues = new JSONArray();
    for (int i = 0; i < timeSeries.getValues().size(); i++) {
      jsonLabels.add(timeSeries.getLabels().get(i));
      jsonValues.add(timeSeries.getValues().get(i));
    }
    json.put("labels", jsonLabels);
    json.put("values", jsonValues);
    if (timeSeries.getTotal().isPresent()) {
      json.put("total", timeSeries.getTotal().getAsDouble());
    }
    return json;
  }

  @SuppressWarnings("unchecked")
  private static JSONArray providersToJson(final Set providers) {
    final JSONArray json = new JSONArray();
    for (StatisticsProvider provider : providers) {
      final JSONObject jsonProvider = new JSONObject();
      final JSONArray jsonResolutions = new JSONArray();
      jsonProvider.put("id", provider.getId());
      jsonProvider.put("title", provider.getTitle());
      jsonProvider.put("description", provider.getDescription());
      jsonProvider.put("resourceType", provider.getResourceType().name());
      if (provider instanceof TimeSeriesProvider) {
        for (DataResolution resolution : ((TimeSeriesProvider) provider).getDataResolutions()) {
          jsonResolutions.add(resolution.name());
        }
        jsonProvider.put("dataResolutions", jsonResolutions);
      }
      json.add(jsonProvider);
    }
    return json;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy