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

org.glowroot.ui.GaugeConfigJsonService Maven / Gradle / Ivy

There is a newer version: 0.9.28
Show newest version
/*
 * Copyright 2014-2015 the original author or authors.
 *
 * 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 org.glowroot.ui;

import java.io.IOException;
import java.util.List;

import javax.annotation.Nullable;

import org.glowroot.agent.shaded.fasterxml.jackson.databind.ObjectMapper;
import org.glowroot.agent.shaded.fasterxml.jackson.databind.module.SimpleModule;
import org.glowroot.agent.shaded.google.common.base.Optional;
import org.glowroot.agent.shaded.google.common.collect.ImmutableList;
import org.glowroot.agent.shaded.google.common.collect.Lists;
import org.glowroot.agent.shaded.netty.handler.codec.http.HttpResponseStatus;
import org.immutables.value.Value;
import org.glowroot.agent.shaded.slf4j.Logger;
import org.glowroot.agent.shaded.slf4j.LoggerFactory;

import org.glowroot.common.config.GaugeConfig;
import org.glowroot.common.config.GaugeConfig.MBeanAttribute;
import org.glowroot.common.config.ImmutableGaugeConfig;
import org.glowroot.common.config.ImmutableMBeanAttribute;
import org.glowroot.common.live.LiveJvmService;
import org.glowroot.common.live.LiveJvmService.MBeanMeta;
import org.glowroot.common.util.ObjectMappers;
import org.glowroot.storage.repo.ConfigRepository;
import org.glowroot.storage.repo.ConfigRepository.DuplicateMBeanObjectNameException;

import static org.glowroot.agent.shaded.netty.handler.codec.http.HttpResponseStatus.CONFLICT;

@JsonService
class GaugeConfigJsonService {

    private static final String SERVER_ID = "";

    private static final Logger logger = LoggerFactory.getLogger(GaugeConfigJsonService.class);
    private static final ObjectMapper mapper = ObjectMappers.create();

    static {
        SimpleModule module = new SimpleModule();
        module.addAbstractTypeMapping(MBeanAttribute.class, ImmutableMBeanAttribute.class);
        mapper.registerModule(module);
    }

    private final ConfigRepository configRepository;
    private final LiveJvmService liveJvmService;

    GaugeConfigJsonService(ConfigRepository configRepository, LiveJvmService liveJvmService) {
        this.configRepository = configRepository;
        this.liveJvmService = liveJvmService;
    }

    @GET("/backend/config/gauges")
    String getGaugeConfig(String queryString) throws Exception {
        GaugeConfigRequest request = QueryStrings.decode(queryString, GaugeConfigRequest.class);
        Optional version = request.version();
        if (version.isPresent()) {
            GaugeConfig gaugeConfig =
                    configRepository.getGaugeConfig(SERVER_ID, version.get());
            if (gaugeConfig == null) {
                throw new JsonServiceException(HttpResponseStatus.NOT_FOUND);
            }
            return mapper.writeValueAsString(buildResponse(gaugeConfig));
        } else {
            List responses = Lists.newArrayList();
            List gaugeConfigs = configRepository.getGaugeConfigs(SERVER_ID);
            gaugeConfigs = GaugeConfig.orderingByName.immutableSortedCopy(gaugeConfigs);
            for (GaugeConfig gaugeConfig : gaugeConfigs) {
                responses.add(ImmutableGaugeConfigWithWarningMessages.builder()
                        .config(GaugeConfigDto.fromConfig(gaugeConfig))
                        .build());
            }
            return mapper.writeValueAsString(responses);
        }
    }

    @GET("/backend/config/matching-mbean-objects")
    String getMatchingMBeanObjects(String queryString) throws Exception {
        MBeanObjectNameRequest request =
                QueryStrings.decode(queryString, MBeanObjectNameRequest.class);
        return mapper.writeValueAsString(liveJvmService.getMatchingMBeanObjectNames(SERVER_ID,
                request.partialMBeanObjectName(), request.limit()));
    }

    @GET("/backend/config/mbean-attributes")
    String getMBeanAttributes(String queryString) throws Exception {
        MBeanAttributeNamesRequest request =
                QueryStrings.decode(queryString, MBeanAttributeNamesRequest.class);
        boolean duplicateMBean = false;
        for (GaugeConfig gaugeConfig : configRepository.getGaugeConfigs(SERVER_ID)) {
            if (gaugeConfig.mbeanObjectName().equals(request.mbeanObjectName())
                    && !gaugeConfig.version().equals(request.gaugeVersion())) {
                duplicateMBean = true;
                break;
            }
        }
        MBeanMeta mbeanMeta = liveJvmService.getMBeanMeta(SERVER_ID, request.mbeanObjectName());
        return mapper.writeValueAsString(ImmutableMBeanAttributeNamesResponse.builder()
                .duplicateMBean(duplicateMBean)
                .mbeanUnmatched(mbeanMeta.unmatched())
                .mbeanUnavailable(mbeanMeta.unavailable())
                .addAllMbeanAttributes(mbeanMeta.attributeNames())
                .build());
    }

    @POST("/backend/config/gauges/add")
    String addGauge(String content) throws Exception {
        GaugeConfigDto gaugeConfigDto = mapper.readValue(content, ImmutableGaugeConfigDto.class);
        GaugeConfig gaugeConfig = gaugeConfigDto.toConfig();
        try {
            configRepository.insertGaugeConfig(SERVER_ID, gaugeConfig);
        } catch (DuplicateMBeanObjectNameException e) {
            // log exception at debug level
            logger.debug(e.getMessage(), e);
            throw new JsonServiceException(CONFLICT, "mbeanObjectName");
        }
        return mapper.writeValueAsString(buildResponse(gaugeConfig));
    }

    @POST("/backend/config/gauges/update")
    String updateGauge(String content) throws Exception {
        GaugeConfigDto gaugeConfigDto = mapper.readValue(content, ImmutableGaugeConfigDto.class);
        GaugeConfig gaugeConfig = gaugeConfigDto.toConfig();
        String version = gaugeConfigDto.version().get();
        try {
            configRepository.updateGaugeConfig(SERVER_ID, gaugeConfig, version);
        } catch (DuplicateMBeanObjectNameException e) {
            // log exception at debug level
            logger.debug(e.getMessage(), e);
            throw new JsonServiceException(CONFLICT, "mbeanObjectName");
        }
        return mapper.writeValueAsString(buildResponse(gaugeConfig));
    }

    @POST("/backend/config/gauges/remove")
    void removeGauge(String content) throws IOException {
        GaugeConfigRequest request = mapper.readValue(content, ImmutableGaugeConfigRequest.class);
        configRepository.deleteGaugeConfig(SERVER_ID, request.version().get());
    }

    private GaugeResponse buildResponse(GaugeConfig gaugeConfig) throws Exception {
        MBeanMeta mbeanMeta =
                liveJvmService.getMBeanMeta(SERVER_ID, gaugeConfig.mbeanObjectName());
        return ImmutableGaugeResponse.builder()
                .config(GaugeConfigDto.fromConfig(gaugeConfig))
                .mbeanUnmatched(mbeanMeta.unmatched())
                .mbeanUnavailable(mbeanMeta.unavailable())
                .addAllMbeanAvailableAttributeNames(mbeanMeta.attributeNames())
                .build();
    }

    @Value.Immutable
    interface GaugeConfigWithWarningMessages {
        GaugeConfigDto config();
        ImmutableList warningMessages();
    }

    @Value.Immutable
    interface GaugeConfigRequest {
        Optional version();
    }

    @Value.Immutable
    interface MBeanObjectNameRequest {
        String partialMBeanObjectName();
        int limit();
    }

    @Value.Immutable
    interface MBeanAttributeNamesRequest {
        String mbeanObjectName();
        @Nullable
        String gaugeVersion();
    }

    @Value.Immutable
    interface MBeanAttributeNamesResponse {
        boolean mbeanUnavailable();
        boolean mbeanUnmatched();
        boolean duplicateMBean();
        ImmutableList mbeanAttributes();
    }

    @Value.Immutable
    abstract static class GaugeResponse {
        abstract GaugeConfigDto config();
        @Value.Default
        boolean mbeanUnavailable() {
            return false;
        }
        @Value.Default
        boolean mbeanUnmatched() {
            return false;
        }
        abstract ImmutableList mbeanAvailableAttributeNames();
    }

    @Value.Immutable
    abstract static class GaugeConfigDto {

        // display is only used in one direction since it is a derived attribute
        abstract @Nullable String display();
        abstract String mbeanObjectName();
        abstract ImmutableList mbeanAttributes();
        abstract Optional version(); // absent for insert operations

        private static GaugeConfigDto fromConfig(GaugeConfig gaugeConfig) {
            return ImmutableGaugeConfigDto.builder()
                    .display(GaugeConfig.display(gaugeConfig.mbeanObjectName()))
                    .mbeanObjectName(gaugeConfig.mbeanObjectName())
                    .addAllMbeanAttributes(gaugeConfig.mbeanAttributes())
                    .version(gaugeConfig.version())
                    .build();
        }

        private GaugeConfig toConfig() {
            return ImmutableGaugeConfig.builder()
                    .mbeanObjectName(mbeanObjectName())
                    .addAllMbeanAttributes(mbeanAttributes())
                    .build();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy