|
38 | 38 | import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage; |
39 | 39 |
|
40 | 40 | import org.opensearch.action.ActionRunnable; |
| 41 | +import org.opensearch.action.admin.indices.forcemerge.ForceMergeResponse; |
41 | 42 | import org.opensearch.action.support.PlainActionFuture; |
| 43 | +import org.opensearch.cluster.metadata.IndexMetadata; |
42 | 44 | import org.opensearch.cluster.metadata.RepositoryMetadata; |
43 | 45 | import org.opensearch.cluster.service.ClusterService; |
44 | 46 | import org.opensearch.common.SuppressForbidden; |
|
57 | 59 | import org.opensearch.indices.recovery.RecoverySettings; |
58 | 60 | import org.opensearch.plugins.Plugin; |
59 | 61 | import org.opensearch.repositories.RepositoriesService; |
| 62 | +import org.opensearch.repositories.Repository; |
60 | 63 | import org.opensearch.repositories.RepositoryData; |
| 64 | +import org.opensearch.repositories.RepositoryMissingException; |
| 65 | +import org.opensearch.repositories.RepositoryStats; |
61 | 66 | import org.opensearch.repositories.blobstore.BlobStoreRepository; |
62 | 67 | import org.opensearch.repositories.blobstore.OpenSearchMockAPIBasedRepositoryIntegTestCase; |
63 | 68 | import org.opensearch.repositories.s3.utils.AwsRequestSigner; |
64 | 69 | import org.opensearch.snapshots.SnapshotId; |
65 | 70 | import org.opensearch.snapshots.SnapshotsService; |
66 | 71 | import org.opensearch.snapshots.mockstore.BlobStoreWrapper; |
| 72 | +import org.opensearch.test.BackgroundIndexer; |
67 | 73 | import org.opensearch.test.OpenSearchIntegTestCase; |
68 | 74 | import org.opensearch.threadpool.ThreadPool; |
69 | 75 |
|
|
73 | 79 | import java.util.ArrayList; |
74 | 80 | import java.util.Collection; |
75 | 81 | import java.util.Collections; |
| 82 | +import java.util.HashMap; |
76 | 83 | import java.util.List; |
77 | 84 | import java.util.Map; |
| 85 | +import java.util.Objects; |
| 86 | +import java.util.stream.StreamSupport; |
78 | 87 |
|
79 | 88 | import fixture.s3.S3HttpHandler; |
80 | 89 |
|
| 90 | +import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked; |
| 91 | +import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertHitCount; |
81 | 92 | import static org.hamcrest.Matchers.containsString; |
| 93 | +import static org.hamcrest.Matchers.equalTo; |
82 | 94 | import static org.hamcrest.Matchers.greaterThan; |
83 | 95 | import static org.hamcrest.Matchers.lessThan; |
84 | 96 |
|
@@ -216,6 +228,67 @@ public void testEnforcedCooldownPeriod() throws IOException { |
216 | 228 | assertThat(repository.threadPool().relativeTimeInNanos() - beforeFastDelete, lessThan(TEST_COOLDOWN_PERIOD.getNanos())); |
217 | 229 | } |
218 | 230 |
|
| 231 | + @AwaitsFix(bugUrl = "https://github.com/opensearch-project/OpenSearch/issues/10735") |
| 232 | + @Override |
| 233 | + public void testRequestStats() throws Exception { |
| 234 | + final String repository = createRepository(randomName()); |
| 235 | + final String index = "index-no-merges"; |
| 236 | + createIndex( |
| 237 | + index, |
| 238 | + Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1).put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0).build() |
| 239 | + ); |
| 240 | + |
| 241 | + final long nbDocs = randomLongBetween(10_000L, 20_000L); |
| 242 | + try (BackgroundIndexer indexer = new BackgroundIndexer(index, "_doc", client(), (int) nbDocs)) { |
| 243 | + waitForDocs(nbDocs, indexer); |
| 244 | + } |
| 245 | + |
| 246 | + flushAndRefresh(index); |
| 247 | + ForceMergeResponse forceMerge = client().admin().indices().prepareForceMerge(index).setFlush(true).setMaxNumSegments(1).get(); |
| 248 | + assertThat(forceMerge.getSuccessfulShards(), equalTo(1)); |
| 249 | + assertHitCount(client().prepareSearch(index).setSize(0).setTrackTotalHits(true).get(), nbDocs); |
| 250 | + |
| 251 | + final String snapshot = "snapshot"; |
| 252 | + assertSuccessfulSnapshot( |
| 253 | + client().admin().cluster().prepareCreateSnapshot(repository, snapshot).setWaitForCompletion(true).setIndices(index) |
| 254 | + ); |
| 255 | + |
| 256 | + assertAcked(client().admin().indices().prepareDelete(index)); |
| 257 | + |
| 258 | + assertSuccessfulRestore(client().admin().cluster().prepareRestoreSnapshot(repository, snapshot).setWaitForCompletion(true)); |
| 259 | + ensureGreen(index); |
| 260 | + assertHitCount(client().prepareSearch(index).setSize(0).setTrackTotalHits(true).get(), nbDocs); |
| 261 | + |
| 262 | + assertAcked(client().admin().cluster().prepareDeleteSnapshot(repository, snapshot).get()); |
| 263 | + |
| 264 | + final RepositoryStats repositoryStats = StreamSupport.stream( |
| 265 | + internalCluster().getInstances(RepositoriesService.class).spliterator(), |
| 266 | + false |
| 267 | + ).map(repositoriesService -> { |
| 268 | + try { |
| 269 | + return repositoriesService.repository(repository); |
| 270 | + } catch (RepositoryMissingException e) { |
| 271 | + return null; |
| 272 | + } |
| 273 | + }).filter(Objects::nonNull).map(Repository::stats).reduce(RepositoryStats::merge).get(); |
| 274 | + |
| 275 | + Map<BlobStore.Metric, Map<String, Long>> extendedStats = repositoryStats.extendedStats; |
| 276 | + Map<String, Long> aggregatedStats = new HashMap<>(); |
| 277 | + extendedStats.forEach((k, v) -> { |
| 278 | + if (k == BlobStore.Metric.RETRY_COUNT || k == BlobStore.Metric.REQUEST_SUCCESS || k == BlobStore.Metric.REQUEST_FAILURE) { |
| 279 | + for (Map.Entry<String, Long> entry : v.entrySet()) { |
| 280 | + aggregatedStats.merge(entry.getKey(), entry.getValue(), Math::addExact); |
| 281 | + } |
| 282 | + } |
| 283 | + |
| 284 | + }); |
| 285 | + final Map<String, Long> mockCalls = getMockRequestCounts(); |
| 286 | + |
| 287 | + String assertionErrorMsg = String.format("SDK sent [%s] calls and handler measured [%s] calls", aggregatedStats, mockCalls); |
| 288 | + |
| 289 | + assertEquals(assertionErrorMsg, mockCalls, aggregatedStats); |
| 290 | + } |
| 291 | + |
219 | 292 | /** |
220 | 293 | * S3RepositoryPlugin that allows to disable chunked encoding and to set a low threshold between single upload and multipart upload. |
221 | 294 | */ |
@@ -327,6 +400,8 @@ public void maybeTrack(final String request, Headers requestHeaders) { |
327 | 400 | trackRequest("PutMultipartObject"); |
328 | 401 | } else if (Regex.simpleMatch("PUT /*/*", request)) { |
329 | 402 | trackRequest("PutObject"); |
| 403 | + } else if (Regex.simpleMatch("POST /*?delete*", request)) { |
| 404 | + trackRequest("DeleteObjects"); |
330 | 405 | } |
331 | 406 | } |
332 | 407 |
|
|
0 commit comments