
org.glowroot.agent.fat.init.ConfigRepositoryImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of glowroot-agent-it-harness Show documentation
Show all versions of glowroot-agent-it-harness Show documentation
Glowroot Agent Integration Test Harness
/*
* Copyright 2011-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.fat.init;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.annotation.Nullable;
import javax.crypto.SecretKey;
import org.glowroot.agent.shaded.google.common.collect.ImmutableList;
import org.glowroot.agent.shaded.google.common.collect.Lists;
import org.glowroot.agent.shaded.google.common.collect.Maps;
import org.glowroot.agent.shaded.google.common.io.Files;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.glowroot.agent.shaded.slf4j.Logger;
import org.glowroot.agent.shaded.slf4j.LoggerFactory;
import org.glowroot.agent.config.AdvancedConfig;
import org.glowroot.agent.config.AlertConfig;
import org.glowroot.agent.config.ConfigService;
import org.glowroot.agent.config.GaugeConfig;
import org.glowroot.agent.config.InstrumentationConfig;
import org.glowroot.agent.config.PluginCache;
import org.glowroot.agent.config.PluginConfig;
import org.glowroot.agent.config.PluginDescriptor;
import org.glowroot.agent.config.TransactionConfig;
import org.glowroot.agent.config.UiConfig;
import org.glowroot.agent.config.UserRecordingConfig;
import org.glowroot.agent.shaded.glowroot.common.util.Versions;
import org.glowroot.agent.shaded.glowroot.storage.config.AccessConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.FatStorageConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.ImmutableAccessConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.ImmutableFatStorageConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.ImmutableSmtpConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.ServerStorageConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.SmtpConfig;
import org.glowroot.agent.shaded.glowroot.storage.config.StorageConfig;
import org.glowroot.agent.shaded.glowroot.storage.repo.ConfigRepository;
import org.glowroot.agent.shaded.glowroot.storage.util.Encryption;
import org.glowroot.agent.shaded.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig;
import org.glowroot.agent.shaded.glowroot.wire.api.model.AgentConfigOuterClass.AgentConfig.PluginProperty;
import static org.glowroot.agent.shaded.google.common.base.Preconditions.checkState;
class ConfigRepositoryImpl implements ConfigRepository {
private static final Logger logger = LoggerFactory.getLogger(ConfigRepositoryImpl.class);
private final ConfigService configService;
private final PluginCache pluginCache;
private final File secretFile;
private final Object writeLock = new Object();
private final ImmutableList rollupConfigs;
private volatile AccessConfig accessConfig;
private volatile FatStorageConfig storageConfig;
private volatile SmtpConfig smtpConfig;
// volatile not needed as access is guarded by secretFile
private @MonotonicNonNull SecretKey secretKey;
static ConfigRepository create(File baseDir, ConfigService configService,
PluginCache pluginCache) {
ConfigRepositoryImpl configRepository =
new ConfigRepositoryImpl(baseDir, configService, pluginCache);
// it's nice to update admin.json on startup if it is missing some/all config
// properties so that the file contents can be reviewed/updated/copied if desired
try {
configRepository.writeAll();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return configRepository;
}
private ConfigRepositoryImpl(File baseDir, ConfigService configService,
PluginCache pluginCache) {
this.configService = configService;
this.pluginCache = pluginCache;
secretFile = new File(baseDir, "secret");
rollupConfigs = ImmutableList.copyOf(RollupConfig.buildRollupConfigs());
AccessConfig accessConfig = configService.getAdmin(ACCESS_KEY, ImmutableAccessConfig.class);
if (accessConfig == null) {
this.accessConfig = ImmutableAccessConfig.builder().build();
} else {
this.accessConfig = accessConfig;
}
FatStorageConfig storageConfig =
configService.getAdmin(STORAGE_KEY, ImmutableFatStorageConfig.class);
if (storageConfig == null) {
this.storageConfig = ImmutableFatStorageConfig.builder().build();
} else if (storageConfig.hasListIssues()) {
this.storageConfig = withCorrectedLists(storageConfig);
} else {
this.storageConfig = storageConfig;
}
SmtpConfig smtpConfig = configService.getAdmin(SMTP_KEY, ImmutableSmtpConfig.class);
if (smtpConfig == null) {
this.smtpConfig = ImmutableSmtpConfig.builder().build();
} else {
this.smtpConfig = smtpConfig;
}
}
@Override
public AgentConfig.TransactionConfig getTransactionConfig(String agentId) {
return configService.getTransactionConfig().toProto();
}
@Override
public AgentConfig.UiConfig getUiConfig(String agentId) {
return configService.getUiConfig().toProto();
}
@Override
public AgentConfig.UserRecordingConfig getUserRecordingConfig(String agentId) {
return configService.getUserRecordingConfig().toProto();
}
@Override
public AgentConfig.AdvancedConfig getAdvancedConfig(String agentId) {
return configService.getAdvancedConfig().toProto();
}
@Override
public List getGaugeConfigs(String agentId) {
List gaugeConfigs = Lists.newArrayList();
for (GaugeConfig gaugeConfig : configService.getGaugeConfigs()) {
gaugeConfigs.add(gaugeConfig.toProto());
}
return gaugeConfigs;
}
@Override
public @Nullable AgentConfig.GaugeConfig getGaugeConfig(String agentId, String version) {
for (GaugeConfig gaugeConfig : configService.getGaugeConfigs()) {
AgentConfig.GaugeConfig config = gaugeConfig.toProto();
if (Versions.getVersion(config).equals(version)) {
return config;
}
}
return null;
}
@Override
public List getAlertConfigs(String agentId) {
List configs = Lists.newArrayList();
for (AlertConfig config : configService.getAlertConfigs()) {
configs.add(config.toProto());
}
return configs;
}
@Override
public @Nullable AgentConfig.AlertConfig getAlertConfig(String agentId, String version) {
for (AlertConfig alertConfig : configService.getAlertConfigs()) {
AgentConfig.AlertConfig config = alertConfig.toProto();
if (Versions.getVersion(config).equals(version)) {
return config;
}
}
return null;
}
@Override
public List getPluginConfigs(String agentId) {
List configs = Lists.newArrayList();
for (PluginConfig config : configService.getPluginConfigs()) {
configs.add(config.toProto());
}
return configs;
}
@Override
public @Nullable AgentConfig.PluginConfig getPluginConfig(String agentId, String pluginId) {
PluginConfig pluginConfig = configService.getPluginConfig(pluginId);
if (pluginConfig == null) {
return null;
}
return pluginConfig.toProto();
}
@Override
public List getInstrumentationConfigs(String agentId) {
List configs = Lists.newArrayList();
for (InstrumentationConfig config : configService.getInstrumentationConfigs()) {
configs.add(config.toProto());
}
return configs;
}
@Override
public @Nullable AgentConfig.InstrumentationConfig getInstrumentationConfig(String agentId,
String version) {
for (InstrumentationConfig instrumentationConfig : configService
.getInstrumentationConfigs()) {
AgentConfig.InstrumentationConfig config = instrumentationConfig.toProto();
if (Versions.getVersion(config).equals(version)) {
return config;
}
}
return null;
}
@Override
public AccessConfig getAccessConfig() {
return accessConfig;
}
@Override
public FatStorageConfig getFatStorageConfig() {
return storageConfig;
}
@Override
public ServerStorageConfig getServerStorageConfig() {
throw new UnsupportedOperationException();
}
@Override
public SmtpConfig getSmtpConfig() {
return smtpConfig;
}
@Override
public void updateTransactionConfig(String agentId,
AgentConfig.TransactionConfig updatedConfig, String priorVersion) throws Exception {
synchronized (writeLock) {
String currVersion =
Versions.getVersion(configService.getTransactionConfig().toProto());
checkVersionsEqual(currVersion, priorVersion);
configService.updateTransactionConfig(TransactionConfig.create(updatedConfig));
}
}
@Override
public void insertGaugeConfig(String agentId, AgentConfig.GaugeConfig gaugeConfig)
throws Exception {
synchronized (writeLock) {
List configs = Lists.newArrayList(configService.getGaugeConfigs());
// check for duplicate mbeanObjectName
for (GaugeConfig loopConfig : configs) {
if (loopConfig.mbeanObjectName().equals(gaugeConfig.getMbeanObjectName())) {
throw new DuplicateMBeanObjectNameException();
}
}
// check for exact duplicate
String version = Versions.getVersion(gaugeConfig);
for (GaugeConfig loopConfig : configs) {
if (Versions.getVersion(loopConfig.toProto()).equals(version)) {
throw new IllegalStateException("This exact gauge already exists");
}
}
configs.add(GaugeConfig.create(gaugeConfig));
configService.updateGaugeConfigs(configs);
}
}
@Override
public void updateGaugeConfig(String agentId, AgentConfig.GaugeConfig gaugeConfig,
String priorVersion) throws Exception {
synchronized (writeLock) {
List configs = Lists.newArrayList(configService.getGaugeConfigs());
boolean found = false;
for (ListIterator i = configs.listIterator(); i.hasNext();) {
GaugeConfig loopConfig = i.next();
String currVersion = Versions.getVersion(loopConfig.toProto());
if (priorVersion.equals(currVersion)) {
i.set(GaugeConfig.create(gaugeConfig));
found = true;
break;
} else if (loopConfig.mbeanObjectName().equals(gaugeConfig.getMbeanObjectName())) {
throw new DuplicateMBeanObjectNameException();
}
}
if (!found) {
throw new OptimisticLockException();
}
configService.updateGaugeConfigs(configs);
}
}
@Override
public void deleteGaugeConfig(String agentId, String version) throws Exception {
synchronized (writeLock) {
List configs = Lists.newArrayList(configService.getGaugeConfigs());
boolean found = false;
for (ListIterator i = configs.listIterator(); i.hasNext();) {
String currVersion = Versions.getVersion(i.next().toProto());
if (version.equals(currVersion)) {
i.remove();
found = true;
break;
}
}
if (!found) {
throw new OptimisticLockException();
}
configService.updateGaugeConfigs(configs);
}
}
@Override
public void insertAlertConfig(String agentId, AgentConfig.AlertConfig alertConfig)
throws Exception {
synchronized (writeLock) {
List configs =
Lists.newArrayList(configService.getAlertConfigs());
// check for exact duplicate
String version = Versions.getVersion(alertConfig);
for (AlertConfig loopConfig : configs) {
if (Versions.getVersion(loopConfig.toProto()).equals(version)) {
throw new IllegalStateException("This exact alert already exists");
}
}
configs.add(AlertConfig.create(alertConfig));
configService.updateAlertConfigs(configs);
}
}
@Override
public void updateAlertConfig(String agentId, AgentConfig.AlertConfig alertConfig,
String priorVersion) throws Exception {
synchronized (writeLock) {
List configs = Lists.newArrayList(configService.getAlertConfigs());
boolean found = false;
for (ListIterator i = configs.listIterator(); i.hasNext();) {
AlertConfig loopConfig = i.next();
String currVersion = Versions.getVersion(loopConfig.toProto());
if (priorVersion.equals(currVersion)) {
i.set(AlertConfig.create(alertConfig));
found = true;
break;
}
}
if (!found) {
throw new OptimisticLockException();
}
configService.updateAlertConfigs(configs);
}
}
@Override
public void deleteAlertConfig(String agentId, String version) throws Exception {
synchronized (writeLock) {
List configs = Lists.newArrayList(configService.getAlertConfigs());
boolean found = false;
for (ListIterator i = configs.listIterator(); i.hasNext();) {
String currVersion = Versions.getVersion(i.next().toProto());
if (version.equals(currVersion)) {
i.remove();
found = true;
break;
}
}
if (!found) {
throw new OptimisticLockException();
}
configService.updateAlertConfigs(configs);
}
}
@Override
public void updateUiConfig(String agentId, AgentConfig.UiConfig uiConfig, String priorVersion)
throws Exception {
synchronized (writeLock) {
String currVersion = Versions.getVersion(configService.getUiConfig().toProto());
checkVersionsEqual(currVersion, priorVersion);
configService.updateUiConfig(UiConfig.create(uiConfig));
}
}
@Override
public void updatePluginConfig(String agentId, String pluginId,
List properties, String priorVersion) throws Exception {
synchronized (writeLock) {
List configs = Lists.newArrayList(configService.getPluginConfigs());
boolean found = false;
for (ListIterator i = configs.listIterator(); i.hasNext();) {
PluginConfig loopPluginConfig = i.next();
if (pluginId.equals(loopPluginConfig.id())) {
String currVersion = Versions.getVersion(loopPluginConfig.toProto());
checkVersionsEqual(currVersion, priorVersion);
PluginDescriptor pluginDescriptor = getPluginDescriptor(pluginId);
i.set(PluginConfig.create(pluginDescriptor, properties));
found = true;
break;
}
}
checkState(found, "Plugin config not found: %s", pluginId);
configService.updatePluginConfigs(configs);
}
}
@Override
public void insertInstrumentationConfig(String agentId,
AgentConfig.InstrumentationConfig instrumentationConfig) throws Exception {
synchronized (writeLock) {
List configs =
Lists.newArrayList(configService.getInstrumentationConfigs());
// check for exact duplicate
String version = Versions.getVersion(instrumentationConfig);
for (InstrumentationConfig loopConfig : configs) {
if (Versions.getVersion(loopConfig.toProto()).equals(version)) {
throw new IllegalStateException("This exact instrumentation already exists");
}
}
configs.add(InstrumentationConfig.create(instrumentationConfig));
configService.updateInstrumentationConfigs(configs);
}
}
@Override
public void updateInstrumentationConfig(String agentId,
AgentConfig.InstrumentationConfig instrumentationConfig, String priorVersion)
throws Exception {
synchronized (writeLock) {
List configs =
Lists.newArrayList(configService.getInstrumentationConfigs());
boolean found = false;
for (ListIterator i = configs.listIterator(); i.hasNext();) {
String currVersion = Versions.getVersion(i.next().toProto());
if (priorVersion.equals(currVersion)) {
i.set(InstrumentationConfig.create(instrumentationConfig));
found = true;
break;
}
}
if (!found) {
throw new OptimisticLockException();
}
configService.updateInstrumentationConfigs(configs);
}
}
@Override
public void deleteInstrumentationConfigs(String agentId, List versions)
throws Exception {
synchronized (writeLock) {
List configs =
Lists.newArrayList(configService.getInstrumentationConfigs());
List remainingVersions = Lists.newArrayList(versions);
for (ListIterator i = configs.listIterator(); i.hasNext();) {
String currVersion = Versions.getVersion(i.next().toProto());
if (remainingVersions.contains(currVersion)) {
i.remove();
remainingVersions.remove(currVersion);
}
}
if (!remainingVersions.isEmpty()) {
throw new OptimisticLockException();
}
configService.updateInstrumentationConfigs(configs);
}
}
@Override
public void insertInstrumentationConfigs(String agentId,
List instrumentationConfigs) throws Exception {
synchronized (writeLock) {
List configs =
Lists.newArrayList(configService.getInstrumentationConfigs());
for (AgentConfig.InstrumentationConfig instrumentationConfig : instrumentationConfigs) {
// check for exact duplicate
String version = Versions.getVersion(instrumentationConfig);
for (InstrumentationConfig loopConfig : configs) {
if (Versions.getVersion(loopConfig.toProto()).equals(version)) {
throw new IllegalStateException(
"This exact instrumentation already exists");
}
}
configs.add(InstrumentationConfig.create(instrumentationConfig));
}
configService.updateInstrumentationConfigs(configs);
}
}
@Override
public void updateUserRecordingConfig(String agentId,
AgentConfig.UserRecordingConfig userRecordingConfig, String priorVersion)
throws Exception {
synchronized (writeLock) {
String currVersion =
Versions.getVersion(configService.getUserRecordingConfig().toProto());
checkVersionsEqual(currVersion, priorVersion);
configService
.updateUserRecordingConfig(UserRecordingConfig.create(userRecordingConfig));
}
}
@Override
public void updateAdvancedConfig(String agentId, AgentConfig.AdvancedConfig advancedConfig,
String priorVersion) throws Exception {
synchronized (writeLock) {
String currVersion = Versions.getVersion(configService.getAdvancedConfig().toProto());
checkVersionsEqual(currVersion, priorVersion);
configService.updateAdvancedConfig(AdvancedConfig.create(advancedConfig));
}
}
@Override
public void updateAccessConfig(AccessConfig updatedConfig, String priorVersion)
throws Exception {
synchronized (writeLock) {
checkVersionsEqual(accessConfig.version(), priorVersion);
configService.updateAdminConfig(ACCESS_KEY, updatedConfig);
accessConfig = updatedConfig;
}
}
@Override
public void updateServerStorageConfig(ServerStorageConfig updatedConfig, String priorVersion) {
throw new UnsupportedOperationException();
}
@Override
public void updateFatStorageConfig(FatStorageConfig updatedConfig, String priorVersion)
throws Exception {
synchronized (writeLock) {
checkVersionsEqual(storageConfig.version(), priorVersion);
configService.updateAdminConfig(STORAGE_KEY, updatedConfig);
storageConfig = updatedConfig;
}
}
@Override
public void updateSmtpConfig(SmtpConfig updatedConfig, String priorVersion) throws Exception {
synchronized (writeLock) {
checkVersionsEqual(smtpConfig.version(), priorVersion);
configService.updateAdminConfig(SMTP_KEY, updatedConfig);
smtpConfig = updatedConfig;
}
}
@Override
public StorageConfig getStorageConfig() {
return getFatStorageConfig();
}
@Override
public long getGaugeCollectionIntervalMillis() {
return configService.getGaugeCollectionIntervalMillis();
}
@Override
public ImmutableList getRollupConfigs() {
return rollupConfigs;
}
// lazy create secret file only when needed
@Override
public SecretKey getSecretKey() throws Exception {
synchronized (secretFile) {
if (secretKey == null) {
if (secretFile.exists()) {
secretKey = Encryption.loadKey(secretFile);
} else {
secretKey = Encryption.generateNewKey();
Files.write(secretKey.getEncoded(), secretFile);
}
}
return secretKey;
}
}
private PluginDescriptor getPluginDescriptor(String pluginId) {
for (PluginDescriptor pluginDescriptor : pluginCache.pluginDescriptors()) {
if (pluginDescriptor.id().equals(pluginId)) {
return pluginDescriptor;
}
}
throw new IllegalStateException("Could not find plugin descriptor: " + pluginId);
}
private void checkVersionsEqual(String version, String priorVersion)
throws OptimisticLockException {
if (!version.equals(priorVersion)) {
throw new OptimisticLockException();
}
}
private void writeAll() throws IOException {
// linked hash map to preserve ordering when writing to config file
Map configs = Maps.newLinkedHashMap();
configs.put(ACCESS_KEY, accessConfig);
configs.put(STORAGE_KEY, storageConfig);
configs.put(SMTP_KEY, smtpConfig);
configService.updateAdminConfigs(configs);
}
private static FatStorageConfig withCorrectedLists(FatStorageConfig storageConfig) {
FatStorageConfig defaultConfig = ImmutableFatStorageConfig.builder().build();
ImmutableList rollupExpirationHours =
fix(storageConfig.rollupExpirationHours(), defaultConfig.rollupExpirationHours());
ImmutableList rollupCappedDatabaseSizesMb =
fix(storageConfig.rollupCappedDatabaseSizesMb(),
defaultConfig.rollupCappedDatabaseSizesMb());
return ImmutableFatStorageConfig.builder()
.copyFrom(storageConfig)
.rollupExpirationHours(rollupExpirationHours)
.rollupCappedDatabaseSizesMb(rollupCappedDatabaseSizesMb)
.build();
}
private static ImmutableList fix(ImmutableList thisList,
List defaultList) {
if (thisList.size() >= defaultList.size()) {
return thisList.subList(0, defaultList.size());
}
List correctedList = Lists.newArrayList(thisList);
for (int i = thisList.size(); i < defaultList.size(); i++) {
correctedList.add(defaultList.get(i));
}
return ImmutableList.copyOf(correctedList);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy