Skip to content

Commit 0692ffc

Browse files
committed
feat: add histogram analytics support in API analytics resource and mapper
1 parent 0a47bc0 commit 0692ffc

File tree

3 files changed

+81
-36
lines changed

3 files changed

+81
-36
lines changed

gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/mapper/ApiAnalyticsMapper.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,28 @@
1515
*/
1616
package io.gravitee.rest.api.management.v2.rest.mapper;
1717

18+
import io.gravitee.apim.core.analytics.model.Aggregation;
19+
import io.gravitee.apim.core.analytics.model.Bucket;
1820
import io.gravitee.apim.core.analytics.model.ResponseStatusOvertime;
21+
import io.gravitee.apim.core.analytics.model.Timestamp;
1922
import io.gravitee.rest.api.management.v2.rest.model.AnalyticTimeRange;
2023
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsAverageConnectionDurationResponse;
2124
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsAverageMessagesPerRequestResponse;
2225
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsRequestsCountResponse;
2326
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsResponseStatusOvertimeResponse;
2427
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsResponseStatusRangesResponse;
28+
import io.gravitee.rest.api.management.v2.rest.model.HistogramAnalytics;
29+
import io.gravitee.rest.api.management.v2.rest.model.HistogramAnalyticsAllOfValues;
30+
import io.gravitee.rest.api.management.v2.rest.model.HistogramTimestamp;
31+
import io.gravitee.rest.api.management.v2.rest.resource.param.ApiAnalyticsParam;
2532
import io.gravitee.rest.api.model.v4.analytics.AverageConnectionDuration;
2633
import io.gravitee.rest.api.model.v4.analytics.AverageMessagesPerRequest;
2734
import io.gravitee.rest.api.model.v4.analytics.RequestsCount;
2835
import io.gravitee.rest.api.model.v4.analytics.ResponseStatusRanges;
36+
import jakarta.validation.Valid;
37+
import java.util.List;
2938
import java.util.Map;
39+
import java.util.stream.Collectors;
3040
import org.mapstruct.Mapper;
3141
import org.mapstruct.Mapping;
3242
import org.mapstruct.factory.Mappers;
@@ -61,4 +71,36 @@ public interface ApiAnalyticsMapper {
6171
AnalyticTimeRange map(ResponseStatusOvertime.TimeRange source);
6272

6373
Map<String, Number> map(Map<String, Long> value);
74+
75+
default HistogramAnalytics mapHistogramAnalytics(List<Bucket> buckets) {
76+
if (buckets == null) {
77+
return null;
78+
}
79+
HistogramAnalytics analytics = new HistogramAnalytics();
80+
analytics.setValues(mapBuckets(buckets));
81+
return analytics;
82+
}
83+
84+
List<@Valid HistogramAnalyticsAllOfValues> mapBuckets(List<Bucket> buckets);
85+
86+
default List<Aggregation> mapAggregations(ApiAnalyticsParam.Aggregations aggregations) {
87+
if (aggregations == null) {
88+
return null;
89+
}
90+
return aggregations
91+
.stream()
92+
.map(a -> new Aggregation(a.getField(), Aggregation.AggregationType.valueOf(a.getType().toUpperCase())))
93+
.collect(Collectors.toList());
94+
}
95+
96+
default HistogramTimestamp map(Timestamp timestamp) {
97+
if (timestamp == null) {
98+
return null;
99+
}
100+
HistogramTimestamp range = new HistogramTimestamp();
101+
range.setFrom(timestamp.getFrom().toEpochMilli());
102+
range.setTo(timestamp.getTo().toEpochMilli());
103+
range.setInterval(timestamp.getInterval().toMillis());
104+
return range;
105+
}
64106
}

gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/api/analytics/ApiAnalyticsResource.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717

