co.cask.cdap.gateway.handlers.MonitorHandler.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.gateway.handlers.MonitorHandler.java

Source

/*
 * Copyright  2014 Cask Data, Inc.
 *
 * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 co.cask.cdap.gateway.handlers;

import co.cask.cdap.app.store.ServiceStore;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.common.twill.MasterServiceManager;
import co.cask.cdap.gateway.auth.Authenticator;
import co.cask.cdap.gateway.handlers.util.AbstractAppFabricHttpHandler;
import co.cask.cdap.proto.SystemServiceMeta;
import co.cask.http.HttpResponder;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

/**
 * Monitor Handler returns the status of different discoverable services
 */
@Path(Constants.Gateway.GATEWAY_VERSION)
public class MonitorHandler extends AbstractAppFabricHttpHandler {
    private final Map<String, MasterServiceManager> serviceManagementMap;
    private static final String STATUSOK = Constants.Monitor.STATUS_OK;
    private static final String STATUSNOTOK = Constants.Monitor.STATUS_NOTOK;
    private static final String NOTAPPLICABLE = "NA";
    private static final Gson GSON = new Gson();
    private final ServiceStore serviceStore;

    @Inject
    public MonitorHandler(Authenticator authenticator, Map<String, MasterServiceManager> serviceMap,
            ServiceStore serviceStore) throws Exception {
        super(authenticator);
        this.serviceManagementMap = serviceMap;
        this.serviceStore = serviceStore;
    }

    /**
     * Returns the number of instances of CDAP Services
     */
    @Path("/system/services/{service-name}/instances")
    @GET
    public void getServiceInstance(final HttpRequest request, final HttpResponder responder,
            @PathParam("service-name") String serviceName) throws Exception {
        JsonObject reply = new JsonObject();
        if (!serviceManagementMap.containsKey(serviceName)) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("Invalid service name %s", serviceName));
            return;
        }
        MasterServiceManager serviceManager = serviceManagementMap.get(serviceName);
        if (serviceManager.isServiceEnabled()) {
            int actualInstance = serviceManagementMap.get(serviceName).getInstances();
            reply.addProperty("provisioned", actualInstance);
            reply.addProperty("requested", getSystemServiceInstanceCount(serviceName));
            responder.sendJson(HttpResponseStatus.OK, reply);
        } else {
            responder.sendString(HttpResponseStatus.FORBIDDEN,
                    String.format("Service %s is not enabled", serviceName));
        }
    }

    /**
     * Sets the number of instances of CDAP Services
     */
    @Path("/system/services/{service-name}/instances")
    @PUT
    public void setServiceInstance(final HttpRequest request, final HttpResponder responder,
            @PathParam("service-name") final String serviceName) {
        try {
            if (!serviceManagementMap.containsKey(serviceName)) {
                responder.sendString(HttpResponseStatus.NOT_FOUND, "Invalid Service Name");
                return;
            }

            MasterServiceManager serviceManager = serviceManagementMap.get(serviceName);
            int instance = getInstances(request);
            if (!serviceManager.isServiceEnabled()) {
                responder.sendString(HttpResponseStatus.FORBIDDEN,
                        String.format("Service %s is not enabled", serviceName));
                return;
            }

            Integer currentInstance = getSystemServiceInstanceCount(serviceName);
            if (instance < serviceManager.getMinInstances() || instance > serviceManager.getMaxInstances()) {
                String response = String.format("Instance count should be between [%s,%s]",
                        serviceManager.getMinInstances(), serviceManager.getMaxInstances());
                responder.sendString(HttpResponseStatus.BAD_REQUEST, response);
                return;
            } else if (instance == currentInstance) {
                responder.sendStatus(HttpResponseStatus.OK);
                return;
            }

            serviceStore.setServiceInstance(serviceName, instance);
            if (serviceManager.setInstances(instance)) {
                responder.sendStatus(HttpResponseStatus.OK);
            } else {
                responder.sendString(HttpResponseStatus.BAD_REQUEST, "Operation did not succeed");
            }
        } catch (Exception e) {
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    String.format("Error updating instances for service: %s", serviceName));
        }
    }

    // Return the status of CDAP services in JSON format
    @Path("/system/services/status")
    @GET
    public void getBootStatus(final HttpRequest request, final HttpResponder responder) {
        Map<String, String> result = new HashMap<String, String>();
        for (String service : serviceManagementMap.keySet()) {
            MasterServiceManager masterServiceManager = serviceManagementMap.get(service);
            if (masterServiceManager.isServiceEnabled() && masterServiceManager.canCheckStatus()) {
                String status = masterServiceManager.isServiceAvailable() ? STATUSOK : STATUSNOTOK;
                result.put(service, status);
            }
        }
        responder.sendJson(HttpResponseStatus.OK, result);
    }

    @Path("/system/services/{service-name}/status")
    @GET
    public void monitor(final HttpRequest request, final HttpResponder responder,
            @PathParam("service-name") final String serviceName) {
        if (!serviceManagementMap.containsKey(serviceName)) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("Invalid service name %s", serviceName));
            return;
        }
        MasterServiceManager masterServiceManager = serviceManagementMap.get(serviceName);
        if (!masterServiceManager.isServiceEnabled()) {
            responder.sendString(HttpResponseStatus.FORBIDDEN,
                    String.format("Service %s is not enabled", serviceName));
            return;
        }
        if (masterServiceManager.canCheckStatus() && masterServiceManager.isServiceAvailable()) {
            JsonObject json = new JsonObject();
            json.addProperty("status", STATUSOK);
            responder.sendJson(HttpResponseStatus.OK, json);
        } else if (masterServiceManager.canCheckStatus()) {
            JsonObject json = new JsonObject();
            json.addProperty("status", STATUSNOTOK);
            responder.sendJson(HttpResponseStatus.OK, json);
        } else {
            responder.sendString(HttpResponseStatus.BAD_REQUEST, "Operation not valid for this service");
        }
    }

    @Path("/system/services")
    @GET
    public void getServiceSpec(final HttpRequest request, final HttpResponder responder) throws Exception {
        List<SystemServiceMeta> response = Lists.newArrayList();
        SortedSet<String> services = new TreeSet<String>(serviceManagementMap.keySet());
        List<String> serviceList = new ArrayList<String>(services);
        for (String service : serviceList) {
            MasterServiceManager serviceManager = serviceManagementMap.get(service);
            if (serviceManager.isServiceEnabled()) {
                String logs = serviceManager.isLogAvailable() ? Constants.Monitor.STATUS_OK
                        : Constants.Monitor.STATUS_NOTOK;
                String canCheck = serviceManager.canCheckStatus()
                        ? (serviceManager.isServiceAvailable() ? STATUSOK : STATUSNOTOK)
                        : NOTAPPLICABLE;
                //TODO: Add metric name for Event Rate monitoring
                response.add(new SystemServiceMeta(service, serviceManager.getDescription(), canCheck, logs,
                        serviceManager.getMinInstances(), serviceManager.getMaxInstances(),
                        getSystemServiceInstanceCount(service), serviceManager.getInstances()));
            }
        }
        responder.sendJson(HttpResponseStatus.OK, response);
    }

    private int getSystemServiceInstanceCount(String serviceName) throws Exception {
        Integer count = serviceStore.getServiceInstance(serviceName);

        //In standalone mode, this count will be null. And thus we just return the actual instance count.
        if (count == null) {
            return serviceManagementMap.get(serviceName).getInstances();
        } else {
            return count;
        }
    }
}