-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathFeatureFlags.java
158 lines (135 loc) · 6.17 KB
/
FeatureFlags.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
package org.opensearch.common.util;
import org.opensearch.common.settings.Setting;
import org.opensearch.common.settings.Setting.Property;
import org.opensearch.common.settings.Settings;
import java.util.List;
/**
* Utility class to manage feature flags. Feature flags are system properties that must be set on the JVM.
* These are used to gate the visibility/availability of incomplete features. For more information, see
* https://featureflags.io/feature-flag-introduction/
*
* @opensearch.internal
*/
public class FeatureFlags {
/**
* Gates the visibility of the remote store migration support from docrep .
*/
public static final String REMOTE_STORE_MIGRATION_EXPERIMENTAL = "opensearch.experimental.feature.remote_store.migration.enabled";
/**
* Gates the ability for Searchable Snapshots to read snapshots that are older than the
* guaranteed backward compatibility for OpenSearch (one prior major version) on a best effort basis.
*/
public static final String SEARCHABLE_SNAPSHOT_EXTENDED_COMPATIBILITY =
"opensearch.experimental.feature.searchable_snapshot.extended_compatibility.enabled";
/**
* Gates the functionality of extensions.
* Once the feature is ready for production release, this feature flag can be removed.
*/
public static final String EXTENSIONS = "opensearch.experimental.feature.extensions.enabled";
/**
* Gates the functionality of identity.
*/
public static final String IDENTITY = "opensearch.experimental.feature.identity.enabled";
/**
* Gates the functionality of telemetry framework.
*/
public static final String TELEMETRY = "opensearch.experimental.feature.telemetry.enabled";
/**
* Gates the optimization of datetime formatters caching along with change in default datetime formatter.
*/
public static final String DATETIME_FORMATTER_CACHING = "opensearch.experimental.optimization.datetime_formatter_caching.enabled";
/**
* Gates the functionality of writeable remote index
* Once the feature is ready for release, this feature flag can be removed.
*/
public static final String WRITEABLE_REMOTE_INDEX = "opensearch.experimental.feature.writeable_remote_index.enabled";
/**
* Gates the functionality of pluggable cache.
* Enables OpenSearch to use pluggable caches with respective store names via setting.
*/
public static final String PLUGGABLE_CACHE = "opensearch.experimental.feature.pluggable.caching.enabled";
public static final Setting<Boolean> REMOTE_STORE_MIGRATION_EXPERIMENTAL_SETTING = Setting.boolSetting(
REMOTE_STORE_MIGRATION_EXPERIMENTAL,
false,
Property.NodeScope
);
public static final Setting<Boolean> EXTENSIONS_SETTING = Setting.boolSetting(EXTENSIONS, false, Property.NodeScope);
public static final Setting<Boolean> IDENTITY_SETTING = Setting.boolSetting(IDENTITY, false, Property.NodeScope);
public static final Setting<Boolean> TELEMETRY_SETTING = Setting.boolSetting(TELEMETRY, false, Property.NodeScope);
public static final Setting<Boolean> DATETIME_FORMATTER_CACHING_SETTING = Setting.boolSetting(
DATETIME_FORMATTER_CACHING,
true,
Property.NodeScope
);
public static final Setting<Boolean> WRITEABLE_REMOTE_INDEX_SETTING = Setting.boolSetting(
WRITEABLE_REMOTE_INDEX,
false,
Property.NodeScope
);
public static final Setting<Boolean> PLUGGABLE_CACHE_SETTING = Setting.boolSetting(PLUGGABLE_CACHE, false, Property.NodeScope);
private static final List<Setting<Boolean>> ALL_FEATURE_FLAG_SETTINGS = List.of(
REMOTE_STORE_MIGRATION_EXPERIMENTAL_SETTING,
EXTENSIONS_SETTING,
IDENTITY_SETTING,
TELEMETRY_SETTING,
DATETIME_FORMATTER_CACHING_SETTING,
WRITEABLE_REMOTE_INDEX_SETTING,
PLUGGABLE_CACHE_SETTING
);
/**
* Should store the settings from opensearch.yml.
*/
private static Settings settings;
static {
Settings.Builder settingsBuilder = Settings.builder();
for (Setting<Boolean> ffSetting : ALL_FEATURE_FLAG_SETTINGS) {
settingsBuilder = settingsBuilder.put(ffSetting.getKey(), ffSetting.getDefault(Settings.EMPTY));
}
settings = settingsBuilder.build();
}
/**
* This method is responsible to map settings from opensearch.yml to local stored
* settings value. That is used for the existing isEnabled method.
*
* @param openSearchSettings The settings stored in opensearch.yml.
*/
public static void initializeFeatureFlags(Settings openSearchSettings) {
Settings.Builder settingsBuilder = Settings.builder();
for (Setting<Boolean> ffSetting : ALL_FEATURE_FLAG_SETTINGS) {
settingsBuilder = settingsBuilder.put(
ffSetting.getKey(),
openSearchSettings.getAsBoolean(ffSetting.getKey(), ffSetting.getDefault(openSearchSettings))
);
}
settings = settingsBuilder.build();
}
/**
* Used to test feature flags whose values are expected to be booleans.
* This method returns true if the value is "true" (case-insensitive),
* and false otherwise.
*/
public static boolean isEnabled(String featureFlagName) {
if ("true".equalsIgnoreCase(System.getProperty(featureFlagName))) {
// TODO: Remove the if condition once FeatureFlags are only supported via opensearch.yml
return true;
}
return settings != null && settings.getAsBoolean(featureFlagName, false);
}
public static boolean isEnabled(Setting<Boolean> featureFlag) {
if ("true".equalsIgnoreCase(System.getProperty(featureFlag.getKey()))) {
// TODO: Remove the if condition once FeatureFlags are only supported via opensearch.yml
return true;
} else if (settings != null) {
return featureFlag.get(settings);
} else {
return featureFlag.getDefault(Settings.EMPTY);
}
}
}