Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor FeatureFlags #17611

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

finnegancarroll
Copy link
Contributor

@finnegancarroll finnegancarroll commented Mar 17, 2025

Description

There are a handful of competing ways to set feature flags today.

  1. FeatureFlags.initializeFeatureFlags
    Takes a setting object and overwrites FeatureFlags.settings. Node invokes this to set flags on startup, but it is also used throughout unit tests to dynamically update and clear feature flags. Provides no way to set a single flag without rewriting all settings.

  2. System.setProperty:
    Sets the feature flag as a JVM property. Calls to FeatureFlags.isEnabled() will check System.getProperty() and see this flag. Allows dynamic setting of individual feature flags.

  3. FeatureFlagSetter.set:
    A small wrapper around the above System.setProperty() which additionally tracks which flags it sets. Used only in tests. Tracks set properties and exposes clearAll() to unset all tracked properties which is invoked during OpenSearchTestCase teardown to ensure a "clean slate" for each test.

Together these implementations provide the desired functionality for feature flags across test and non-test use cases but present some issues:

  • Non of the implementations are thread safe as feature flags are global/static and may be modified at any time.
  • System properties persist for the lifetime of the JVM and can carry over to other tests run on the same JVM, polluting other test environments if not cleared.
  • System.getProperty() can be slow and have performance implications when feature flags are retrieved in a hot path.
  • When not using System.setProperty(), clearing or setting any single feature flag resets all flags.

This PR refactors FeatureFlags to consolidate feature flag functionality and remove usage of JVM system properties in all cases except initializeFeatureFlags which is called once by Node on startup.

Specific changes include:

  • Replaces FeatureFlags immutable internal settings with a map.
  • initializeFeatureFlags now reads and sets feature flags from JVM system properties.
  • isEnabled no longer checks JVM system properties to mitigate performance impact.
  • For test use cases functionality for setting/unsetting flags is provided behind FeatureFlags.TestUtils for clarity.
    • @LockFeatureFlag annotation provided as a thread safe way to set a feature flag for the duration of the test case.
    • FeatureFlags.TestUtils.with for thread safe execution of a critical section with provided feature flag enabled.
    • FeatureFlags.TestUtils.FlagLock for directly accessing a feature flag's lock.

Related Issues

Resolves #16519

Check List

  • Functionality includes testing.
  • API changes companion pull request created, if applicable.
  • Public documentation issue/PR created, if applicable.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@github-actions github-actions bot added bug Something isn't working good first issue Good for newcomers Search Search query, autocomplete ...etc v3.0.0 Issues and PRs related to version 3.0.0 labels Mar 17, 2025
Copy link
Contributor

❌ Gradle check result for fdec16b: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from fdec16b to f1d5490 Compare March 17, 2025 19:25
Copy link
Contributor

❌ Gradle check result for f1d5490: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from f1d5490 to 1228bda Compare March 17, 2025 19:44
Copy link
Contributor

❌ Gradle check result for 1228bda: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from 1228bda to b688424 Compare March 17, 2025 20:06
Copy link
Contributor

❌ Gradle check result for 4a3e60f: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll
Copy link
Contributor Author

Verifying isEnabled is represented less in big5 term flame graph per #16519.

Feature branch:
image

Main branch:
image

@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from 4a3e60f to 4bc33cd Compare March 18, 2025 20:37
Copy link
Contributor

❌ Gradle check result for 4bc33cd: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from 4bc33cd to 94fd7af Compare March 18, 2025 21:06
Copy link
Contributor

❌ Gradle check result for 94fd7af: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from feec9a7 to e8ad6be Compare March 18, 2025 21:52
Copy link
Contributor

❌ Gradle check result for e8ad6be: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@finnegancarroll finnegancarroll changed the title Refactor feature flags for better test support Refactor FeatureFlags Mar 18, 2025
@finnegancarroll
Copy link
Contributor Author

{"run-benchmark-test": "id_5"}

Copy link
Contributor

The Jenkins job url is https://build.ci.opensearch.org/job/benchmark-pull-request/2624/ . Final results will be published once the job is completed.

@finnegancarroll
Copy link
Contributor Author

{"run-benchmark-test": "id_3"}

@opensearch-ci-bot
Copy link
Collaborator

Benchmark Results

Benchmark Results for Job: https://build.ci.opensearch.org/job/benchmark-pull-request/2624/

