Skip to content

Commit d4f30d8

Browse files
committed
fix metrics for serverless
1 parent bbaa3a7 commit d4f30d8

File tree

5 files changed

+66
-21
lines changed

5 files changed

+66
-21
lines changed

modules/repository-gcs/src/internalClusterTest/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobStoreRepositoryTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public TestGoogleCloudStoragePlugin(Settings settings) {
229229
}
230230

231231
@Override
232-
protected GoogleCloudStorageService createStorageService() {
232+
protected GoogleCloudStorageService createStorageService(boolean isServerless) {
233233
return new GoogleCloudStorageService() {
234234
@Override
235235
StorageOptions createStorageOptions(

modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcsRepositoryStatsCollector.java

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121

2222
import java.io.IOException;
2323
import java.util.EnumMap;
24+
import java.util.HashMap;
2425
import java.util.Map;
2526
import java.util.concurrent.atomic.LongAdder;
2627
import java.util.function.LongSupplier;
2728
import java.util.function.Supplier;
28-
import java.util.stream.Collectors;
2929

3030
/**
3131
* Stats collector class that performs metrics initialization and propagation through GCS client
@@ -56,7 +56,7 @@ public class GcsRepositoryStatsCollector {
5656
/**
5757
* Track operations for billing and REST API
5858
*/
59-
private final EnumMap<StorageOperation, OpsCollector> restMetering;
59+
private final EnumMap<OperationPurpose, EnumMap<StorageOperation, OpsCollector>> restMetering;
6060
/**
6161
* Telemetry (APM)
6262
*/
@@ -74,9 +74,13 @@ public class GcsRepositoryStatsCollector {
7474
GcsRepositoryStatsCollector(LongSupplier timer, RepositoryMetadata metadata, RepositoriesMetrics repositoriesMetrics) {
7575
this.timer = timer;
7676
this.telemetry = repositoriesMetrics;
77-
this.restMetering = new EnumMap<>(StorageOperation.class);
78-
for (var op : StorageOperation.values()) {
79-
restMetering.put(op, new OpsCollector(new LongAdder(), new LongAdder()));
77+
this.restMetering = new EnumMap<>(OperationPurpose.class);
78+
for (var purpose : OperationPurpose.values()) {
79+
var operationsMap = new EnumMap<StorageOperation, OpsCollector>(StorageOperation.class);
80+
for (var op : StorageOperation.values()) {
81+
operationsMap.put(op, new OpsCollector(new LongAdder(), new LongAdder()));
82+
}
83+
restMetering.put(purpose, operationsMap);
8084
}
8185
this.telemetryAttributes = new EnumMap<>(OperationPurpose.class);
8286
if (repositoriesMetrics != RepositoriesMetrics.NOOP) {
@@ -202,10 +206,11 @@ private void collect(OperationStats stats) {
202206
if (stats.reqAtt == 0) {
203207
return; // nothing happened
204208
}
205-
var op = stats.operation;
209+
var purpose = stats.purpose;
210+
var operation = stats.operation;
206211
var opOk = 0;
207212
var opErr = 0;
208-
switch (op) {
213+
switch (operation) {
209214
case GET, LIST -> {
210215
opOk = stats.reqAtt - stats.reqErr + stats.reqBillableErr;
211216
opErr = stats.reqBillableErr;
@@ -216,7 +221,8 @@ private void collect(OperationStats stats) {
216221
}
217222
}
218223
if (opOk > 0) {
219-
var opStats = restMetering.get(op);
224+
var opStats = restMetering.get(purpose).get(operation);
225+
assert opStats != null;
220226
opStats.operations.add(opOk);
221227
opStats.requests.add(stats.reqAtt - stats.reqErr + stats.reqBillableErr);
222228
}
@@ -236,14 +242,37 @@ private void collect(OperationStats stats) {
236242
}
237243
}
238244

239-
public Map<String, BlobStoreActionStats> operationsStats() {
240-
return restMetering.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().key, e -> {
241-
var ops = e.getValue().operations.sum();
242-
// TODO this test assumes requests, but need operations, azure does not like it
243-
// org.elasticsearch.repositories.blobstore.ESMockAPIBasedRepositoryIntegTestCase.testRequestStats
244-
// var reqs = e.getValue().requests.sum();
245-
return new BlobStoreActionStats(ops, ops);
246-
}));
245+
public Map<String, BlobStoreActionStats> operationsStats(boolean isServerless) {
246+
var out = new HashMap<String, BlobStoreActionStats>();
247+
if (isServerless) {
248+
// Map<'Purpose_Operation', <operations, requests>
249+
for (var purposeKv : restMetering.entrySet()) {
250+
for (var operationKv : restMetering.get(purposeKv.getKey()).entrySet()) {
251+
var stat = operationKv.getValue();
252+
var ops = stat.operations.sum();
253+
var req = stat.requests.sum();
254+
out.put(purposeKv.getKey() + "_" + operationKv.getKey(), new BlobStoreActionStats(ops, req));
255+
}
256+
}
257+
} else {
258+
// Map<'Operation', <operations, requests>
259+
for (var purposeKv : restMetering.entrySet()) {
260+
for (var operationKv : purposeKv.getValue().entrySet()) {
261+
out.compute(operationKv.getKey().key(), (k, v) -> {
262+
var stat = operationKv.getValue();
263+
var ops = stat.operations.sum();
264+
// TODO update map with (ops,req) when azure ready
265+
// var req = stat.requests.sum();
266+
if (v == null) {
267+
return new BlobStoreActionStats(ops, ops);
268+
} else {
269+
return new BlobStoreActionStats(v.operations() + ops, v.operations() + ops);
270+
}
271+
});
272+
}
273+
}
274+
}
275+
return out;
247276
}
248277

249278
record OpsCollector(LongAdder operations, LongAdder requests) {}

modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ private static String buildKey(String keyPath, String s) {
629629

630630
@Override
631631
public Map<String, BlobStoreActionStats> stats() {
632-
return statsCollector.operationsStats();
632+
return statsCollector.operationsStats(storageService.isServerless());
633633
}
634634

635635
private static final class WritableBlobChannel implements WritableByteChannel {

modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStoragePlugin.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.repositories.gcs;
1111

12+
import org.elasticsearch.cluster.node.DiscoveryNode;
1213
import org.elasticsearch.cluster.service.ClusterService;
1314
import org.elasticsearch.common.settings.Setting;
1415
import org.elasticsearch.common.settings.Settings;
@@ -34,14 +35,15 @@ public class GoogleCloudStoragePlugin extends Plugin implements RepositoryPlugin
3435

3536
@SuppressWarnings("this-escape")
3637
public GoogleCloudStoragePlugin(final Settings settings) {
37-
this.storageService = createStorageService();
38+
var isServerless = settings.getAsBoolean(DiscoveryNode.STATELESS_ENABLED_SETTING_NAME, false);
39+
this.storageService = createStorageService(isServerless);
3840
// eagerly load client settings so that secure settings are readable (not closed)
3941
reload(settings);
4042
}
4143

4244
// overridable for tests
43-
protected GoogleCloudStorageService createStorageService() {
44-
return new GoogleCloudStorageService();
45+
protected GoogleCloudStorageService createStorageService(boolean isServerless) {
46+
return new GoogleCloudStorageService(isServerless);
4547
}
4648

4749
@Override

modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ public class GoogleCloudStorageService {
5555

5656
private volatile Map<String, GoogleCloudStorageClientSettings> clientSettings = emptyMap();
5757

58+
private final boolean isServerless;
59+
60+
public GoogleCloudStorageService() {
61+
this.isServerless = false;
62+
}
63+
64+
public GoogleCloudStorageService(boolean isServerless) {
65+
this.isServerless = isServerless;
66+
}
67+
68+
public boolean isServerless() {
69+
return isServerless;
70+
}
71+
5872
private record ClientKey(String repositoryName) {}
5973

6074
/**

0 commit comments

Comments
 (0)