Skip to content

Commit b3cc4ef

Browse files
authored
TSDB: Downsampling copies all settings from source to rollup index (#88565)
This PR modified the rollup action so that all index settings are copied from the source index to the rollup index. Relates to #85708
1 parent 2a65683 commit b3cc4ef

File tree

3 files changed

+82
-44
lines changed

3 files changed

+82
-44
lines changed

x-pack/plugin/rollup/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dependencies {
1515
compileOnly project(path: xpackModule('core'))
1616
compileOnly project(path: xpackModule('analytics'))
1717
compileOnly project(path: xpackModule('mapper-aggregate-metric'))
18+
compileOnly project(path: xpackModule('ilm'))
1819
compileOnly project(':modules:data-streams')
1920
testImplementation(testArtifact(project(xpackModule('core'))))
2021
}

x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/v2/TransportRollupAction.java

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.elasticsearch.common.Priority;
3939
import org.elasticsearch.common.bytes.BytesReference;
4040
import org.elasticsearch.common.inject.Inject;
41+
import org.elasticsearch.common.settings.IndexScopedSettings;
42+
import org.elasticsearch.common.settings.Setting;
4143
import org.elasticsearch.common.settings.Settings;
4244
import org.elasticsearch.common.xcontent.XContentHelper;
4345
import org.elasticsearch.index.Index;
@@ -61,7 +63,6 @@
6163
import org.elasticsearch.xpack.core.rollup.action.RollupIndexerAction;
6264

6365
import java.io.IOException;
64-
import java.time.Instant;
6566
import java.util.HashMap;
6667
import java.util.List;
6768
import java.util.Map;
@@ -79,6 +80,7 @@ public class TransportRollupAction extends AcknowledgedTransportMasterNodeAction
7980
private final Client client;
8081
private final ClusterService clusterService;
8182
private final MetadataCreateIndexService metadataCreateIndexService;
83+
private final IndexScopedSettings indexScopedSettings;
8284

8385
/**
8486
* This is the cluster state task executor for cluster state update actions.
@@ -107,7 +109,8 @@ public TransportRollupAction(
107109
ThreadPool threadPool,
108110
MetadataCreateIndexService metadataCreateIndexService,
109111
ActionFilters actionFilters,
110-
IndexNameExpressionResolver indexNameExpressionResolver
112+
IndexNameExpressionResolver indexNameExpressionResolver,
113+
IndexScopedSettings indexScopedSettings
111114
) {
112115
super(
113116
RollupAction.NAME,
@@ -122,6 +125,7 @@ public TransportRollupAction(
122125
this.client = new OriginSettingClient(client, ClientHelper.ROLLUP_ORIGIN);
123126
this.clusterService = clusterService;
124127
this.metadataCreateIndexService = metadataCreateIndexService;
128+
this.indexScopedSettings = indexScopedSettings;
125129
}
126130

127131
@Override
@@ -242,19 +246,20 @@ protected void masterOperation(
242246
client.execute(RollupIndexerAction.INSTANCE, rollupIndexerRequest, ActionListener.wrap(indexerResp -> {
243247
if (indexerResp.isCreated()) {
244248
// 4. Make rollup index read-only and set the correct number of replicas
245-
final Settings settings = Settings.builder()
246-
.put(IndexMetadata.SETTING_BLOCKS_WRITE, true)
247-
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, sourceIndexMetadata.getNumberOfReplicas())
248-
.build();
249-
UpdateSettingsRequest updateSettingsReq = new UpdateSettingsRequest(settings, rollupIndexName);
249+
final Settings.Builder settings = Settings.builder().put(IndexMetadata.SETTING_BLOCKS_WRITE, true);
250+
// Number of replicas had been previously set to 0 to speed up index population
251+
if (sourceIndexMetadata.getNumberOfReplicas() > 0) {
252+
settings.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, sourceIndexMetadata.getNumberOfReplicas());
253+
}
254+
UpdateSettingsRequest updateSettingsReq = new UpdateSettingsRequest(settings.build(), rollupIndexName);
250255
updateSettingsReq.setParentTask(parentTask);
251256
client.admin().indices().updateSettings(updateSettingsReq, ActionListener.wrap(updateSettingsResponse -> {
252257
if (updateSettingsResponse.isAcknowledged()) {
253258
// 5. Refresh rollup index
254259
refreshIndex(rollupIndexName, parentTask, ActionListener.wrap(refreshIndexResponse -> {
255260
if (refreshIndexResponse.getFailedShards() == 0) {
256261
// 6. Mark rollup index as "completed successfully"
257-
updateRollupMetadata(sourceIndexName, rollupIndexName, request, ActionListener.wrap(resp -> {
262+
updateRollupMetadata(rollupIndexName, request, ActionListener.wrap(resp -> {
258263
if (resp.isAcknowledged()) {
259264
// 7. Force-merge the rollup index to a single segment
260265
forceMergeIndex(
@@ -427,42 +432,42 @@ public static String createRollupIndexMapping(
427432
}
428433

429434
/**
430-
* Copy index metadata from the source index to the rollup index.
435+
* Copy index settings from the source index to the rollup index. Settings that
436+
* have already been set in the rollup index will not be overridden.
431437
*/
432438
private IndexMetadata.Builder copyIndexMetadata(IndexMetadata sourceIndexMetadata, IndexMetadata rollupIndexMetadata) {
433-
String sourceIndexName = sourceIndexMetadata.getIndex().getName();
439+
// Copy index settings from the source index, but do not override the settings
440+
// that already have been set in the rollup index
441+
final Settings.Builder targetSettings = Settings.builder().put(rollupIndexMetadata.getSettings());
442+
for (final String key : sourceIndexMetadata.getSettings().keySet()) {
443+
final Setting<?> setting = indexScopedSettings.get(key);
444+
if (setting == null) {
445+
assert indexScopedSettings.isPrivateSetting(key) : "expected [" + key + "] to be private but it was not";
446+
} else if (setting.getProperties().contains(Setting.Property.NotCopyableOnResize)) {
447+
// we leverage the NotCopyableOnResize setting property for rollup, because
448+
// the same rules with resize apply
449+
continue;
450+
}
451+
// do not override settings that have already been set in the rollup index
452+
if (targetSettings.keys().contains(key)) {
453+
continue;
454+
}
455+
targetSettings.copy(key, sourceIndexMetadata.getSettings());
456+
}
434457

435458
/*
436459
* Add the source index name and UUID to the rollup index metadata.
437460
* If the source index is a rollup index, we will add the name and UUID
438461
* of the first index that we initially rolled up.
439462
*/
440-
String originalIndexName = IndexMetadata.INDEX_ROLLUP_SOURCE_NAME.exists(sourceIndexMetadata.getSettings())
441-
? IndexMetadata.INDEX_ROLLUP_SOURCE_NAME.get(sourceIndexMetadata.getSettings())
442-
: sourceIndexName;
443-
String originalIndexUuid = IndexMetadata.INDEX_ROLLUP_SOURCE_UUID.exists(sourceIndexMetadata.getSettings())
444-
? IndexMetadata.INDEX_ROLLUP_SOURCE_UUID.get(sourceIndexMetadata.getSettings())
445-
: sourceIndexMetadata.getIndexUUID();
446-
447-
// Copy time series index settings from original index
448-
List<String> indexRoutingPath = sourceIndexMetadata.getRoutingPaths();
449-
Instant startTime = IndexSettings.TIME_SERIES_START_TIME.get(sourceIndexMetadata.getSettings());
450-
Instant endTime = IndexSettings.TIME_SERIES_END_TIME.get(sourceIndexMetadata.getSettings());
451-
IndexMode indexMode = IndexSettings.MODE.get(sourceIndexMetadata.getSettings());
452-
453-
return IndexMetadata.builder(rollupIndexMetadata)
454-
.settings(
455-
Settings.builder()
456-
.put(rollupIndexMetadata.getSettings())
457-
.put(IndexMetadata.INDEX_ROLLUP_SOURCE_NAME.getKey(), originalIndexName)
458-
.put(IndexMetadata.INDEX_ROLLUP_SOURCE_UUID.getKey(), originalIndexUuid)
459-
.put(IndexMetadata.INDEX_HIDDEN_SETTING.getKey(), sourceIndexMetadata.isHidden())
460-
// Add the time series index settings
461-
.put(IndexSettings.MODE.getKey(), indexMode)
462-
.putList(IndexMetadata.INDEX_ROUTING_PATH.getKey(), indexRoutingPath)
463-
.put(IndexSettings.TIME_SERIES_START_TIME.getKey(), startTime.toString())
464-
.put(IndexSettings.TIME_SERIES_END_TIME.getKey(), endTime.toString())
465-
);
463+
if (IndexMetadata.INDEX_ROLLUP_SOURCE_UUID.exists(sourceIndexMetadata.getSettings()) == false
464+
|| IndexMetadata.INDEX_ROLLUP_SOURCE_NAME.exists(sourceIndexMetadata.getSettings()) == false) {
465+
Index sourceIndex = sourceIndexMetadata.getIndex();
466+
targetSettings.put(IndexMetadata.INDEX_ROLLUP_SOURCE_NAME.getKey(), sourceIndex.getName())
467+
.put(IndexMetadata.INDEX_ROLLUP_SOURCE_UUID.getKey(), sourceIndex.getUUID());
468+
}
469+
470+
return IndexMetadata.builder(rollupIndexMetadata).settings(targetSettings);
466471
}
467472

468473
/**
@@ -524,12 +529,7 @@ public ClusterState execute(ClusterState currentState) throws Exception {
524529
}, ClusterStateTaskConfig.build(Priority.URGENT, request.masterNodeTimeout()), STATE_UPDATE_TASK_EXECUTOR);
525530
}
526531

527-
private void updateRollupMetadata(
528-
String sourceIndexName,
529-
String rollupIndexName,
530-
RollupAction.Request request,
531-
ActionListener<AcknowledgedResponse> listener
532-
) {
532+
private void updateRollupMetadata(String rollupIndexName, RollupAction.Request request, ActionListener<AcknowledgedResponse> listener) {
533533
// 6. Mark rollup index as "completed successfully" ("index.rollup.status": "success")
534534
clusterService.submitStateUpdateTask(
535535
"update-rollup-metadata [" + rollupIndexName + "]",

x-pack/plugin/rollup/src/test/java/org/elasticsearch/xpack/rollup/v2/RollupActionSingleNodeTests.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
1616
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
1717
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
18+
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
1819
import org.elasticsearch.action.admin.indices.template.put.PutComposableIndexTemplateAction;
1920
import org.elasticsearch.action.bulk.BulkItemResponse;
2021
import org.elasticsearch.action.bulk.BulkRequestBuilder;
@@ -58,10 +59,13 @@
5859
import org.elasticsearch.xpack.aggregatemetric.AggregateMetricMapperPlugin;
5960
import org.elasticsearch.xpack.analytics.AnalyticsPlugin;
6061
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
62+
import org.elasticsearch.xpack.core.ilm.LifecycleSettings;
63+
import org.elasticsearch.xpack.core.ilm.RolloverAction;
6164
import org.elasticsearch.xpack.core.rollup.ConfigTestHelpers;
6265
import org.elasticsearch.xpack.core.rollup.RollupActionConfig;
6366
import org.elasticsearch.xpack.core.rollup.action.RollupAction;
6467
import org.elasticsearch.xpack.core.rollup.action.RollupActionRequestValidationException;
68+
import org.elasticsearch.xpack.ilm.IndexLifecycle;
6569
import org.elasticsearch.xpack.rollup.Rollup;
6670
import org.junit.Before;
6771

@@ -104,7 +108,8 @@ protected Collection<Class<? extends Plugin>> getPlugins() {
104108
Rollup.class,
105109
AnalyticsPlugin.class,
106110
AggregateMetricMapperPlugin.class,
107-
DataStreamsPlugin.class
111+
DataStreamsPlugin.class,
112+
IndexLifecycle.class
108113
);
109114
}
110115

@@ -115,7 +120,7 @@ public void setup() {
115120
startTime = randomLongBetween(946769284000L, 1607470084000L); // random date between 2000-2020
116121
docCount = randomIntBetween(10, 9000);
117122
numOfShards = randomIntBetween(1, 4);
118-
numOfReplicas = 0; // Since this is a single node, we cannot have replicas
123+
numOfReplicas = randomIntBetween(0, 3);
119124

120125
// Values for keyword dimensions
121126
dimensionValues = new ArrayList<>(MAX_DIM_VALUES);
@@ -170,6 +175,38 @@ public void testRollupIndex() throws IOException {
170175
assertRollupIndex(sourceIndex, rollupIndex, config);
171176
}
172177

178+
public void testCopyIndexSettings() throws IOException {
179+
Settings settings = Settings.builder()
180+
.put(LifecycleSettings.LIFECYCLE_NAME, randomAlphaOfLength(5))
181+
.put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS_SETTING.getKey(), randomAlphaOfLength(5))
182+
.put(LifecycleSettings.LIFECYCLE_PARSE_ORIGINATION_DATE_SETTING.getKey(), randomBoolean())
183+
.build();
184+
logger.info("Updating index [{}] with settings [{}]", sourceIndex, settings);
185+
186+
var updateSettingsReq = new UpdateSettingsRequest(settings, sourceIndex);
187+
var r = client().admin().indices().updateSettings(updateSettingsReq).actionGet();
188+
assertTrue("Update settings not acked", r.isAcknowledged());
189+
190+
RollupActionConfig config = new RollupActionConfig(randomInterval());
191+
SourceSupplier sourceSupplier = () -> {
192+
String ts = randomDateForInterval(config.getInterval());
193+
return XContentFactory.jsonBuilder()
194+
.startObject()
195+
.field(FIELD_TIMESTAMP, ts)
196+
.field(FIELD_DIMENSION_1, randomFrom(dimensionValues))
197+
.field(FIELD_NUMERIC_1, randomInt())
198+
.endObject();
199+
};
200+
bulkIndex(sourceSupplier);
201+
prepareSourceIndex(sourceIndex);
202+
rollup(sourceIndex, rollupIndex, config);
203+
204+
GetIndexResponse indexSettingsResp = client().admin().indices().prepareGetIndex().addIndices(rollupIndex).get();
205+
for (String key : settings.keySet()) {
206+
assertEquals(settings.get(key), indexSettingsResp.getSetting(rollupIndex, key));
207+
}
208+
}
209+
173210
public void testNullSourceIndexName() {
174211
RollupActionConfig config = new RollupActionConfig(randomInterval());
175212
ActionRequestValidationException exception = expectThrows(

0 commit comments

Comments
 (0)