/* * Copyright 2015-2016 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.agent.it.harness.impl; import java.util.List; import java.util.ListIterator; import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.glowroot.agent.it.harness.ConfigService; import org.glowroot.agent.util.JavaVersion; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.AdvancedConfig; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.GaugeConfig; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.InstrumentationConfig; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.MBeanAttribute; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.PluginConfig; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.PluginProperty; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.TransactionConfig; import org.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.UserRecordingConfig; import org.glowroot.wire.api.model.Proto.OptionalInt32; class ConfigServiceImpl implements ConfigService { private final GrpcServerWrapper server; private final boolean reweavable; ConfigServiceImpl(GrpcServerWrapper server, boolean reweavable) { this.server = server; this.reweavable = reweavable; } @Override public void updateTransactionConfig(TransactionConfig config) throws Exception { AgentConfig agentConfig = server.getAgentConfig(); server.updateAgentConfig(agentConfig.toBuilder() .setTransactionConfig(config) .build()); } @Override public void setPluginProperty(String pluginId, String propertyName, boolean propertyValue) throws Exception { updatePluginConfig(pluginId, propertyName, PluginProperty.Value.newBuilder().setBval(propertyValue).build()); } @Override public void setPluginProperty(String pluginId, String propertyName, @Nullable Double propertyValue) throws Exception { if (propertyValue == null) { updatePluginConfig(pluginId, propertyName, PluginProperty.Value.newBuilder().setDvalNull(true).build()); } else { updatePluginConfig(pluginId, propertyName, PluginProperty.Value.newBuilder().setDval(propertyValue).build()); } } @Override public void setPluginProperty(String pluginId, String propertyName, String propertyValue) throws Exception { updatePluginConfig(pluginId, propertyName, PluginProperty.Value.newBuilder().setSval(propertyValue).build()); } @Override public int updateInstrumentationConfigs(List<InstrumentationConfig> configs) throws Exception { AgentConfig agentConfig = server.getAgentConfig(); server.updateAgentConfig(agentConfig.toBuilder() .clearInstrumentationConfig() .addAllInstrumentationConfig(configs) .build()); if (reweavable) { return server.reweave(); } else { return 0; } } @Override public void updateUserRecordingConfig(UserRecordingConfig config) throws Exception { AgentConfig agentConfig = server.getAgentConfig(); server.updateAgentConfig(agentConfig.toBuilder() .setUserRecordingConfig(config) .build()); } @Override public void updateAdvancedConfig(AdvancedConfig config) throws Exception { AgentConfig agentConfig = server.getAgentConfig(); server.updateAgentConfig(agentConfig.toBuilder() .setAdvancedConfig(config) .build()); } void setSlowThresholdToZero() throws Exception { AgentConfig agentConfig = server.getAgentConfig(); server.updateAgentConfig(agentConfig.toBuilder() .setTransactionConfig(agentConfig.getTransactionConfig().toBuilder() .setSlowThresholdMillis(of(0))) .build()); } void resetConfig() throws Exception { AgentConfig.Builder builder = AgentConfig.newBuilder() .setTransactionConfig(getDefaultTransactionConfig()) .setAdvancedConfig(getDefaultAdvancedConfig()); builder.addAllGaugeConfig(getDefaultGaugeConfigs()); for (PluginConfig pluginConfig : server.getAgentConfig().getPluginConfigList()) { PluginConfig.Builder pluginConfigBuilder = PluginConfig.newBuilder() .setId(pluginConfig.getId()); for (PluginProperty pluginProperty : pluginConfig.getPropertyList()) { pluginConfigBuilder.addProperty(pluginProperty.toBuilder() .setValue(pluginProperty.getDefault())); } builder.addPluginConfig(pluginConfigBuilder.build()); } server.updateAgentConfig(builder.build()); } private void updatePluginConfig(String pluginId, String name, PluginProperty.Value value) throws Exception { PluginConfig pluginConfig = getPluginConfig(pluginId); List<PluginProperty> properties = Lists.newArrayList(pluginConfig.getPropertyList()); ListIterator<PluginProperty> i = properties.listIterator(); boolean found = false; while (i.hasNext()) { PluginProperty existingPluginProperty = i.next(); if (existingPluginProperty.getName().equals(name)) { i.set(existingPluginProperty.toBuilder() .setValue(value) .build()); found = true; break; } } if (!found) { throw new IllegalStateException("Could not find plugin property with name: " + name); } updatePluginConfig(pluginConfig.toBuilder() .clearProperty() .addAllProperty(properties) .build()); } private PluginConfig getPluginConfig(String pluginId) throws InterruptedException { AgentConfig agentConfig = server.getAgentConfig(); for (PluginConfig pluginConfig : agentConfig.getPluginConfigList()) { if (pluginConfig.getId().equals(pluginId)) { return pluginConfig; } } throw new IllegalStateException("Could not find plugin with id: " + pluginId); } private void updatePluginConfig(PluginConfig config) throws Exception { AgentConfig agentConfig = server.getAgentConfig(); List<PluginConfig> pluginConfigs = Lists.newArrayList(agentConfig.getPluginConfigList()); ListIterator<PluginConfig> i = pluginConfigs.listIterator(); boolean found = false; while (i.hasNext()) { if (i.next().getId().equals(config.getId())) { i.set(config); found = true; break; } } if (!found) { throw new IllegalStateException("Could not find plugin with id: " + config.getId()); } server.updateAgentConfig(agentConfig.toBuilder() .clearPluginConfig() .addAllPluginConfig(pluginConfigs) .build()); } private static TransactionConfig getDefaultTransactionConfig() { // TODO this needs to be kept in sync with default values return TransactionConfig.newBuilder() .setProfilingIntervalMillis(of(1000)) .setSlowThresholdMillis(of(0)) .setCaptureThreadStats(true) .build(); } private static AdvancedConfig getDefaultAdvancedConfig() { // TODO this needs to be kept in sync with default values return AdvancedConfig.newBuilder() .setWeavingTimer(false) .setImmediatePartialStoreThresholdSeconds(of(60)) .setMaxAggregateTransactionsPerType(of(500)) .setMaxAggregateQueriesPerType(of(500)) .setMaxTraceEntriesPerTransaction(of(2000)) .setMaxStackTraceSamplesPerTransaction(of(10000)) .setMbeanGaugeNotFoundDelaySeconds(of(60)) .build(); } private static List<GaugeConfig> getDefaultGaugeConfigs() { // TODO this needs to be kept in sync with default values List<GaugeConfig> defaultGaugeConfigs = Lists.newArrayList(); defaultGaugeConfigs.add(GaugeConfig.newBuilder() .setMbeanObjectName("java.lang:type=Memory") .addMbeanAttribute(MBeanAttribute.newBuilder() .setName("HeapMemoryUsage.used")) .build()); defaultGaugeConfigs.add(GaugeConfig.newBuilder() .setMbeanObjectName("java.lang:type=GarbageCollector,name=*") .addMbeanAttribute(MBeanAttribute.newBuilder() .setName("CollectionCount") .setCounter(true)) .addMbeanAttribute(MBeanAttribute.newBuilder() .setName("CollectionTime") .setCounter(true)) .build()); defaultGaugeConfigs.add(GaugeConfig.newBuilder() .setMbeanObjectName("java.lang:type=MemoryPool,name=*") .addMbeanAttribute(MBeanAttribute.newBuilder() .setName("Usage.used")) .build()); GaugeConfig.Builder operatingSystemMBean = GaugeConfig.newBuilder() .setMbeanObjectName("java.lang:type=OperatingSystem") .addMbeanAttribute(MBeanAttribute.newBuilder() .setName("FreePhysicalMemorySize")); if (!JavaVersion.isJava6()) { // these are only available since 1.7 operatingSystemMBean.addMbeanAttribute(MBeanAttribute.newBuilder() .setName("ProcessCpuLoad")); operatingSystemMBean.addMbeanAttribute(MBeanAttribute.newBuilder() .setName("SystemCpuLoad")); } defaultGaugeConfigs.add(operatingSystemMBean.build()); return ImmutableList.copyOf(defaultGaugeConfigs); } private static OptionalInt32 of(int value) { return OptionalInt32.newBuilder().setValue(value).build(); } }