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

org.elasticsearch.common.util.FeatureFlag Maven / Gradle / Ivy

There is a newer version: 8.15.1
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

package org.elasticsearch.common.util;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.Build;
import org.elasticsearch.core.Booleans;

import java.util.function.Function;

/**
 * A utility class for registering feature flags in Elasticsearch code.
 * 
* Typical usage: *
{
 *    public static final FeatureFlag XYZZY_FEATURE_FLAG = new FeatureFlag("xyzzy");
 *    // ...
 *    if (XYZZY_FEATURE_FLAG.isEnabled()) {
 *        addRestHandlers();
 *        registerSettings();
 *        // etc
 *    }
 * }
*

* The feature flag will be enabled automatically in all {@link Build#isSnapshot() snapshot} builds. * The feature flag can be enabled in release builds by setting the system property "es.{name}_feature_flag_enabled" to {@code true} * (e.g. {@code -Des.xyzzy_feature_flag_enabled=true} *

*/ public class FeatureFlag { private static final Logger logger = LogManager.getLogger(FeatureFlag.class); private final String name; private final boolean enabled; private static final Function GET_SYSTEM_PROPERTY = System::getProperty; public FeatureFlag(String name) { this(name, "enabled", Build.current(), GET_SYSTEM_PROPERTY); } /** * This method exists to register feature flags that use the old {@code {name}_feature_flag_registered} naming for their system * property, instead of the preferred {@code {name}_feature_flag_enabled} name. * It exists so that old style feature flag implementations can be converted to use this utility class without changing the name of * their system property (which would affect consumers of the feature). * @deprecated Use {@link FeatureFlag#FeatureFlag(String)} instead */ @Deprecated public static FeatureFlag legacyRegisteredFlag(String name) { return new FeatureFlag(name, "registered", Build.current(), GET_SYSTEM_PROPERTY); } /** * Accessible for testing only */ FeatureFlag(String name, String suffix, Build build, Function getSystemProperty) { this.name = name; assert name.indexOf('.') == -1 : "Feature flag names may not contain a '.' character"; assert name.contains("feature_flag") == false : "Feature flag names may not contain the string 'feature_flag'"; final String propertyName = "es." + name + "_feature_flag_" + suffix; if (build.isSnapshot()) { enabled = parseSystemProperty(getSystemProperty, propertyName, true); if (enabled == false) { throw new IllegalArgumentException( "Feature flag " + name + " (via system property '" + propertyName + "') cannot be disabled in snapshot builds" ); } logger.info("The current build is a snapshot, feature flag [{}] is enabled", name); } else { enabled = parseSystemProperty(getSystemProperty, propertyName, false); logger.debug("The current build is a not snapshot, feature flag [{}] is {}", name, enabled ? "enabled" : "disabled"); } } private boolean parseSystemProperty(Function getProperty, String propertyName, boolean defaultValue) { final String propertyValue = getProperty.apply(propertyName); logger.trace("Feature flag system property [{}] is set to [{}]", propertyName, propertyValue); try { return Booleans.parseBoolean(propertyValue, defaultValue); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid value [" + propertyValue + "] for system property [" + propertyName + "]", e); } } public boolean isEnabled() { return enabled; } @Override public String toString() { return "Feature-Flag(" + name + "=" + enabled + ")"; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy