private RequestMonitor(ConfigurationRegistry configuration, Metric2Registry registry, TracingPlugin tracingPlugin) { this.metricRegistry = registry; this.corePlugin = configuration.getConfig(CorePlugin.class); this.tracingPlugin = tracingPlugin; }
private static void reloadPluginsAndConfiguration() { List<ConfigurationSource> configurationSources = new ArrayList<ConfigurationSource>(); for (StagemonitorConfigurationSourceInitializer initializer : ServiceLoader.load(StagemonitorConfigurationSourceInitializer.class, Stagemonitor.class.getClassLoader())) { initializer.modifyConfigurationSources(new StagemonitorConfigurationSourceInitializer.ModifyArguments(configurationSources)); } configurationSources.remove(null); plugins = ServiceLoader.load(StagemonitorPlugin.class, Stagemonitor.class.getClassLoader()); configuration = ConfigurationRegistry.builder() .optionProviders(plugins) .configSources(configurationSources) .build(); try { for (StagemonitorConfigurationSourceInitializer initializer : ServiceLoader.load(StagemonitorConfigurationSourceInitializer.class, Stagemonitor.class.getClassLoader())) { initializer.onConfigurationInitialized(new StagemonitorConfigurationSourceInitializer.ConfigInitializedArguments(configuration)); } } catch (Exception e) { logger.error(e.getMessage(), e); logger.error("Stagemonitor will be deactivated!"); disabled = true; } } }
/** * Updates the existing value with a new one * * @param newValue the new value * @param configurationSourceName the name of the configuration source that the value should be saved to * @throws IOException if there was an error saving the key to the source * @throws IllegalArgumentException if there was a error processing the configuration key or value or the * configurationSourceName did not match any of the available configuration * sources * @throws UnsupportedOperationException if saving values is not possible with this configuration source */ public void update(T newValue, String configurationSourceName) throws IOException { final String newValueAsString = valueConverter.toString(newValue); configuration.save(key, newValueAsString, configurationSourceName); }
private void addElasticsearchConfigurationSources(ConfigurationRegistry configuration, CorePlugin corePlugin, Collection<String> elasticsearchConfigurationSourceIds) { ElasticsearchClient elasticsearchClient = configuration.getConfig(CorePlugin.class).getElasticsearchClient(); if (corePlugin.isDeactivateStagemonitorIfEsConfigSourceIsDown()) { assertElasticsearchIsAvailable(elasticsearchClient, corePlugin); } for (String configurationId : elasticsearchConfigurationSourceIds) { final ElasticsearchConfigurationSource esSource = new ElasticsearchConfigurationSource(elasticsearchClient, configurationId); configuration.addConfigurationSourceAfter(esSource, SimpleSource.class); } configuration.reloadAllConfigurationOptions(); }
@Test public void testGetConfigSubclass() { final CorePlugin corePluginMock = mock(CorePlugin.class); configuration = ConfigurationRegistry.builder() .addOptionProvider(corePluginMock) .addConfigSource(new SimpleSource()) .build(); assertSame(corePluginMock, configuration.getConfig(CorePlugin.class)); assertNull(configuration.getConfig(new ConfigurationOptionProvider(){}.getClass())); }
@Before public void setUp() throws Exception { configurationRegistry = ConfigurationRegistry.builder() // its also possible to automatically detect all ConfigurationOptionProvider // implementations at runtime via ServiceLoader.load .addOptionProvider(new ExampleConfiguration()) // Defines the hierarchy of configuration sources // The first one has the highest precedence // You can implement custom configuration sources // For example JdbcConfigurationSource to sore config values in your DB .addConfigSource(new SimpleSource()) .addConfigSource(new SystemPropertyConfigurationSource()) .addConfigSource(new PropertyFileConfigurationSource("application.properties")) .addConfigSource(new EnvironmentVariableConfigurationSource()) .build(); // reloads configuration options from all configuration sources each 30 seconds configurationRegistry.scheduleReloadAtRate(30, TimeUnit.SECONDS); exampleConfiguration = configurationRegistry.getConfig(ExampleConfiguration.class); }
void logConfiguration(ConfigurationRegistry configurationRegistry, Logger logger) { final String serviceName = configurationRegistry.getConfig(CoreConfiguration.class).getServiceName(); logger.info("Starting Elastic APM {} as {} on {}", elasticApmVersion, serviceName, getJvmAndOsVersionString()); for (List<ConfigurationOption<?>> options : configurationRegistry.getConfigurationOptionsByCategory().values()) { for (ConfigurationOption<?> option : options) { if (!option.isDefault()) { logConfigWithNonDefaultValue(logger, option); } } } if (configurationRegistry.getConfig(StacktraceConfiguration.class).getApplicationPackages().isEmpty()) { logger.warn("To enable all features and to increase startup times, please configure {}", StacktraceConfiguration.APPLICATION_PACKAGES); } }
@Test public void testValidateConfigurationOption() throws Exception { final ConfigurationOption<Boolean> configurationOption = ConfigurationOption.booleanOption() .key("foo") .addValidator((value) -> { if (!value) { throw new IllegalArgumentException("Validation failed"); } }) .buildWithDefault(true); final ConfigurationOptionProvider optionProvider = TestConfigurationOptionProvider.of(configurationOption); final SimpleSource configurationSource = new SimpleSource("test"); final ConfigurationRegistry config = ConfigurationRegistry.builder() .addOptionProvider(optionProvider) .addConfigSource(configurationSource) .build(); try { config.save("foo", "false", "test"); fail(); } catch (IllegalArgumentException e) { assertEquals("Validation failed", e.getMessage()); } }
public static void main(String[] args) throws IOException { final String json = JsonUtils.toJson(ConfigurationRegistry.builder() .optionProviders(ServiceLoader.load(StagemonitorPlugin.class, ConfigurationRegistry.class.getClassLoader())) .build() .getConfigurationOptionsByCategory()); System.out.println(json); File stagemonitorWidgetDevHtml = new File("stagemonitor-web-servlet/src/test/resources/stagemonitorWidgetDev.html"); String content = FileUtils.readFileToString(stagemonitorWidgetDevHtml); content = content.replaceAll("configurationOptions .*", "configurationOptions = " + json.replace("$", "\\$").replace("\\\"", "\\\\\"") + ";"); FileUtils.writeStringToFile(stagemonitorWidgetDevHtml, content); } }
@Test public void testUpdateConfigurationWrongDatatype() throws IOException { configuration.addConfigurationSource(SimpleSource.forTest("stagemonitor.internal.monitoring", "1")); configuration.reloadAllConfigurationOptions(); assertFalse(corePlugin.isInternalMonitoringActive()); assertEquals("Error in Test Configuration Source: Can't convert '1' to Boolean.", configuration.getConfigurationOptionByKey("stagemonitor.internal.monitoring").getErrorMessage()); configuration.save("stagemonitor.internal.monitoring", "true", "Test Configuration Source"); assertTrue(corePlugin.isInternalMonitoringActive()); assertNull(configuration.getConfigurationOptionByKey("stagemonitor.internal.monitoring").getErrorMessage()); }
@Test public void testAddConfigurationSource() { ConfigurationRegistry configuration = ConfigurationRegistry.builder().build(); configuration.addConfigurationSource(new SimpleSource()); assertEquals(Collections.singletonMap("Transient Configuration Source", true), configuration.getNamesOfConfigurationSources()); }
@Test public void testUpdateConfigurationNonDynamicPersistent() throws IOException { final ConfigurationSource persistentSourceMock = mock(ConfigurationSource.class); when(persistentSourceMock.isSavingPossible()).thenReturn(true); when(persistentSourceMock.isSavingPersistent()).thenReturn(true); when(persistentSourceMock.getName()).thenReturn("Test Persistent"); configuration.addConfigurationSource(persistentSourceMock); assertEquals(0, corePlugin.getConsoleReportingInterval()); configuration.save("stagemonitor.reporting.interval.console", "1", "Test Persistent"); verify(persistentSourceMock).save("stagemonitor.reporting.interval.console", "1"); }
@Test public void testIsPasswordSetTrue() throws Exception { ConfigurationRegistry configuration = ConfigurationRegistry.builder().build(); configuration.addConfigurationSource(SimpleSource.forTest(passwordKey, "")); assertTrue(new ConfigurationPasswordChecker(configuration, passwordKey).isPasswordSet()); }
private ConfigurationRegistry getDefaultConfigurationRegistry(List<ConfigurationSource> configSources) { try { final ConfigurationRegistry configurationRegistry = ConfigurationRegistry.builder() .configSources(configSources) .optionProviders(ServiceLoader.load(ConfigurationOptionProvider.class, ElasticApmTracer.class.getClassLoader())) .failOnMissingRequiredValues(true) .build(); configurationRegistry.scheduleReloadAtRate(30, TimeUnit.SECONDS); return configurationRegistry; } catch (IllegalStateException e) { logger.warn(e.getMessage()); return ConfigurationRegistry.builder() .addConfigSource(new SimpleSource("Noop Configuration") .add(CoreConfiguration.ACTIVE, "false") .add(CoreConfiguration.INSTRUMENT, "false") .add(CoreConfiguration.SERVICE_NAME, "none") .add(CoreConfiguration.SAMPLE_RATE, "0")) .optionProviders(ServiceLoader.load(ConfigurationOptionProvider.class, ElasticApmTracer.class.getClassLoader())) .build(); } }
@Test public void testWithOptions_valid() { final ConfigurationOption<String> option = ConfigurationOption.stringOption() .key("test.options") .addValidOptions("foo", "bar") .buildWithDefault("foo"); final ConfigurationRegistry configuration = createConfiguration(Collections.singletonList(option), SimpleSource.forTest("test.options", "bar")); assertThat(configuration.getConfigurationOptionByKey("test.options").getValueAsString()).isEqualTo("bar"); assertThatThrownBy(() -> configuration.save("test.options", "baz", "Test Configuration Source")) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Invalid option"); }
private boolean reloadConfigIfRequested(HttpServletRequest req) { if (req.getParameter("reload") != null) { configuration.reloadDynamicConfigurationOptions(); return true; } return false; }
@Override public void injectHtml(HtmlInjector.InjectArguments injectArguments) { final List<String> pathsOfWidgetTabPlugins = new ArrayList<String>(); for (String path : Stagemonitor.getPathsOfWidgetTabPlugins()) { pathsOfWidgetTabPlugins.add(contextPath + path); } final List<String> pathsOfWidgetMetricTabPlugins = new ArrayList<String>(); for (String path : Stagemonitor.getPathsOfWidgetMetricTabPlugins()) { pathsOfWidgetMetricTabPlugins.add(contextPath + path); } final SpanWrapper span = injectArguments.getSpanWrapper(); injectArguments.setContentToInjectBeforeClosingBody(widgetTemplate .replace("@@JSON_REQUEST_TRACE_PLACEHOLDER@@", span != null ? JsonUtils.toJson(span, SpanUtils.CALL_TREE_ASCII) : "null") .replace("@@CONFIGURATION_OPTIONS@@", JsonUtils.toJson(configuration.getConfigurationOptionsByCategory())) .replace("@@CONFIGURATION_PWD_SET@@", Boolean.toString(servletPlugin.getConfigurationPasswordChecker().isPasswordSet())) .replace("@@CONFIGURATION_SOURCES@@", JsonUtils.toJson(configuration.getNamesOfConfigurationSources())) .replace("@@MEASUREMENT_SESSION@@", JsonUtils.toJson(Stagemonitor.getMeasurementSession())) .replace("@@PATHS_OF_TAB_PLUGINS@@", JsonUtils.toJson(pathsOfWidgetTabPlugins)) .replace("@@PATHS_OF_WIDGET_METRIC_TAB_PLUGINS@@", JsonUtils.toJson(pathsOfWidgetMetricTabPlugins)) .replace("@@CONNECTION_ID@@", UUID.randomUUID().toString())); } }
@Test public void testCachingAndReload() { assertEquals("testCaching", testCaching.getValue()); configSource.add("testCaching", "testCaching2"); assertEquals("testCaching", testCaching.getValue()); configuration.reloadDynamicConfigurationOptions(); assertEquals("testCaching", testCaching.getValue()); configuration.reloadAllConfigurationOptions(); assertEquals("testCaching2", testCaching.getValue()); }
public void logConfiguration(ConfigurationRegistry configuration) { logger.info("# stagemonitor configuration, listing non-default values:"); boolean hasOnlyDefaultOptions = true; for (List<ConfigurationOption<?>> options : configuration.getConfigurationOptionsByCategory().values()) { for (ConfigurationOption<?> option : options) { if (!option.isDefault()) { hasOnlyDefaultOptions = false; logger.info("{}: {} (source: {})", option.getKey(), prepareOptionValueForLog(option), option.getNameOfCurrentConfigurationSource()); if (option.getTags().contains("deprecated")) { logger.warn("Detected usage of deprecated configuration option '{}'. " + "This option might be removed in the future. " + "Please refer to the documentation about alternatives.", option.getKey()); } if (!option.getKey().equals(option.getUsedKey())) { logger.warn("Detected usage of an old configuration key: '{}'. Please use '{}' instead.", option.getUsedKey(), option.getKey()); } } } } if (hasOnlyDefaultOptions) { logger.warn("stagemonitor has not been configured. Have a look at " + "https://github.com/stagemonitor/stagemonitor/wiki/How-should-I-configure-stagemonitor%3F " + "and " + "https://github.com/stagemonitor/stagemonitor/wiki/Configuration-Options " + "for further instructions"); } }
/** * Adds a configuration source as first priority to the configuration. * <p> * Don't forget to call {@link #reloadAllConfigurationOptions()} or {@link #reloadDynamicConfigurationOptions()} * after adding all configuration sources. * * @param configurationSource the configuration source to add */ public void addConfigurationSource(ConfigurationSource configurationSource) { addConfigurationSource(configurationSource, true); }