Skip to content

Commit 6235ffa

Browse files
add get call for sampling configs (#136912)
* add get call for configs * wire in handlers * update comments * update action name --------- Co-authored-by: Keith Massey <[email protected]>
1 parent 6637732 commit 6235ffa

File tree

10 files changed

+1003
-1
lines changed

10 files changed

+1003
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"indices.get_sample_configuration": {
3+
"documentation": {
4+
"url": "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-get-sample-configuration",
5+
"description": "Get sampling configuration for an index or data stream"
6+
},
7+
"stability": "experimental",
8+
"visibility": "public",
9+
"headers": {
10+
"accept": [
11+
"application/json"
12+
]
13+
},
14+
"url": {
15+
"paths": [
16+
{
17+
"path": "/{index}/_sample/config",
18+
"methods": [
19+
"GET"
20+
],
21+
"parts": {
22+
"index": {
23+
"type": "string",
24+
"description": "The name of a data stream or index"
25+
}
26+
}
27+
}
28+
]
29+
},
30+
"params": {
31+
"master_timeout": {
32+
"type": "time",
33+
"description": "Timeout for connection to master node"
34+
}
35+
}
36+
}
37+
}
38+
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
---
2+
setup:
3+
- requires:
4+
cluster_features: [ "random_sampling" ]
5+
reason: requires feature 'random_sampling' to get random samples
6+
7+
---
8+
teardown:
9+
- do:
10+
indices.delete:
11+
index: "*test*"
12+
ignore_unavailable: true
13+
allow_no_indices: true
14+
15+
---
16+
"Get sampling configuration after setting it":
17+
- do:
18+
indices.create:
19+
index: test-get-config-index
20+
body:
21+
settings:
22+
number_of_shards: 1
23+
24+
- do:
25+
indices.put_sample_configuration:
26+
index: test-get-config-index
27+
body:
28+
rate: 0.5
29+
max_samples: 100
30+
max_size: "10mb"
31+
time_to_live: "1h"
32+
33+
- match: { acknowledged: true }
34+
35+
- do:
36+
indices.get_sample_configuration:
37+
index: test-get-config-index
38+
human: true
39+
40+
- match: { configuration.rate: 0.5 }
41+
- match: { configuration.max_samples: 100 }
42+
- match: { configuration.max_size: "10mb" }
43+
- match: { configuration.time_to_live: "1h" }
44+
45+
---
46+
"Get sampling configuration with minimal parameters":
47+
- do:
48+
indices.create:
49+
index: test-minimal-config-index
50+
51+
- do:
52+
indices.put_sample_configuration:
53+
index: test-minimal-config-index
54+
body:
55+
rate: 0.1
56+
57+
- match: { acknowledged: true }
58+
59+
- do:
60+
indices.get_sample_configuration:
61+
index: test-minimal-config-index
62+
human: true
63+
64+
- match: { configuration.rate: 0.1 }
65+
66+
---
67+
"Get sampling configuration with condition":
68+
- do:
69+
indices.create:
70+
index: test-condition-config-index
71+
72+
- do:
73+
indices.put_sample_configuration:
74+
index: test-condition-config-index
75+
body:
76+
rate: 1.0
77+
max_samples: 50
78+
if: "ctx?.field == 'sample_me'"
79+
80+
- match: { acknowledged: true }
81+
82+
- do:
83+
indices.get_sample_configuration:
84+
index: test-condition-config-index
85+
human: true
86+
87+
- match: { configuration.rate: 1.0 }
88+
- match: { configuration.max_samples: 50 }
89+
- match: { configuration.if: "ctx?.field == 'sample_me'" }
90+
91+
---
92+
"Get sampling configuration for non-existent index":
93+
- do:
94+
catch: missing
95+
indices.get_sample_configuration:
96+
index: non-existent-index
97+
98+
---
99+
"Get sampling configuration for index without configuration":
100+
- do:
101+
indices.create:
102+
index: test-no-config-index
103+
104+
- do:
105+
indices.get_sample_configuration:
106+
index: test-no-config-index
107+
human: true
108+
109+
# Should return empty or default configuration
110+
- is_false: test-no-config-index.sampling
111+
112+
---
113+
"Get sampling configuration after update":
114+
- do:
115+
indices.create:
116+
index: test-update-config-index
117+
118+
# Set initial configuration
119+
- do:
120+
indices.put_sample_configuration:
121+
index: test-update-config-index
122+
body:
123+
rate: 0.3
124+
max_samples: 25
125+
126+
- match: { acknowledged: true }
127+
128+
- do:
129+
indices.get_sample_configuration:
130+
index: test-update-config-index
131+
human: true
132+
133+
- match: { configuration.rate: 0.3 }
134+
- match: { configuration.max_samples: 25 }
135+
136+
# Update configuration
137+
- do:
138+
indices.put_sample_configuration:
139+
index: test-update-config-index
140+
body:
141+
rate: 0.8
142+
max_samples: 75
143+
max_size: "5mb"
144+
145+
- match: { acknowledged: true }
146+
147+
# Verify updated configuration
148+
- do:
149+
indices.get_sample_configuration:
150+
index: test-update-config-index
151+
human: true
152+
153+
- match: { configuration.rate: 0.8 }
154+
- match: { configuration.max_samples: 75 }
155+
- match: { configuration.max_size: "5mb" }
156+
157+
---
158+
"Get sampling configuration with master timeout":
159+
- do:
160+
indices.create:
161+
index: test-timeout-config-index
162+
163+
- do:
164+
indices.put_sample_configuration:
165+
index: test-timeout-config-index
166+
body:
167+
rate: 0.7
168+
max_samples: 200
169+
170+
- match: { acknowledged: true }
171+
172+
- do:
173+
indices.get_sample_configuration:
174+
index: test-timeout-config-index
175+
master_timeout: "30s"
176+
human: true
177+
178+
- match: { configuration.rate: 0.7 }
179+
- match: { configuration.max_samples: 200 }
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.action.admin.indices.sampling;
11+
12+
import org.elasticsearch.common.unit.ByteSizeValue;
13+
import org.elasticsearch.core.TimeValue;
14+
import org.elasticsearch.ingest.SamplingService;
15+
import org.elasticsearch.test.ESIntegTestCase;
16+
17+
import static org.hamcrest.Matchers.equalTo;
18+
import static org.hamcrest.Matchers.notNullValue;
19+
import static org.hamcrest.Matchers.nullValue;
20+
21+
public class GetSampleConfigurationActionIT extends ESIntegTestCase {
22+
23+
public void testGetSampleConfiguration() {
24+
assumeTrue("Requires the sampling feature flag to be enabled", SamplingService.RANDOM_SAMPLING_FEATURE_FLAG);
25+
26+
String indexName = randomIdentifier();
27+
createIndex(indexName);
28+
29+
// Create a random sampling configuration
30+
SamplingConfiguration config = randomSamplingConfiguration();
31+
putSamplingConfiguration(indexName, config);
32+
33+
// Get and verify the sampling configuration
34+
assertGetConfigurationMatches(indexName, config);
35+
}
36+
37+
public void testGetSampleConfigurationForNonExistentIndex() {
38+
assumeTrue("Requires the sampling feature flag to be enabled", SamplingService.RANDOM_SAMPLING_FEATURE_FLAG);
39+
40+
String nonExistentIndex = randomIdentifier();
41+
42+
// Try to get configuration for non-existent index
43+
GetSampleConfigurationAction.Request getRequest = new GetSampleConfigurationAction.Request(randomValidTimeValue());
44+
getRequest.indices(nonExistentIndex);
45+
46+
// This should fail - cannot get config for non-existent index
47+
expectThrows(Exception.class, () -> client().execute(GetSampleConfigurationAction.INSTANCE, getRequest).actionGet());
48+
}
49+
50+
public void testGetSampleConfigurationForIndexWithoutConfiguration() {
51+
assumeTrue("Requires the sampling feature flag to be enabled", SamplingService.RANDOM_SAMPLING_FEATURE_FLAG);
52+
53+
String indexName = randomIdentifier();
54+
createIndex(indexName);
55+
56+
// Get configuration for index without any sampling configuration
57+
GetSampleConfigurationAction.Request getRequest = new GetSampleConfigurationAction.Request(randomValidTimeValue());
58+
getRequest.indices(indexName);
59+
60+
GetSampleConfigurationAction.Response response = client().execute(GetSampleConfigurationAction.INSTANCE, getRequest).actionGet();
61+
62+
// Verify response returns null configuration
63+
assertThat("Response should not be null", response, notNullValue());
64+
assertThat("Index name should match", response.getIndex(), equalTo(indexName));
65+
assertThat("Configuration should be null for index without config", response.getConfiguration(), nullValue());
66+
}
67+
68+
public void testGetSampleConfigurationAfterUpdate() {
69+
assumeTrue("Requires the sampling feature flag to be enabled", SamplingService.RANDOM_SAMPLING_FEATURE_FLAG);
70+
71+
String indexName = randomIdentifier();
72+
createIndex(indexName);
73+
74+
// Create initial random configuration
75+
SamplingConfiguration initialConfig = randomSamplingConfiguration();
76+
putSamplingConfiguration(indexName, initialConfig);
77+
78+
// Get initial configuration
79+
assertGetConfigurationMatches(indexName, initialConfig);
80+
81+
// Update with new random configuration
82+
SamplingConfiguration updatedConfig = randomSamplingConfiguration();
83+
putSamplingConfiguration(indexName, updatedConfig);
84+
85+
// Get and verify updated configuration
86+
assertGetConfigurationMatches(indexName, updatedConfig);
87+
}
88+
89+
public void testGetSampleConfigurationPersistsAcrossClusterStateUpdates() {
90+
assumeTrue("Requires the sampling feature flag to be enabled", SamplingService.RANDOM_SAMPLING_FEATURE_FLAG);
91+
92+
String indexName = randomIdentifier();
93+
createIndex(indexName);
94+
95+
// Store random sampling configuration
96+
SamplingConfiguration config = randomSamplingConfiguration();
97+
putSamplingConfiguration(indexName, config);
98+
99+
// Get initial configuration
100+
assertGetConfigurationMatches(indexName, config);
101+
102+
// Trigger cluster state updates by creating additional indices with random names
103+
int numDummyIndices = randomIntBetween(2, 5);
104+
for (int i = 0; i < numDummyIndices; i++) {
105+
createIndex(randomIdentifier());
106+
}
107+
108+
// Get configuration again after cluster state changes and verify it persists
109+
assertGetConfigurationMatches(indexName, config);
110+
}
111+
112+
private SamplingConfiguration randomSamplingConfiguration() {
113+
return new SamplingConfiguration(
114+
randomDoubleBetween(0.1, 1.0, true),
115+
randomBoolean() ? randomIntBetween(1, SamplingConfiguration.MAX_SAMPLES_LIMIT) : null,
116+
randomBoolean() ? ByteSizeValue.ofMb(randomIntBetween(1, 100)) : null,
117+
randomBoolean() ? randomValidTimeValue() : null,
118+
randomBoolean() ? randomAlphaOfLengthBetween(5, 30) : null
119+
);
120+
}
121+
122+
private void putSamplingConfiguration(String indexName, SamplingConfiguration config) {
123+
PutSampleConfigurationAction.Request putRequest = new PutSampleConfigurationAction.Request(
124+
config,
125+
randomValidTimeValue(),
126+
randomValidTimeValue()
127+
);
128+
putRequest.indices(indexName);
129+
client().execute(PutSampleConfigurationAction.INSTANCE, putRequest).actionGet();
130+
ensureGreen();
131+
}
132+
133+
private void assertGetConfigurationMatches(String indexName, SamplingConfiguration expectedConfig) {
134+
GetSampleConfigurationAction.Request getRequest = new GetSampleConfigurationAction.Request(randomValidTimeValue());
135+
getRequest.indices(indexName);
136+
137+
GetSampleConfigurationAction.Response response = client().execute(GetSampleConfigurationAction.INSTANCE, getRequest).actionGet();
138+
139+
assertThat("Response should not be null", response, notNullValue());
140+
assertThat("Index name should match", response.getIndex(), equalTo(indexName));
141+
assertThat("Configuration should match", response.getConfiguration(), equalTo(expectedConfig));
142+
}
143+
144+
private TimeValue randomValidTimeValue() {
145+
return TimeValue.timeValueDays(randomIntBetween(10, 20));
146+
}
147+
}

0 commit comments

Comments
 (0)