Metric Task Value Unit
Cumulative indexing time of primary shards 69.6455 min
Min cumulative indexing time across primary shards 69.6455 min
Median cumulative indexing time across primary shards 69.6455 min
Max cumulative indexing time across primary shards 69.6455 min
Cumulative indexing throttle time of primary shards 0 min
Min cumulative indexing throttle time across primary shards 0 min
Median cumulative indexing throttle time across primary shards 0 min
Max cumulative indexing throttle time across primary shards 0 min
Cumulative merge time of primary shards 39.4971 min
Cumulative merge count of primary shards 50
Min cumulative merge time across primary shards 39.4971 min
Median cumulative merge time across primary shards 39.4971 min
Max cumulative merge time across primary shards 39.4971 min
Cumulative merge throttle time of primary shards 10.1662 min
Min cumulative merge throttle time across primary shards 10.1662 min
Median cumulative merge throttle time across primary shards 10.1662 min
Max cumulative merge throttle time across primary shards 10.1662 min
Cumulative refresh time of primary shards 1.24378 min
Cumulative refresh count of primary shards 73
Min cumulative refresh time across primary shards 1.24378 min
Median cumulative refresh time across primary shards 1.24378 min
Max cumulative refresh time across primary shards 1.24378 min
Cumulative flush time of primary shards 5.24718 min
Cumulative flush count of primary shards 55
Min cumulative flush time across primary shards 5.24718 min
Median cumulative flush time across primary shards 5.24718 min
Max cumulative flush time across primary shards 5.24718 min
Total Young Gen GC time 1.213 s
Total Young Gen GC count 45
Total Old Gen GC time 0 s
Total Old Gen GC count 0
Store size 19.3685 GB
Translog size 5.12227e-08 GB
Heap used for segments 0 MB
Heap used for doc values 0 MB
Heap used for terms 0 MB
Heap used for norms 0 MB
Heap used for points 0 MB
Heap used for stored fields 0 MB
Segment count 33
Min Throughput index-append 533.09 docs/s
Mean Throughput index-append 555.14 docs/s
Median Throughput index-append 553.5 docs/s
Max Throughput index-append 576.99 docs/s
50th percentile latency index-append 6682.17 ms
90th percentile latency index-append 11185.8 ms
99th percentile latency index-append 14529.5 ms
100th percentile latency index-append 15045.7 ms
50th percentile service time index-append 6679.34 ms
90th percentile service time index-append 11185.8 ms
99th percentile service time index-append 14529.5 ms
100th percentile service time index-append 15045.7 ms
error rate index-append 0 %
Min Throughput wait-until-merges-finish 0 ops/s
Mean Throughput wait-until-merges-finish 0 ops/s
Median Throughput wait-until-merges-finish 0 ops/s
Max Throughput wait-until-merges-finish 0 ops/s
100th percentile latency wait-until-merges-finish 224855 ms
100th percentile service time wait-until-merges-finish 224855 ms
error rate wait-until-merges-finish 0 %
Min Throughput default 19.95 ops/s
Mean Throughput default 19.96 ops/s
Median Throughput default 19.96 ops/s
Max Throughput default 19.96 ops/s
50th percentile latency default 5.60398 ms
90th percentile latency default 6.0789 ms
99th percentile latency default 7.24975 ms
100th percentile latency default 8.27455 ms
50th percentile service time default 4.74304 ms
90th percentile service time default 4.98108 ms
99th percentile service time default 6.21427 ms
100th percentile service time default 7.28716 ms
error rate default 0 %
Min Throughput term 19.99 ops/s
Mean Throughput term 19.99 ops/s
Median Throughput term 19.99 ops/s
Max Throughput term 19.99 ops/s
50th percentile latency term 6.76375 ms
90th percentile latency term 7.18768 ms
99th percentile latency term 8.16676 ms
100th percentile latency term 8.65761 ms
50th percentile service time term 5.99482 ms
90th percentile service time term 6.16012 ms
99th percentile service time term 7.63441 ms
100th percentile service time term 7.87623 ms
error rate term 0 %
Min Throughput phrase 19.97 ops/s
Mean Throughput phrase 19.98 ops/s
Median Throughput phrase 19.98 ops/s
Max Throughput phrase 19.98 ops/s
50th percentile latency phrase 7.70236 ms
90th percentile latency phrase 8.05669 ms
99th percentile latency phrase 8.66324 ms
100th percentile latency phrase 10.4943 ms
50th percentile service time phrase 6.86142 ms
90th percentile service time phrase 7.01882 ms
99th percentile service time phrase 7.67354 ms
100th percentile service time phrase 9.24893 ms
error rate phrase 0 %
Min Throughput articles_monthly_agg_uncached 19.9 ops/s
Mean Throughput articles_monthly_agg_uncached 19.92 ops/s
Median Throughput articles_monthly_agg_uncached 19.92 ops/s
Max Throughput articles_monthly_agg_uncached 19.93 ops/s
50th percentile latency articles_monthly_agg_uncached 9.26923 ms
90th percentile latency articles_monthly_agg_uncached 9.84287 ms
99th percentile latency articles_monthly_agg_uncached 12.0116 ms
100th percentile latency articles_monthly_agg_uncached 14.2108 ms
50th percentile service time articles_monthly_agg_uncached 8.53063 ms
90th percentile service time articles_monthly_agg_uncached 8.82642 ms
99th percentile service time articles_monthly_agg_uncached 11.6331 ms
100th percentile service time articles_monthly_agg_uncached 13.4582 ms
error rate articles_monthly_agg_uncached 0 %
Min Throughput articles_monthly_agg_cached 20.02 ops/s
Mean Throughput articles_monthly_agg_cached 20.02 ops/s
Median Throughput articles_monthly_agg_cached 20.02 ops/s
Max Throughput articles_monthly_agg_cached 20.02 ops/s
50th percentile latency articles_monthly_agg_cached 3.84179 ms
90th percentile latency articles_monthly_agg_cached 4.28907 ms
99th percentile latency articles_monthly_agg_cached 4.66468 ms
100th percentile latency articles_monthly_agg_cached 4.84658 ms
50th percentile service time articles_monthly_agg_cached 3.06734 ms
90th percentile service time articles_monthly_agg_cached 3.19375 ms
99th percentile service time articles_monthly_agg_cached 3.73989 ms
100th percentile service time articles_monthly_agg_cached 3.80996 ms
error rate articles_monthly_agg_cached 0 %
Min Throughput scroll 12.55 pages/s
Mean Throughput scroll 12.58 pages/s
Median Throughput scroll 12.57 pages/s
Max Throughput scroll 12.64 pages/s
50th percentile latency scroll 685.659 ms
90th percentile latency scroll 690.486 ms
99th percentile latency scroll 723.053 ms
100th percentile latency scroll 726.376 ms
50th percentile service time scroll 683.41 ms
90th percentile service time scroll 687.764 ms
99th percentile service time scroll 720.837 ms
100th percentile service time scroll 723.685 ms
error rate scroll 0 %

@opensearch-ci-bot
Copy link
Collaborator

Benchmark Baseline Comparison Results

Benchmark Results for Job: https://build.ci.opensearch.org/job/benchmark-compare/40/

Metric Task Baseline Contender Diff Unit
Cumulative indexing time of primary shards 66.5823 69.6455 3.06325 min
Min cumulative indexing time across primary shard 66.5823 69.6455 3.06325 min
Median cumulative indexing time across primary shard 66.5823 69.6455 3.06325 min
Max cumulative indexing time across primary shard 66.5823 69.6455 3.06325 min
Cumulative indexing throttle time of primary shards 0 0 0 min
Min cumulative indexing throttle time across primary shard 0 0 0 min
Median cumulative indexing throttle time across primary shard 0 0 0 min
Max cumulative indexing throttle time across primary shard 0 0 0 min
Cumulative merge time of primary shards 36.9144 39.4971 2.58272 min
Cumulative merge count of primary shards 50 50 0
Min cumulative merge time across primary shard 36.9144 39.4971 2.58272 min
Median cumulative merge time across primary shard 36.9144 39.4971 2.58272 min
Max cumulative merge time across primary shard 36.9144 39.4971 2.58272 min
Cumulative merge throttle time of primary shards 9.61303 10.1662 0.55318 min
Min cumulative merge throttle time across primary shard 9.61303 10.1662 0.55318 min
Median cumulative merge throttle time across primary shard 9.61303 10.1662 0.55318 min
Max cumulative merge throttle time across primary shard 9.61303 10.1662 0.55318 min
Cumulative refresh time of primary shards 1.30153 1.24378 -0.05775 min
Cumulative refresh count of primary shards 73 73 0
Min cumulative refresh time across primary shard 1.30153 1.24378 -0.05775 min
Median cumulative refresh time across primary shard 1.30153 1.24378 -0.05775 min
Max cumulative refresh time across primary shard 1.30153 1.24378 -0.05775 min
Cumulative flush time of primary shards 5.02535 5.24718 0.22183 min
Cumulative flush count of primary shards 56 55 -1
Min cumulative flush time across primary shard 5.02535 5.24718 0.22183 min
Median cumulative flush time across primary shard 5.02535 5.24718 0.22183 min
Max cumulative flush time across primary shard 5.02535 5.24718 0.22183 min
Total Young Gen GC time 1.268 1.213 -0.055 s
Total Young Gen GC count 44 45 1
Total Old Gen GC time 0 0 0 s
Total Old Gen GC count 0 0 0
Store size 19.3661 19.3685 0.0024 GB
Translog size 5.12227e-08 5.12227e-08 0 GB
Heap used for segments 0 0 0 MB
Heap used for doc values 0 0 0 MB
Heap used for terms 0 0 0 MB
Heap used for norms 0 0 0 MB
Heap used for points 0 0 0 MB
Heap used for stored fields 0 0 0 MB
Segment count 35 33 -2
Min Throughput index-append 556.954 533.093 -23.8608 docs/s
Mean Throughput index-append 573.226 555.145 -18.0815 docs/s
Median Throughput index-append 570.98 553.497 -17.4832 docs/s
Max Throughput index-append 591.414 576.988 -14.426 docs/s
50th percentile latency index-append 6485.8 6682.17 196.374 ms
90th percentile latency index-append 10736 11185.8 449.817 ms
99th percentile latency index-append 13461 14529.5 1068.53 ms
100th percentile latency index-append 14951.6 15045.7 94.0654 ms
50th percentile service time index-append 6486.85 6679.34 192.495 ms
90th percentile service time index-append 10731.4 11185.8 454.37 ms
99th percentile service time index-append 13461 14529.5 1068.53 ms
100th percentile service time index-append 14951.6 15045.7 94.0654 ms
error rate index-append 0 0 0 %
Min Throughput wait-until-merges-finish 0.00548835 0.0044473 -0.00104 ops/s
Mean Throughput wait-until-merges-finish 0.00548835 0.0044473 -0.00104 ops/s
Median Throughput wait-until-merges-finish 0.00548835 0.0044473 -0.00104 ops/s
Max Throughput wait-until-merges-finish 0.00548835 0.0044473 -0.00104 ops/s
100th percentile latency wait-until-merges-finish 182204 224855 42651.3 ms
100th percentile service time wait-until-merges-finish 182204 224855 42651.3 ms
error rate wait-until-merges-finish 0 0 0 %
Min Throughput default 19.9525 19.9481 -0.00438 ops/s
Mean Throughput default 19.9591 19.9554 -0.00371 ops/s
Median Throughput default 19.9594 19.9559 -0.00349 ops/s
Max Throughput default 19.9645 19.9613 -0.00321 ops/s
50th percentile latency default 5.20545 5.60398 0.39853 ms
90th percentile latency default 5.7976 6.0789 0.2813 ms
99th percentile latency default 6.44605 7.24975 0.8037 ms
100th percentile latency default 9.36473 8.27455 -1.09018 ms
50th percentile service time default 4.52042 4.74304 0.22263 ms
90th percentile service time default 4.84029 4.98108 0.1408 ms
99th percentile service time default 5.58834 6.21427 0.62593 ms
100th percentile service time default 8.91136 7.28716 -1.6242 ms
error rate default 0 0 0 %
Min Throughput term 19.9619 19.9875 0.02559 ops/s
Mean Throughput term 19.9673 19.9892 0.02188 ops/s
Median Throughput term 19.9674 19.9891 0.02171 ops/s
Max Throughput term 19.972 19.9906 0.01863 ops/s
50th percentile latency term 6.53014 6.76375 0.23362 ms
90th percentile latency term 7.08096 7.18768 0.10673 ms
99th percentile latency term 8.39588 8.16676 -0.22913 ms
100th percentile latency term 8.5744 8.65761 0.08321 ms
50th percentile service time term 5.76724 5.99482 0.22757 ms
90th percentile service time term 6.17798 6.16012 -0.01786 ms
99th percentile service time term 7.41239 7.63441 0.22201 ms
100th percentile service time term 7.57209 7.87623 0.30414 ms
error rate term 0 0 0 %
Min Throughput phrase 19.9522 19.9724 0.02026 ops/s
Mean Throughput phrase 19.9593 19.9766 0.01729 ops/s
Median Throughput phrase 19.9598 19.9771 0.01733 ops/s
Max Throughput phrase 19.9656 19.98 0.01437 ops/s
50th percentile latency phrase 7.13969 7.70236 0.56267 ms
90th percentile latency phrase 7.85193 8.05669 0.20476 ms
99th percentile latency phrase 9.59321 8.66324 -0.92997 ms
100th percentile latency phrase 9.82166 10.4943 0.6726 ms
50th percentile service time phrase 6.35502 6.86142 0.5064 ms
90th percentile service time phrase 6.89474 7.01882 0.12408 ms
99th percentile service time phrase 8.78502 7.67354 -1.11149 ms
100th percentile service time phrase 9.25579 9.24893 -0.00686 ms
error rate phrase 0 0 0 %
Min Throughput articles_monthly_agg_uncached 19.8827 19.903 0.02034 ops/s
Mean Throughput articles_monthly_agg_uncached 19.8993 19.9165 0.01725 ops/s
Median Throughput articles_monthly_agg_uncached 19.9002 19.9174 0.01721 ops/s
Max Throughput articles_monthly_agg_uncached 19.9128 19.9277 0.01487 ops/s
50th percentile latency articles_monthly_agg_uncached 8.42931 9.26923 0.83992 ms
90th percentile latency articles_monthly_agg_uncached 9.01449 9.84287 0.82838 ms
99th percentile latency articles_monthly_agg_uncached 11.3613 12.0116 0.65035 ms
100th percentile latency articles_monthly_agg_uncached 12.872 14.2108 1.33882 ms
50th percentile service time articles_monthly_agg_uncached 7.70701 8.53063 0.82363 ms
90th percentile service time articles_monthly_agg_uncached 8.14383 8.82642 0.6826 ms
99th percentile service time articles_monthly_agg_uncached 10.7346 11.6331 0.89856 ms
100th percentile service time articles_monthly_agg_uncached 12.6251 13.4582 0.83304 ms
error rate articles_monthly_agg_uncached 0 0 0 %
Min Throughput articles_monthly_agg_cached 20.018 20.0165 -0.00152 ops/s
Mean Throughput articles_monthly_agg_cached 20.0211 20.0189 -0.00228 ops/s
Median Throughput articles_monthly_agg_cached 20.021 20.0184 -0.00256 ops/s
Max Throughput articles_monthly_agg_cached 20.0245 20.0222 -0.00225 ops/s
50th percentile latency articles_monthly_agg_cached 3.02567 3.84179 0.81611 ms
90th percentile latency articles_monthly_agg_cached 3.51716 4.28907 0.77191 ms
99th percentile latency articles_monthly_agg_cached 3.85585 4.66468 0.80883 ms
100th percentile latency articles_monthly_agg_cached 4.02648 4.84658 0.8201 ms
50th percentile service time articles_monthly_agg_cached 2.25914 3.06734 0.8082 ms
90th percentile service time articles_monthly_agg_cached 2.61932 3.19375 0.57443 ms
99th percentile service time articles_monthly_agg_cached 2.80007 3.73989 0.93981 ms
100th percentile service time articles_monthly_agg_cached 2.83951 3.80996 0.97045 ms
error rate articles_monthly_agg_cached 0 0 0 %
Min Throughput scroll 12.5463 12.548 0.00167 pages/s
Mean Throughput scroll 12.5761 12.5789 0.00281 pages/s
Median Throughput scroll 12.5693 12.5718 0.00254 pages/s
Max Throughput scroll 12.6372 12.6423 0.00509 pages/s
50th percentile latency scroll 666.024 685.659 19.6352 ms
90th percentile latency scroll 681.993 690.486 8.49335 ms
99th percentile latency scroll 778.473 723.053 -55.4203 ms
100th percentile latency scroll 786.847 726.376 -60.4711 ms
50th percentile service time scroll 663.62 683.41 19.79 ms
90th percentile service time scroll 679.785 687.764 7.97818 ms
99th percentile service time scroll 776.09 720.837 -55.2531 ms
100th percentile service time scroll 784.191 723.685 -60.5066 ms
error rate scroll 0 0 0 %

@rishabh6788
Copy link
Contributor

{"run-benchmark-test": "id_3"}

Copy link
Contributor

✅ Gradle check result for e8ad6be: SUCCESS

Copy link

codecov bot commented Mar 20, 2025

Codecov Report

Attention: Patch coverage is 95.12195% with 4 lines in your changes missing coverage. Please review.

Project coverage is 72.42%. Comparing base (47d3655) to head (10cdbec).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
.../java/org/opensearch/common/util/FeatureFlags.java 95.12% 4 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #17611      +/-   ##
============================================
- Coverage     72.53%   72.42%   -0.12%     
+ Complexity    65826    65727      -99     
============================================
  Files          5311     5311              
  Lines        305073   305135      +62     
  Branches      44243    44254      +11     
============================================
- Hits         221293   220992     -301     
- Misses        65688    66044     +356     
- Partials      18092    18099       +7     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@finnegancarroll
Copy link
Contributor Author

distance_amount_agg is just barely showing a ~5% regression in 90+ percentile latency.
#17611 (comment)

Copy link
Collaborator

@msfroh msfroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great improvement! Using annotations is much easier (and more consistent) for developers testing their code.

- Remove internal immutable `settings` in favor of `ConcurrentHashMap`.
- Move functionality to internal `FeatureFlagsImpl` class.
Expose public api of `FeatureFlagsImpl` in FeatureFlags.
Expose test api of `FeatureFlagsImpl` in FeatureFlags.TestUtils.
- Read and set JVM system properties once on `initializeFeatureFlags`.
Remove JVM system properties check from `isEnabled`.
- Add `FlagLock` in `TestUtils` to maintain a lock for each feature flag.
- Add helper functions to set & access feature flags in a thread safe way.
`TestUtils.with(<feature flag>, () -> {})` to execute crtical sections.
`New FlagLock(<feature flag>)` for fine grained control.

Signed-off-by: Finn Carroll <[email protected]>
- Add annotation in OpenSearchTestCase to enable and lock a flag for the
duration of a single test case.

Signed-off-by: Finn Carroll <[email protected]>
- Add cases for public api.
- Add cases for thread safe helpers
@LockFeatureFlag
FlagLock
TestUtils.with

Signed-off-by: Finn Carroll <[email protected]>
Signed-off-by: Finn Carroll <[email protected]>
Replace all usages of `FeatureFlagSetter` in tests.
Replace all usages of JVM system properties for feature flags in tests.
Replace all usages of `initializeFeatureFlags` with `TestUtils.set` in tests.

Signed-off-by: Finn Carroll <[email protected]>
Signed-off-by: Finn Carroll <[email protected]>
- Add missing LockFeatureFlag annotations.
- Cannot use annotation in tests which expect exception thrown.
- SEARCHABLE_SNAPSHOT_EXTENDED_COMPATIBILITY has no setting? Adding.
- Flight server tests need flag enabled on setup.

Signed-off-by: Finn Carroll <[email protected]>
@finnegancarroll finnegancarroll force-pushed the feature-flag-kinda-slow branch from e8ad6be to 10cdbec Compare March 20, 2025 18:00
Copy link
Contributor

✅ Gradle check result for 10cdbec: SUCCESS

Copy link
Collaborator

@jainankitk jainankitk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@finnegancarroll - Few nitpicks, but otherwise this looks great!

Comment on lines +31 to +32
public static final String OS_EXPERIMENTAL_PREFIX = "opensearch.experimental.";
public static final String FEATURE_FLAG_PREFIX = OS_EXPERIMENTAL_PREFIX + "feature.";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
OS_EXPERIMENTAL_PREFIX can be private?
FEATURE_FLAG_PREFIX can be package private for testing?

Comment on lines +246 to +247
if (!featureFlags.containsKey(ff)) return false;
return featureFlags.get(ff);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could this be return featureFlags.getOrDefault(ff, false)?

Comment on lines +255 to +256
for (Setting<Boolean> ff : featureFlags.keySet()) {
if (ff.getKey().equals(featureFlagName)) featureFlags.put(ff, value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially, I was confused why we need to iterate over the keys for putting featureFlag, then I noticed need to compare the setting name, within Setting object that is the key. I am assuming this is done only during the initialization?

}

/**
* Provides feature flag write access and synchronization for test use cases.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying from this comment from @reta about how tests are run:

So this is my understanding of how we do that:

  • we run test suites concurrently by forking JVMs
  • we never run test suites (or tests with same suite) concurrently within same JVM

The static state between tests should not be shared between JVMs but it is possible that we don't clean up properly after some test suites so this problem emerges.

As far as I know there should be no contention between tests modifying feature flags in the static state because within one JVM there is only ever one test running at one time. That means the concurrency primitives here (ReentrantLocks) should not be needed. I'd be in favor of not using locks if they are not necessary because it will only add to confusion about how tests are run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers Search Search query, autocomplete ...etc v3.0.0 Issues and PRs related to version 3.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] FeatureFlags.isEnabled is kinda slow
6 participants