2121
2222import java .io .IOException ;
2323import java .util .EnumMap ;
24+ import java .util .HashMap ;
2425import java .util .Map ;
2526import java .util .concurrent .atomic .LongAdder ;
2627import java .util .function .LongSupplier ;
2728import 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 ) {}
0 commit comments