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

org.zodiac.monitor.console.ui.ApplicationReactiveController Maven / Gradle / Ivy

package org.zodiac.monitor.console.ui;

import java.net.URI;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.Link;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
import org.springframework.boot.actuate.endpoint.web.WebOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.zodiac.commons.util.Colls;
import org.zodiac.monitor.console.constants.MonitorConsoleConstants;
import org.zodiac.monitor.console.event.InstanceEndpointsDetectedEvent;
import org.zodiac.monitor.console.event.InstanceEvent;
import org.zodiac.monitor.console.event.InstanceEventLog;
import org.zodiac.monitor.console.event.InstanceRegisteredEvent;
import org.zodiac.monitor.console.event.InstanceStatusChangedEvent;
import org.zodiac.monitor.console.model.Application;
import org.zodiac.monitor.console.model.Endpoints;
import org.zodiac.monitor.console.model.Instance;
import org.zodiac.monitor.console.model.Registration;
import org.zodiac.monitor.console.model.UserInfo;
import org.zodiac.sdk.toolkit.util.collection.CollUtil;

/**
 * @author zodiac
 */
@RestController
@RequestMapping(path = {"/monitor", "/_monitor"})
public class ApplicationReactiveController {

    private Collection> endpoints;

    private Application application;

    private UserInfo userInfo;

    private InstanceEventLog instanceEventLog;

    public ApplicationReactiveController(Collection> endpoints, Application application,
        InstanceEventLog instanceEventLog, UserInfo userInfo) {
        this.endpoints = endpoints;
        this.application = application;
        this.instanceEventLog = instanceEventLog;
        this.userInfo = userInfo;
    }

    @ResponseBody
    @GetMapping(path = "/applications", produces = MediaType.APPLICATION_JSON_VALUE)
    public List applications(@CookieValue(name = MonitorConsoleConstants.CONSOLE_MONITOR_ID_COOKIE_NAME, required = false) String monitorId,
        ServerHttpRequest request, ServerHttpResponse response) {
        /*不设置用户名密码直接返回成功*/
        if (userInfo.getUsername() != null && userInfo.getPassword() != null) {
            if (monitorId == null || !monitorId.equals(userInfo.getUsernameToken())) {
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return null;
            }
        }
        initApplicationInfo(request);
        return Arrays.asList(application);
    }

    /**
     * 组装application信息。
     * 
     * @param request 请求
     */
    public void initApplicationInfo(ServerHttpRequest request) {
        String normalizedUrl = normalizeRequestUrl(request);
        Map links = CollUtil.concurrentMap();
        for (ExposableEndpoint endpoint : this.endpoints) {
            if (endpoint instanceof ExposableWebEndpoint) {
                collectLinks(links, (ExposableWebEndpoint)endpoint, normalizedUrl);
            } else if (endpoint instanceof PathMappedEndpoint) {
                links.put(endpoint.getEndpointId().toString(), createLink(normalizedUrl, ((PathMappedEndpoint)endpoint).getRootPath()));
            }
        }
        Endpoints endpoints = new Endpoints(links);
        Registration registration = new Registration(application.getName(), normalizedUrl, normalizedUrl + "/health",
            hostUrl(request), "http-api");
        Instance instance = new Instance(application.getName(), registration, endpoints);
        application.setInstances(Arrays.asList(instance));

        if (!instanceEventLog.isHasInit()) {
            InstanceRegisteredEvent instanceRegisteredEvent =
                new InstanceRegisteredEvent(application.getName(), 0, Instant.now(), registration);
            instanceEventLog.add(instanceRegisteredEvent);
            InstanceStatusChangedEvent instanceStatusChangedEvent =
                new InstanceStatusChangedEvent(application.getName(), 1, Instant.now(), instance.getStatusInfo());
            instanceEventLog.add(instanceStatusChangedEvent);
            InstanceEndpointsDetectedEvent instanceEndpointsDetectedEvent =
                new InstanceEndpointsDetectedEvent(application.getName(), 2, Instant.now(), endpoints);
            instanceEventLog.add(instanceEndpointsDetectedEvent);
            instanceEventLog.setHasInit(true);
        }
    }

    @ResponseBody
    @GetMapping(path = "/applications", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public List applicationsStream(ServerHttpRequest request, ServerHttpResponse response) {
        initApplicationInfo(request);
        return Arrays.asList(application);
    }

    @ResponseBody
    @GetMapping(path = "instances/events", produces = MediaType.APPLICATION_JSON_VALUE)
    public List events(ServerHttpRequest request, ServerHttpResponse response) {
        if (!instanceEventLog.isHasInit()) {
            return Collections.emptyList();
        }
        return instanceEventLog.getEventList();
    }

    @ResponseBody
    @GetMapping(path = "instances/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public List> eventsStream(ServerHttpRequest request, ServerHttpResponse response) {
        if (!instanceEventLog.isHasInit()) {
            return Collections.emptyList();
        }
        List> retList = CollUtil.list();
        for (InstanceEvent event : instanceEventLog.getEventList()) {
            retList.add(ServerSentEvent.builder(event).build());
        }
        return retList;
    }

    private String normalizeRequestUrl(ServerHttpRequest request) {
        URI requestUri = request.getURI();
        String uri = requestUri.getScheme() + "://" + requestUri.getHost() + request.getPath().contextPath().value();

        if (!uri.endsWith("/")) {
            uri = uri + "/";
        }

        return uri + "actuator";
    }

    private String hostUrl(ServerHttpRequest request) {
        URI requestUri = request.getURI();
        String uri = requestUri.getScheme() + "://" + requestUri.getHost() + request.getPath().contextPath().value();

        if (!uri.endsWith("/")) {
            uri = uri + "/";
        }

        return uri;
    }

    private void collectLinks(Map links, ExposableWebEndpoint endpoint, String normalizedUrl) {
        for (WebOperation operation : endpoint.getOperations()) {
            links.put(operation.getId(), createLink(normalizedUrl, operation));
        }
    }

    private Link createLink(String requestUrl, WebOperation operation) {
        return createLink(requestUrl, operation.getRequestPredicate().getPath());
    }

    private Link createLink(String requestUrl, String path) {
        return new Link(requestUrl + (path.startsWith("/") ? path : "/" + path));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy