This is an automated email from the ASF dual-hosted git repository.

SvenO3 pushed a commit to branch 
4633-move-dataset-count-display-into-dataset-overview
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit f0fa876af3d488073f80935ab69143baf0095224
Author: Sven Oehler <[email protected]>
AuthorDate: Wed Jun 24 15:07:08 2026 +0200

    Update measurement count endpoint
---
 .../impl/datalake/DataLakeMeasureResource.java     | 59 +++++++++++++++-------
 .../src/lib/apis/datalake-rest.service.ts          | 16 +++---
 .../datalake-configuration.component.ts            | 38 +++++++-------
 3 files changed, 68 insertions(+), 45 deletions(-)

diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
index 57dfb7553e..166b3dd4be 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
@@ -29,9 +29,9 @@ import 
org.apache.streampipes.storage.api.explorer.IChartStorage;
 
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.prepost.PostFilter;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -44,7 +44,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 
 @RestController
@@ -80,29 +79,53 @@ public class DataLakeMeasureResource extends 
AbstractDataLakeResource {
   }
 
   /**
-   * Handles HTTP GET requests to retrieve the entry counts of specified
-   * measurements.
+   * Handles HTTP GET requests to retrieve the entry count of a specified
+   * measurement.
    *
-   * @param measurementNames A list of measurement names to return the count.
-   * @return A ResponseEntity containing a map of measurement names and their
-   *         corresponding entry counts.
+   * @param elementId The measurement id to return the count for.
+   * @return The entry count of the measurement.
    */
-  @Operation(summary = "Retrieve measurement counts", description = "Retrieves 
the entry counts for the specified measurements from the data lake.")
-  @GetMapping(path = "/count", produces = MediaType.APPLICATION_JSON_VALUE)
-  @PreAuthorize("this.hasReadAuthority()")
-  @PostFilter("this.checkPermissionByName(filterObject.key, 'READ')")
-  public Map<String, Integer> getEntryCountsOfMeasurements(
-      @Parameter(description = "A list of measurement names to return the 
count.") @RequestParam(value = "measurementNames") List<String> 
measurementNames,
-      @Parameter(description = "The number of days from today where the count 
should start") @RequestParam(value = "daysBack", defaultValue = "-1") int 
daysBack) {
+  @Operation(
+      summary = "Retrieve measurement count",
+      description = "Retrieves the entry count for the specified measurement 
from the data lake."
+  )
+  @GetMapping(path = "{id}/count", produces = MediaType.APPLICATION_JSON_VALUE)
+  @PreAuthorize("this.hasReadAuthority() and hasPermission(#elementId, 
'READ')")
+  public ResponseEntity<?> getEntryCountOfMeasurement(
+      @Parameter(description = "The measurement id to return the count for.")
+      @PathVariable("id") String elementId,
+      @Parameter(description = "The number of days from today where the count 
should start")
+      @RequestParam(value = "daysBack", defaultValue = "-1") int daysBack) {
+    var measure = this.dataLakeMeasureManagement.getById(elementId);
+    if (Objects.isNull(measure)) {
+      return notFound();
+    }
+
     var allMeasurements = this.dataLakeMeasureManagement.getAllMeasurements();
-    var result = new DataExplorerDispatcher()
+    return ok(new DataExplorerDispatcher()
         .getDataExplorerManager()
         .getMeasurementCounter(
             allMeasurements,
-            measurementNames,
+            List.of(measure.getMeasureName()),
             daysBack)
-        .countMeasurementSizes();
-    return result;
+        .countMeasurementSizes()
+        .getOrDefault(measure.getMeasureName(), 0));
+  }
+
+  @Operation(
+      summary = "Deprecated measurement count endpoint",
+      description = "Use /api/v4/datalake/measure/{id}/count instead.",
+      deprecated = true
+  )
+  @GetMapping(path = "/count", produces = MediaType.APPLICATION_JSON_VALUE)
+  @PreAuthorize("this.hasReadAuthority()")
+  public ResponseEntity<?> getDeprecatedEntryCountOfMeasurement() {
+    return ResponseEntity
+        .status(HttpStatus.GONE)
+        .body(SpLogMessage.warn(
+            "Deprecated endpoint",
+            "Use /api/v4/datalake/measure/{id}/count instead."
+        ));
   }
 
   @GetMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
 
b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
index fb2ccafeff..8ab764a7ea 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
@@ -64,18 +64,18 @@ export class DatalakeRestService {
         return this.baseUrl + '/api/v4/datalake/import';
     }
 
-    getMeasurementEntryCounts(
-        measurementNames: string[],
+    getMeasurementEntryCount(
+        measurementId: string,
         daysBack = -1,
-    ): Observable<Record<string, number>> {
-        return this.http
-            .get(`${this.dataLakeMeasureUrl}/count`, {
+    ): Observable<number> {
+        return this.http.get<number>(
+            
`${this.dataLakeMeasureUrl}/${encodeURIComponent(measurementId)}/count`,
+            {
                 params: {
-                    measurementNames,
                     daysBack,
                 },
-            })
-            .pipe(map(r => r as Record<string, number>));
+            },
+        );
     }
 
     getAllMeasurementSeries(): Observable<DataLakeMeasure[]> {
diff --git 
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
 
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
index cf53cd6441..b98ac2278a 100644
--- 
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
+++ 
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
@@ -91,7 +91,7 @@ import { MatProgressSpinner } from 
'@angular/material/progress-spinner';
 import { DatePipe, DecimalPipe, NgStyle } from '@angular/common';
 import { StyleDirective } from '@ngbracket/ngx-layout/extended';
 import { MatMenuItem } from '@angular/material/menu';
-import { Subscription } from 'rxjs';
+import { forkJoin, Subscription } from 'rxjs';
 
 @Component({
     selector: 'sp-datalake-configuration',
@@ -436,7 +436,7 @@ export class DatalakeConfigurationComponent
     }
 
     receiveTotalMeasurementSize(entry: DataLakeConfigurationEntry): void {
-        this.queryEntryCounts([entry.name], 'eventsTotal');
+        this.queryEntryCounts([entry], 'eventsTotal');
     }
 
     receiveMeasurementSizes(pageIndex: number): void {
@@ -444,8 +444,7 @@ export class DatalakeConfigurationComponent
         const end = start + this.pageSize;
         const measurements = this.filteredMeasurements
             .slice(start, end)
-            .filter(m => m.eventsLatest === -1)
-            .map(m => m.name);
+            .filter(m => m.eventsLatest === -1);
         if (measurements.length > 0) {
             this.queryEntryCounts(measurements, 'eventsLatest', 7);
         }
@@ -489,33 +488,34 @@ export class DatalakeConfigurationComponent
     }
 
     queryEntryCounts(
-        measurements: string[],
+        measurements: DataLakeConfigurationEntry[],
         targetField: string,
         daysBack = -1,
     ): void {
         this.applyLoadingStatus(measurements, targetField, true);
-        this.datalakeRestService
-            .getMeasurementEntryCounts(measurements, daysBack)
-            .subscribe(res => {
-                this.applyLoadingStatus(measurements, targetField, false);
-                this.availableMeasurements.forEach(m => {
-                    if (res[m.name] !== undefined) {
-                        m[targetField] = res[m.name];
-                    }
-                });
+        forkJoin(
+            measurements.map(measurement =>
+                this.datalakeRestService.getMeasurementEntryCount(
+                    measurement.elementId,
+                    daysBack,
+                ),
+            ),
+        ).subscribe(res => {
+            this.applyLoadingStatus(measurements, targetField, false);
+            measurements.forEach((measurement, index) => {
+                measurement[targetField] = res[index];
             });
+        });
     }
 
     applyLoadingStatus(
-        measurements: string[],
+        measurements: DataLakeConfigurationEntry[],
         targetField: string,
         status: boolean,
     ): void {
         const loadingField = targetField + 'Loading';
-        this.availableMeasurements.forEach(m => {
-            if (measurements.includes(m.name)) {
-                m[loadingField] = status;
-            }
+        measurements.forEach(measurement => {
+            measurement[loadingField] = status;
         });
     }
 

Reply via email to