1818
import io.gravitee.apim.core.analytics.use_case.SearchAverageConnectionDurationUseCase;
1919
import io.gravitee.apim.core.analytics.use_case.SearchAverageMessagesPerRequestAnalyticsUseCase;
20+
import io.gravitee.apim.core.analytics.use_case.SearchHistogramAnalyticsUseCase;
2021
import io.gravitee.apim.core.analytics.use_case.SearchRequestsCountAnalyticsUseCase;
2122
import io.gravitee.apim.core.analytics.use_case.SearchResponseStatusOverTimeUseCase;
2223
import io.gravitee.apim.core.analytics.use_case.SearchResponseStatusRangesUseCase;
2324
import io.gravitee.apim.core.analytics.use_case.SearchResponseTimeUseCase;
2425
import io.gravitee.rest.api.management.v2.rest.mapper.ApiAnalyticsMapper;
2526
import io.gravitee.rest.api.management.v2.rest.model.AnalyticTimeRange;
27+
import io.gravitee.rest.api.management.v2.rest.model.AnalyticsType;
2628
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsAverageConnectionDurationResponse;
2729
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsAverageMessagesPerRequestResponse;
2830
import io.gravitee.rest.api.management.v2.rest.model.ApiAnalyticsOverPeriodResponse;
@@ -39,10 +41,8 @@
3941
import io.gravitee.rest.api.service.common.GraviteeContext;
4042
import jakarta.inject.Inject;
4143
import jakarta.ws.rs.BeanParam;
42-
import jakarta.ws.rs.Consumes;
4344
import jakarta.ws.rs.GET;
4445
import jakarta.ws.rs.NotFoundException;
45-
import jakarta.ws.rs.POST;
4646
import jakarta.ws.rs.Path;
4747
import jakarta.ws.rs.PathParam;
4848
import jakarta.ws.rs.Produces;
@@ -75,6 +75,9 @@ public class ApiAnalyticsResource extends AbstractResource {
7575
@Inject
7676
private SearchResponseStatusOverTimeUseCase searchResponseStatusOverTimeUseCase;
7777

78+
@Inject
79+
private SearchHistogramAnalyticsUseCase searchHistogramAnalyticsUseCase;
80+
7881
@Path("/requests-count")
7982
@GET
8083
@Produces(MediaType.APPLICATION_JSON)
@@ -188,16 +191,27 @@ public ApiAnalyticsResponseStatusOvertimeResponse getResponseStatusOvertime(@Que
188191
return ApiAnalyticsMapper.INSTANCE.map(result);
189192
}
190193

191-
@POST
194+
@GET
192195
@Produces(MediaType.APPLICATION_JSON)
193-
@Consumes(MediaType.APPLICATION_JSON)
194196
@Permissions({ @Permission(value = RolePermission.API_ANALYTICS, acls = { RolePermissionAction.READ }) })
195197
public ApiAnalyticsResponse performApiAnalytics(
196198
@PathParam("envId") String envId,
197199
@PathParam("apiId") String apiId,
198200
@BeanParam ApiAnalyticsParam apiAnalyticsParam
199201
) {
200-
// TODO: Implement the logic for handling analytics requests
202+
if (apiAnalyticsParam.getType() == AnalyticsType.HISTOGRAM) {
203+
var input = new SearchHistogramAnalyticsUseCase.Input(
204+
apiId,
205+
apiAnalyticsParam.getFrom(),
206+
apiAnalyticsParam.getTo(),
207+
apiAnalyticsParam.getInterval(),
208+
ApiAnalyticsMapper.INSTANCE.mapAggregations(apiAnalyticsParam.getAggregations())
209+
);
210+
var output = searchHistogramAnalyticsUseCase.execute(GraviteeContext.getExecutionContext(), input);
211+
var histogramResponse = ApiAnalyticsMapper.INSTANCE.mapHistogramAnalytics(output.values());
212+
histogramResponse.setTimestamp(ApiAnalyticsMapper.INSTANCE.map(output.timestamp()));
213+
return new ApiAnalyticsResponse(histogramResponse);
214+
}
201215
return new ApiAnalyticsResponse();
202216
}
203217
}

gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/resources/openapi/openapi-apis.yaml

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7688,14 +7688,23 @@ components:
76887688
additionalProperties:
76897689
type: string
76907690
HistogramAnalytics:
7691-
76927691
allOf:
76937692
- $ref: "#/components/schemas/GenericAnalytics"
76947693
- type: object
76957694
properties:
76967695
timestamp:
7697-
type: string
7698-
format: date-time
7696+
type: object
7697+
title: HistogramTimestamp
7698+
properties:
7699+
from:
7700+
type: integer
7701+
format: int64
7702+
to:
7703+
type: integer
7704+
format: int64
7705+
interval:
7706+
type: integer
7707+
format: int64
76997708
values:
77007709
type: array
77017710
items:
@@ -7704,21 +7713,18 @@ components:
77047713
buckets:
77057714
type: array
77067715
items:
7707-
$ref: "#/components/schemas/Bucket"
7716+
type: object
7717+
properties:
7718+
name:
7719+
type: string
7720+
data:
7721+
type: array
7722+
items:
7723+
type: number
77087724
field:
77097725
type: string
77107726
name:
77117727
type: string
7712-
data:
7713-
type: array
7714-
items:
7715-
type: number
7716-
metadata:
7717-
type: object
7718-
additionalProperties:
7719-
type: object
7720-
additionalProperties:
7721-
type: string
77227728
GroupByAnalytics:
77237729
allOf:
77247730
- $ref: "#/components/schemas/GenericAnalytics"
@@ -7735,23 +7741,6 @@ components:
77357741
type: object
77367742
additionalProperties:
77377743
type: string
7738-
Bucket:
7739-
type: object
7740-
properties:
7741-
field:
7742-
type: string
7743-
name:
7744-
type: string
7745-
data:
7746-
type: array
7747-
items:
7748-
type: number
7749-
metadata:
7750-
type: object
7751-
additionalProperties:
7752-
type: object
7753-
additionalProperties:
7754-
type: string
77557744

77567745
# API Health
77577746
HealthCheckLog:

0 commit comments

Comments
 (0)